This repository was archived by the owner on Oct 13, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday16.py
More file actions
executable file
·107 lines (84 loc) · 2.81 KB
/
Copy pathday16.py
File metadata and controls
executable file
·107 lines (84 loc) · 2.81 KB
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
import re
def get_data():
with open('input') as f:
data = []
test = []
data_text, test_text = f.read().split('\n\n\n\n')
for line in data_text.splitlines():
if not line.strip():
continue
values = list(map(int, re.findall(r'(\d+)', line)))
if line.startswith('Before'):
data.append([values])
else:
data[-1].append(values)
for line in test_text.splitlines():
values = list(map(int, re.findall(r'(\d+)', line)))
test.append(values)
return data, test
def init():
registers = [0] * 4
ops = [
lambda regs, a, b, c: regs[a] + regs[b], # addr
lambda regs, a, b, c: regs[a] + b, # addi
lambda regs, a, b, c: regs[a] * regs[b], # mulr
lambda regs, a, b, c: regs[a] * b, # muli
lambda regs, a, b, c: regs[a] & regs[b], # banr
lambda regs, a, b, c: regs[a] & b, # bani
lambda regs, a, b, c: regs[a] | regs[b], # borr
lambda regs, a, b, c: regs[a] | b, # bori
lambda regs, a, b, c: regs[a], # setr
lambda regs, a, b, c: a, # seti
lambda regs, a, b, c: int(a > regs[b]), # gtir
lambda regs, a, b, c: int(regs[a] > b), # gtri
lambda regs, a, b, c: int(regs[a] > regs[b]), # gtrr
lambda regs, a, b, c: int(a == regs[b]), # eqir
lambda regs, a, b, c: int(regs[a] == b), # eqri
lambda regs, a, b, c: int(regs[a] == regs[b]), # eqrr
]
return registers, ops
def part_1(data):
_, ops = init()
result = 0
for inputs in data:
before, line, after = inputs
_, a, b, c = line
cnt = 0
for op in ops:
registers = before[:]
registers[c] = op(registers, a, b, c)
if registers == after:
cnt += 1
if cnt >= 3:
result += 1
return result
def part_2(data, test):
_, ops = init()
repeats = {}
for inputs in data:
before, line, after = inputs
opcode, a, b, c = line
for i, op in enumerate(ops):
registers = before[:]
registers[c] = op(registers, a, b, c)
if registers == after:
repeats.setdefault(opcode, set()).add(i)
found = set()
table = {}
for i in range(16):
for k, v in repeats.items():
if len(v - found) == 1:
table[k] = next(iter(v-found))
found.update(v)
registers = [0] * 4
for inputs in test:
opcode, a, b, c = inputs
op = ops[table[opcode]]
registers[c] = op(registers, a, b, c)
return registers[0]
def main():
data, test = get_data()
print('1:', part_1(data))
print('2:', part_2(data, test))
if __name__ == '__main__':
main()