diff --git a/2017/18/18.md b/2017/18/18.md index bd866bf..1b9971f 100644 --- a/2017/18/18.md +++ b/2017/18/18.md @@ -76,8 +76,6 @@ with a non-zero value? 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 @@ -134,7 +132,13 @@ 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: +Your puzzle answer was `7239`. -Although it hasn\'t changed, you can still [get your puzzle +Both parts of this puzzle are complete! They provide two gold stars: +\*\* + +At this point, you should [return to your Advent calendar](/2017) and +try another puzzle. + +If you still want to see it, you can [get your puzzle input](18/input). diff --git a/2017/18/solution.py b/2017/18/solution.py index 3748389..45cd659 100644 --- a/2017/18/solution.py +++ b/2017/18/solution.py @@ -96,7 +96,99 @@ if part == 1: ######################################### # # # Part 2 # -# # +# in seperate file # ######################################### +def parse_input(input_str): + pattern = r"^([a-zA-Z]{3})\s{1}(\w)?\s?(-?\w+)$" + + match = re.match(pattern, input_str) + if match: + if match.group(2): + return match.group(1),match.group(2),match.group(3) + else: + return match.group(1),match.group(3) + return None + +def sets_1_return(x): + if x in Sets_1: + value = Sets_1[x] + if isinstance(value, str) and not x.lstrip('-').isdigit(): + return sets_1_return(value) + return value + elif x.isdigit() or x.lstrip('-').isdigit(): + return int(x) + else: + return None + +def sets_0_return(x): + if x in Sets_0: + value = Sets_0[x] + if isinstance(value, str) and not x.lstrip('-').isdigit(): + return sets_0_return(value) + return value + elif x.isdigit() or x.lstrip('-').isdigit(): + return int(x) + else: + return None + +instructions = [] + +Sets_1 = {} +Sets_0 = {} + +p_1 = [] +p_0 = [] + +last_sound = 0 + if part == 2: - exit() + with open(input_f) as file: + for line in file: + instructions.append(list(parse_input(line.rstrip()))) + + x = 0 + + 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': + Sets[i[1]] = int(sets_return(i[2])) + x += 1 + + elif i[0] == 'add': + Sets[i[1]] += sets_return(i[2]) + x += 1 + + elif i[0] == 'mul': + Sets[i[1]] *= sets_return(i[2]) + x += 1 + + elif i[0] == 'mod': + Sets[i[1]] %= sets_return(i[2]) + x += 1 + + elif i[0] == 'snd': + last_sound = sets_return(i[1]) + x += 1 + + elif i[0] == 'rcv': + if sets_return(i[1]) != 0: + Sets[i[1]] = sets_return(i[1]) + print(last_sound) + exit() + x += 1 + + + elif i[0] == 'jgz': + if sets_return(i[1]) > 0: + x += sets_return(i[2]) + else: + x += 1 + + input() + + diff --git a/2017/18/solution_part2.py b/2017/18/solution_part2.py new file mode 100644 index 0000000..2740f80 --- /dev/null +++ b/2017/18/solution_part2.py @@ -0,0 +1,138 @@ +import sys,re,asyncio + +input_f = 'input' + +def parse_input(input_str): + pattern = r"^([a-zA-Z]{3})\s{1}(\w)?\s?(-?\w+)$" + match = re.match(pattern, input_str) + if match: + if match.group(2): + return match.group(1),match.group(2),match.group(3) + else: + return match.group(1),match.group(3) + return None + +def sets_return(value, sets): + if value in sets: + result = sets[value] + if isinstance(result, str) and not value.lstrip('-').isdigit(): + return sets_return(result, sets) + return result + elif value.isdigit() or value.lstrip('-').isdigit(): + return int(value) + return None + +async def loop0(instructions,p_0, p_1,sets_0,state): + x = 0 + while 0 <= x < len(instructions): + i = instructions[x] + if i[0] == 'set': + sets_0[i[1]] = sets_return(i[2],sets_0) + x += 1 + elif i[0] == 'add': + sets_0[i[1]] += sets_return(i[2],sets_0) + x += 1 + elif i[0] == 'mul': + sets_0[i[1]] *= sets_return(i[2],sets_0) + x += 1 + elif i[0] == 'mod': + sets_0[i[1]] %= sets_return(i[2],sets_0) + x += 1 + elif i[0] == 'snd': + await p_1.put(sets_return(i[1],sets_0)) + #print('P0 send', sets_0_return(i[1]),sets_0)#,'p_1',p_1) + x += 1 + elif i[0] == 'rcv': + if p_0.empty(): + state["loop0_waiting"] = True + if state["loop1_waiting"]: # Both loops are stuck + print(f"Program exiting. Loop1 'snd' count: {state['count']}") + return + await asyncio.sleep(0.1) + else: + state["loop0_waiting"] = False + sets_0[i[1]] = await p_0.get() + #print('P0 recv', sets_0[i[1]],sets_0)#,'p_0',p_0) + x += 1 + elif i[0] == 'jgz': + if sets_return(i[1],sets_0) > 0: + x += sets_return(i[2],sets_0) + else: + x += 1 + await asyncio.sleep(0.01) + +async def loop1(instructions,p_0, p_1,sets_1,state): + x = 0 + while 0 <= x < len(instructions): + i = instructions[x] + if i[0] == 'set': + sets_1[i[1]] = sets_return(i[2],sets_1) + x += 1 + elif i[0] == 'add': + sets_1[i[1]] += sets_return(i[2],sets_1) + x += 1 + elif i[0] == 'mul': + sets_1[i[1]] *= sets_return(i[2],sets_1) + x += 1 + elif i[0] == 'mod': + sets_1[i[1]] %= sets_return(i[2],sets_1) + x += 1 + elif i[0] == 'snd': + await p_0.put(sets_return(i[1],sets_1)) + state["count"] += 1 + print(state["count"]) + x += 1 + elif i[0] == 'rcv': + if p_1.empty(): + state["loop1_waiting"] = True + if state["loop0_waiting"]: # Both loops are stuck + print(f"Program exiting. Loop1 'snd' count: {state['count']}") + return + await asyncio.sleep(0.1) + + else: + state["loop1_waiting"] = False + sets_1[i[1]] = await p_1.get() + #print('P1 recv', sets_1[i[1]],sets_1) #,'p_1',p_1) + #condition.notify_all() + x += 1 + + + + + elif i[0] == 'jgz': + if sets_return(i[1],sets_1) > 0: + x += sets_return(i[2],sets_1) + else: + x += 1 + await asyncio.sleep(0.01) + +async def main(instructions): + p_0 = asyncio.Queue() + p_1 = asyncio.Queue() + sets_0 = {'p': 0} + sets_1 = {'p': 1} + state = { + "loop0_waiting": False, + "loop1_waiting": False, + "count": 0 + } + # Create tasks for the two loops + #task1 = asyncio.create_task(loop0(instructions[:],p_0,p_1)) + #task2 = asyncio.create_task(loop1(count,instructions[:],p_0,p_1)) + + + + await asyncio.gather( + loop0(instructions, p_0, p_1, sets_0, state), + loop1(instructions, p_0, p_1, sets_1, state) + ) + +instructions = [] + +with open(input_f) as file: + for line in file: + instructions.append(list(parse_input(line.rstrip()))) + + +asyncio.run(main(instructions)) \ No newline at end of file diff --git a/2017/18/test1 b/2017/18/test1 new file mode 100644 index 0000000..bf7e168 --- /dev/null +++ b/2017/18/test1 @@ -0,0 +1,7 @@ +snd 1 +snd 2 +snd p +rcv a +rcv b +rcv c +rcv d diff --git a/2017/18/test2 b/2017/18/test2 new file mode 100644 index 0000000..8b74206 --- /dev/null +++ b/2017/18/test2 @@ -0,0 +1,41 @@ +set i 31 +set a 1 +mul p 17 +jgz p p +mul a 2 +add i -1 +jgz i -2 +add a -1 +set i 127 +set p 735 +mul p 8505 +mod p a +mul p 129749 +add p 12345 +mod p a +set b p +mod b 10000 +snd b +add i -1 +jgz i -9 +jgz a 3 +rcv b +jgz b -1 +set f 0 +set i 126 +rcv a +rcv b +set p a +mul p -1 +add p b +jgz p 4 +snd a +set a b +jgz 1 3 +snd b +set f 1 +add i -1 +jgz i -11 +snd a +jgz f -16 +jgz a -19 diff --git a/2017/19/19.md b/2017/19/19.md new file mode 100644 index 0000000..df9be32 --- /dev/null +++ b/2017/19/19.md @@ -0,0 +1,45 @@ +## \-\-- Day 19: A Series of Tubes \-\-- + +Somehow, a network packet got +lost +and ended up here. It\'s trying to follow a routing diagram (your puzzle +input), but it\'s confused about where to go. + +Its starting point is just off the top of the diagram. Lines (drawn with +`|`, `-`, and `+`) show the path it needs to take, starting by going +down onto the only line connected to the top of the diagram. It needs to +follow this path until it reaches the end (located somewhere within the +diagram) and stop there. + +Sometimes, the lines cross over each other; in these cases, it needs to +continue going the same direction, and only turn left or right when +there\'s no other option. In addition, someone has left *letters* on the +line; these also don\'t change its direction, but it can use them to +keep track of where it\'s been. For example: + + | + | +--+ + A | C + F---|----E|--+ + | | | D + +B-+ +--+ + +Given this diagram, the packet needs to take the following path: + +- Starting at the only line touching the top of the diagram, it must + go down, pass through `A`, and continue onward to the first `+`. +- Travel right, up, and right, passing through `B` in the process. +- Continue down (collecting `C`), right, and up (collecting `D`). +- Finally, go all the way left through `E` and stopping at `F`. + +Following the path to the end, the letters it sees on its path are +`ABCDEF`. + +The little packet looks up at you, hoping you can help it find the way. +*What letters will it see* (in the order it would see them) if it +follows the path? (The routing diagram is very wide; make sure you view +it without line wrapping.) + +To begin, [get your puzzle input](19/input). + +Answer: diff --git a/2017/19/solution.py b/2017/19/solution.py new file mode 100644 index 0000000..3ad4cc7 --- /dev/null +++ b/2017/19/solution.py @@ -0,0 +1,130 @@ +#!/bin/python3 +import sys,re +from pprint import pprint +sys.path.insert(0, '../../') +from fred import list2int + +input_f = 'test' + +part = 1 +######################################### +# # +# Part 1 # +# # +######################################### + +grid = [] + +start = () +prev = () + +def valid_n(grid,cur): + r,c = cur + count = 0 + if grid[r-1][c] != ' ': + count += 1 + if grid[r+1][c] != ' ': + count += 1 + if grid[r][c+1] != ' ': + count += 1 + if grid[r][c-1] != ' ': + count += 1 + return count + + +if part == 1: + with open(input_f) as file: + for line in file: + grid.append(list(line.rstrip())) + + for r, row in enumerate(grid): + for c, col in enumerate(row): + print(grid[r][c],end='') + print() + + for r, row in enumerate(grid): + for c, col in enumerate(row): + if r == 0: + if grid[r][c] == '|': + start = (r,c) + + end = False + cur = start + prev = (-1,-1) + prev_dir = { + 'up': False, + 'down': False, + 'left': False, + 'right': False + } + + while not end: + r,c = cur + try: + if grid[r-1][c] != ' ' and prev != (r-1,c): + print('up',grid[r-1][c]) + + prev = cur + prev_dir = { + 'up': True, + 'down': False, + 'left': False, + 'right': False + } + cur = (r-1,c) + except Exception as e: + print(e) + + try: + if grid[r+1][c] != ' ' and prev != (r+1,c): + print('down',grid[r+1][c]) + if valid_n(grid,cur) >= 1 and prev_dir['down']: + prev = cur + prev_dir = { + 'up': False, + 'down': True, + 'left': False, + 'right': False + } + cur = (r+1,c) + except Exception as e: + print(e) + + try: + if grid[r][c-1] != ' ' and prev != (r,c-1) and not prev_dir['left']: + print('left',grid[r][c-1]) + prev = cur + prev_dir = { + 'up': False, + 'down': False, + 'left': True, + 'right': False + } + cur = (r,c-1) + except Exception as e: + print(e) + + try: + if grid[r][c+1] != ' ' and prev != (r,c+1) and not prev_dir['right']: + print('right',grid[r][c+1]) + prev = cur + prev_dir = { + 'up': False, + 'down': False, + 'left': False, + 'right': True + } + cur = (r,c+1) + except Exception as e: + print(e) + input() + + + +######################################### +# # +# Part 2 # +# # +######################################### +if part == 2: + exit()