-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday16.py
117 lines (77 loc) · 2.61 KB
/
day16.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from collections import defaultdict
import re
def addr(a, b, c, registers):
registers[c] = registers[a] + registers[b]
return registers
def addi(a, b, c, registers):
registers[c] = registers[a] + b
return registers
def mulr(a, b, c, registers):
registers[c] = registers[a] * registers[b]
return registers
def muli(a, b, c, registers):
registers[c] = registers[a] * b
return registers
def banr(a, b, c, registers):
registers[c] = registers[a] & registers[b]
return registers
def bani(a, b, c, registers):
registers[c] = registers[a] & b
return registers
def borr(a, b, c, registers):
registers[c] = registers[a] | registers[b]
return registers
def bori(a, b, c, registers):
registers[c] = registers[a] | b
return registers
def setr(a, b, c, registers):
registers[c] = registers[a]
return registers
def seti(a, b, c, registers):
registers[c] = a
return registers
def gtir(a, b, c, registers):
registers[c] = a > registers[b]
return registers
def gtri(a, b, c, registers):
registers[c] = registers[a] > b
return registers
def gtrr(a, b, c, registers):
registers[c] = registers[a] > registers[b]
return registers
def eqir(a, b, c, registers):
registers[c] = a == registers[b]
return registers
def eqri(a, b, c, registers):
registers[c] = registers[a] == b
return registers
def eqrr(a, b, c, registers):
registers[c] = registers[a] == registers[b]
return registers
def part1(input):
functions = {addr, addi, mulr, muli, banr, bani, borr, bori, setr, seti, gtir, gtri, gtrr, eqir, eqri, eqrr}
cnt = 0
opcodes = defaultdict(lambda: set(functions))
for x in input:
before = x[:4]
op, *args = x[4:8]
after = x[8:]
possibles = {f for f in functions if f(*args, before[:]) == after}
cnt += len(possibles) >= 3
opcodes[op] &= possibles
print(cnt)
while not all(len(x) == 1 for x in opcodes.values()):
decided = {next(iter(x)) for x in opcodes.values() if len(x) == 1}
opcodes = {x: (y - decided if len(y) > 1 else y) for x, y in opcodes.items()}
return opcodes
def part2(input, opcodes):
registers = [0, 0, 0, 0]
for op, *args in input:
registers = next(iter(opcodes[op]))(*args, registers)
return registers[0]
def main():
input1, input2 = open('day16.txt').read().split('\n\n\n')
opcodes = part1((list(map(int, re.findall(r'-?\d+', x))) for x in input1.split('\n\n')))
print(part2((map(int, x.split()) for x in input2.strip().split('\n')), opcodes))
if __name__ == '__main__':
main()