-
Notifications
You must be signed in to change notification settings - Fork 0
/
day17.py
56 lines (49 loc) · 1.36 KB
/
day17.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
regs = [45483412, 0, 0]
instrs = [2, 4, 1, 3, 7, 5, 0, 3, 4, 1, 1, 5, 5, 5, 3, 0]
ptr = 0
out = []
while ptr < len(instrs):
opcode, literal = instrs[ptr : ptr + 2]
combo = literal if literal <= 3 else regs[literal - 4]
match opcode:
case 0:
regs[0] = regs[0] // (2**combo)
case 1:
regs[1] = regs[1] ^ literal
case 2:
regs[1] = combo % 8
case 3:
if regs[0] != 0:
ptr = literal
continue
case 4:
regs[1] = regs[1] ^ regs[2]
case 5:
out.append(str(combo % 8))
case 6:
regs[1] = regs[0] // (2**combo)
case 7:
regs[2] = regs[0] // (2**combo)
ptr += 2
print(",".join(out))
def invert(out, bit):
states = set()
window = min(48 - bit, 10)
for a in range(2**window):
shift = (a & 0b111) ^ 0b011
c = (a >> shift) & 0b111
b = shift ^ c ^ 0b101
if b == out:
states.add((c, shift, a & 0b111))
return states
possible = {0}
for i in reversed(range(16)):
states = invert(instrs[i], i * 3)
next_possible = set()
for A in possible:
for c, shift, a in states:
A_ = A << 3 | a
if (A_ >> shift) & 0b111 == c:
next_possible.add(A_)
possible = next_possible
print(min(possible))