AdventOfCode/Python/2018/16.py

75 lines
2.1 KiB
Python

from lib import *
input = read_input(2018, 16)
opcodes = [
lambda reg, a, b: reg[a] + reg[b], # addr
lambda reg, a, b: reg[a] + b, # addi
lambda reg, a, b: reg[a] * reg[b], # mulr
lambda reg, a, b: reg[a] * b, # muli
lambda reg, a, b: reg[a] & reg[b], # banr
lambda reg, a, b: reg[a] & b, # bani
lambda reg, a, b: reg[a] | reg[b], # borr
lambda reg, a, b: reg[a] | b, # bori
lambda reg, a, b: reg[a], # setr
lambda reg, a, b: a, # seti
lambda reg, a, b: a > reg[b], # gtir
lambda reg, a, b: reg[a] > b, # gtri
lambda reg, a, b: reg[a] > reg[b], # gtrr
lambda reg, a, b: a == reg[b], # eqir
lambda reg, a, b: reg[a] == b, # eqri
lambda reg, a, b: reg[a] == reg[b], # eqrr
]
def exec_opcode(reg, op, a, b, c):
reg[c] = int(op(reg, a, b))
def test_opcode(before, after, op, a, b, c):
before = [*before]
exec_opcode(before, op, a, b, c)
return before == after
out = 0
for before, instruction, after in map(str.splitlines, input.split("\n\n\n")[0].split("\n\n")):
before = eval(before.split(": ")[1])
_, a, b, c = map(int, instruction.split())
after = eval(after.split(": ")[1])
out += sum(test_opcode(before, after, op, a, b, c) for op in opcodes) >= 3
print(out)
codes = [opcodes.copy() for _ in range(16)]
m = [None] * 16
for before, instruction, after in map(str.splitlines, input.split("\n\n\n")[0].split("\n\n")):
before = eval(before.split(": ")[1])
op, a, b, c = map(int, instruction.split())
after = eval(after.split(": ")[1])
for o in [*codes[op]]:
if not test_opcode(before, after, o, a, b, c):
codes[op].remove(o)
if len(codes[op]) == 1:
m[op] = codes[op][0]
q = [x for x in m if x]
while q:
x = q.pop()
for i, lst in enumerate(codes):
if x in lst:
lst.remove(x)
if len(lst) == 1:
m[i] = lst[0]
q.append(m[i])
reg = [0] * 4
for line in input.split("\n\n\n\n")[1].splitlines():
op, a, b, c = map(int, line.split())
exec_opcode(reg, m[op], a, b, c)
print(reg[0])