From 1ecac41ed45b658971871d9df09006f2a99464ec Mon Sep 17 00:00:00 2001 From: FrederikBaerentsen Date: Wed, 27 Nov 2024 16:45:03 +0100 Subject: [PATCH] Added 2017/18 part 1 --- 2017/18/18.md | 63 +++++++++++++++++++++++++++++++++++++++++- 2017/18/solution.py | 67 ++++++++++++++++++++------------------------- 2 files changed, 92 insertions(+), 38 deletions(-) diff --git a/2017/18/18.md b/2017/18/18.md index ff9eaa8..bd866bf 100644 --- a/2017/18/18.md +++ b/2017/18/18.md @@ -74,6 +74,67 @@ last sound played is `4`. recently played sound) the *first* time a `rcv` instruction is executed with a non-zero value? -To begin, [get your puzzle input](18/input). +Your puzzle answer was `8600`. + +The first half of this puzzle is complete! It provides one gold star: \* + +## \-\-- Part Two \-\-- {#part2} + +As you congratulate yourself for a job well done, you notice that the +documentation has been on the back of the tablet this entire time. While +you actually got most of the instructions correct, there are a few key +differences. This assembly code isn\'t about sound at all - it\'s meant +to be run *twice at the same time*. + +Each running copy of the program has its own set of registers and +follows the code independently - in fact, the programs don\'t even +necessarily run at the same speed. To coordinate, they use the *send* +(`snd`) and *receive* (`rcv`) instructions: + +- `snd X` *sends* the value of `X` to the other program. These values + wait in a queue until that program is ready to receive them. Each + program has its own message queue, so a program can never receive a + message it sent. +- `rcv X` *receives* the next value and stores it in register `X`. If + no values are in the queue, the program *waits for a value to be + sent to it*. Programs do not continue to the next instruction until + they have received a value. Values are received in the order they + are sent. + +Each program also has its own *program ID* (one `0` and the other `1`); +the register `p` should begin with this value. + +For example: + + snd 1 + snd 2 + snd p + rcv a + rcv b + rcv c + rcv d + +Both programs begin by sending three values to the other. Program `0` +sends `1, 2, 0`; program `1` sends `1, 2, 1`. Then, each program +receives a value (both `1`) and stores it in `a`, receives another value +(both `2`) and stores it in `b`, and then each receives the program ID +of the other program (program `0` receives `1`; program `1` receives +`0`) and stores it in `c`. Each program now sees a different value in +its own copy of register `c`. + +Finally, both programs try to `rcv` a *fourth* time, but no data is +waiting for either of them, and they reach a *deadlock*. When this +happens, both programs terminate. + +It should be noted that it would be equally valid for the programs to +run at different speeds; for example, program `0` might have sent all +three values and then stopped at the first `rcv` before program `1` +executed even its first instruction. + +Once both of your programs have terminated (regardless of what caused +them to do so), *how many times did program `1` send a value*? Answer: + +Although it hasn\'t changed, you can still [get your puzzle +input](18/input). diff --git a/2017/18/solution.py b/2017/18/solution.py index d2d0663..3748389 100644 --- a/2017/18/solution.py +++ b/2017/18/solution.py @@ -4,7 +4,7 @@ from pprint import pprint sys.path.insert(0, '../../') from fred import list2int -input_f = 'test' +input_f = 'input' part = 1 ######################################### @@ -25,9 +25,20 @@ def parse_input(input_str): return None +def sets_return(x): + if x in Sets: + value = Sets[x] + if isinstance(value, str) and not x.lstrip('-').isdigit(): + return sets_return(value) + return value + elif x.isdigit() or x.lstrip('-').isdigit(): + return int(x) + else: + return None + instructions = [] -sets = {} +Sets = {} last_sound = 0 @@ -40,63 +51,45 @@ if part == 1: while True: i = instructions[x] - print(i) + + if isinstance(i[1], str): + if i[1] not in Sets: + Sets[i[1]] = 0 if i[0] == 'set': - if isinstance(i[2], str): - sets[i[1]] = int(i[2]) - else: - sets[i[1]] = int(sets[i[2]]) + Sets[i[1]] = int(sets_return(i[2])) x += 1 elif i[0] == 'add': - sets[i[1]] = int(sets[i[1]]) + int(i[2]) + Sets[i[1]] += sets_return(i[2]) x += 1 elif i[0] == 'mul': - if i[2] in sets: - sets[i[1]] = int(sets[i[1]]) * int(sets[i[2]]) - else: - sets[i[1]] = int(sets[i[1]]) * int(i[2]) + Sets[i[1]] *= sets_return(i[2]) x += 1 elif i[0] == 'mod': - sets[i[1]] = int(sets[i[1]]) % int(i[2]) + Sets[i[1]] %= sets_return(i[2]) x += 1 elif i[0] == 'snd': - last_sound = sets[i[1]] + last_sound = sets_return(i[1]) x += 1 elif i[0] == 'rcv': - if sets[i[1]] != 0: - sets[i[1]] = int(sets[i[1]]) - x += 1 - else: - print('skipped') + if sets_return(i[1]) != 0: + Sets[i[1]] = sets_return(i[1]) + print(last_sound) + exit() x += 1 - elif i[0] == 'jgz': #this is the one that fails - if isinstance(i[2], str): - if sets[i[1]] > 0: - - x += int(sets[i[2]]) - else: - x += int(i[2]) + elif i[0] == 'jgz': + if sets_return(i[1]) > 0: + x += sets_return(i[2]) else: x += 1 - - - - - print(x,sets,last_sound) - input() - #print(programs) - #print(instructions) - #print(len(instructions)) - - #for idx,i in enumerate(instructions): +