from lib import LETTERS_LOWER from collections import defaultdict, deque def get_value(regs, val): if val in LETTERS_LOWER: return regs[val] return int(val) def part_1(data): regs = defaultdict(int) insts = data.splitlines() last_sound = None pc = 0 while pc <= len(insts): cmds = insts[pc].split() match cmds: case ["set", reg, val]: val = get_value(regs, val) regs[reg] = val case ["mul", reg, val]: val = get_value(regs, val) regs[reg] = regs[reg] * val case ["add", reg, val]: val = get_value(regs, val) regs[reg] = regs[reg] + val case ["mod", reg, val]: val = get_value(regs, val) regs[reg] = regs[reg] % val case ["rcv", val]: if get_value(regs, val) != 0: print(last_sound) return case ["snd", val]: last_sound = get_value(regs, val) case ["jgz", cnd, off]: if get_value(regs, cnd) > 0: pc += get_value(regs, off) # XXX? continue case _: print(cmds) assert False pc += 1 def part_2(data): progs = [] insts = data.splitlines() prog1_counter = 0 for i in [0, 1]: regs = defaultdict(int) regs["p"] = i pc = 0 progs.append([pc, regs, False, deque()]) while not all(prog[2] for prog in progs): for prog in progs: pc, regs, waiting, queue = prog cmds = insts[pc].split() match cmds: case ["set", reg, val]: val = get_value(regs, val) regs[reg] = val case ["mul", reg, val]: val = get_value(regs, val) regs[reg] = regs[reg] * val case ["add", reg, val]: val = get_value(regs, val) regs[reg] = regs[reg] + val case ["mod", reg, val]: val = get_value(regs, val) regs[reg] = regs[reg] % val case ["rcv", reg]: if queue: val = queue.popleft() regs[reg] = val else: prog[2] = True pc -= 1 case ["snd", val]: val = get_value(regs, val) if prog == progs[0]: other_prog = progs[1] else: prog1_counter += 1 other_prog = progs[0] other_prog[3].append(val) case ["jgz", cnd, off]: if get_value(regs, cnd) > 0: pc += get_value(regs, off) # XXX? pc -= 1 case _: print(cmds) assert False prog[0] = pc + 1 print(prog1_counter) def main(): data = open(0).read().strip() part_1(data) part_2(data) if __name__ == "__main__": main()