-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy path16.py
87 lines (78 loc) · 2.34 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
76
77
78
79
80
81
82
83
84
85
86
87
import fileinput
import re
def addr(r, a, b, c): r[c] = r[a] + r[b]
def addi(r, a, b, c): r[c] = r[a] + b
def mulr(r, a, b, c): r[c] = r[a] * r[b]
def muli(r, a, b, c): r[c] = r[a] * b
def banr(r, a, b, c): r[c] = r[a] & r[b]
def bani(r, a, b, c): r[c] = r[a] & b
def borr(r, a, b, c): r[c] = r[a] | r[b]
def bori(r, a, b, c): r[c] = r[a] | b
def setr(r, a, b, c): r[c] = r[a]
def seti(r, a, b, c): r[c] = a
def gtir(r, a, b, c): r[c] = int(a > r[b])
def gtri(r, a, b, c): r[c] = int(r[a] > b)
def gtrr(r, a, b, c): r[c] = int(r[a] > r[b])
def eqir(r, a, b, c): r[c] = int(a == r[b])
def eqri(r, a, b, c): r[c] = int(r[a] == b)
def eqrr(r, a, b, c): r[c] = int(r[a] == r[b])
functions = [
addr, addi, mulr, muli, banr, bani, borr, bori,
setr, seti, gtir, gtri, gtrr, eqir, eqri, eqrr,
]
def parse(line):
return list(map(int, re.findall(r'\d+', line)))
def behaves_like(instruction, before, after):
count = 0
for f in functions:
r = list(before)
f(r, *instruction[1:])
if r == after:
count += 1
return count
def remove_candidates(instruction, before, after, candidates):
for f in functions:
r = list(before)
f(r, *instruction[1:])
if r != after:
candidates[instruction[0]].discard(f)
lines = list(fileinput.input())
# part 1
count = 0
for line in lines:
if 'Before' in line:
before = parse(line)
elif 'After' in line:
after = parse(line)
if behaves_like(instruction, before, after) >= 3:
count += 1
else:
instruction = parse(line)
print(count)
# part 2
opcodes = {}
known = set()
while len(known) < len(functions):
candidates = {}
for i in range(len(functions)):
candidates[i] = set(functions) - set(known)
for line in lines:
if 'Before' in line:
before = parse(line)
elif 'After' in line:
after = parse(line)
remove_candidates(instruction, before, after, candidates)
else:
instruction = parse(line)
for i in range(len(functions)):
if len(candidates[i]) == 1:
f = candidates[i].pop()
opcodes[i] = f
known.add(f)
r = [0] * 4
i = max(i for i, x in enumerate(lines) if not x.strip()) + 1
for line in lines[i:]:
op, a, b, c = parse(line)
f = opcodes[op]
f(r, a, b, c)
print(r[0])