-
Notifications
You must be signed in to change notification settings - Fork 0
/
16.py
75 lines (58 loc) · 2.09 KB
/
16.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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])