2017-12-18 - Duet
(original .ipynb)import math from collections import defaultdict puzzle_input_str = open("puzzle_input/day18.txt").read() test_input_str = """set a 1 add a 2 mul a a mod a 5 snd a set a 0 rcv a jgz a -1 set a 1 jgz a -2""" def val(regs, x): if x.isalpha(): return regs[x] return int(x) def op_snd_v1(regs, x): regs["frequency"] = val(regs, x) return 1 def op_set(regs, x, y): regs[x] = val(regs, y) return 1 def op_add(regs, x, y): regs[x] += val(regs, y) return 1 def op_mul(regs, x, y): regs[x] *= val(regs, y) return 1 def op_mod(regs, x, y): regs[x] %= val(regs, y) return 1 def op_rcv_v1(regs, x): if regs[x] != 0: return math.inf return 1 def op_jgz(regs, x, y): if val(regs, x) > 0: return val(regs, y) return 1 ops = { "snd": op_snd_v1, "set": op_set, "add": op_add, "mul": op_mul, "mod": op_mod, "rcv": op_rcv_v1, "jgz": op_jgz, } def part_one(input_str): instructions = [line.split(" ") for line in input_str.split("\n")] register_file = defaultdict(lambda: 0) ip = 0 while ip < math.inf: instr = instructions[ip] op = ops[instr[0]] ip += op(register_file, *instr[1:]) return register_file["frequency"] assert 4 == part_one(test_input_str) print("part one:", part_one(puzzle_input_str))
part one: 4601
def op_snd_v2(regs, x): regs["out"] = val(regs, x) return 1 def op_rcv_v2(regs, x): if len(regs["in"]) > 0: regs[x] = regs["in"].pop(0) return 1 return 0 def part_two(input_str): instructions = [line.split(" ") for line in input_str.split("\n")] register_file_0 = defaultdict(lambda: 0) register_file_1 = defaultdict(lambda: 0) ip_0 = 0 ip_1 = 0 register_file_0["in"] = [] register_file_0["out"] = None register_file_1["p"] = 0 register_file_1["in"] = [] register_file_1["out"] = None register_file_1["p"] = 1 ops["snd"] = op_snd_v2 ops["rcv"] = op_rcv_v2 program_1_sent = 0 prev_ip_0 = None prev_ip_1 = None while (prev_ip_0 != ip_0) or (prev_ip_1 != ip_1): prev_ip_0 = ip_0 prev_ip_1 = ip_1 # run program 0 if ip_0 < math.inf and ip_0 < len(instructions): instr_0 = instructions[ip_0] op_0 = ops[instr_0[0]] ip_0 += op_0(register_file_0, *instr_0[1:]) # run program 1 if ip_1 < math.inf and ip_1 < len(instructions): instr_1 = instructions[ip_1] op_1 = ops[instr_1[0]] ip_1 += op_1(register_file_1, *instr_1[1:]) # pass values back and forward if register_file_0["out"]: register_file_1["in"].append(register_file_0["out"]) register_file_0["out"] = None if register_file_1["out"]: register_file_0["in"].append(register_file_1["out"]) register_file_1["out"] = None program_1_sent += 1 return program_1_sent test_input_str_2 = """snd 1 snd 2 snd p rcv a rcv b rcv c rcv d""" assert 3 == part_two(test_input_str_2) print("part two:", part_two(puzzle_input_str))
part two: 6858