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