aocpy/2017/d18.py
2024-05-30 09:01:51 -04:00

110 lines
3.2 KiB
Python

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()