This repository has been archived by the owner on Jan 2, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
25.py
96 lines (66 loc) · 2.53 KB
/
25.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
#!/usr/bin/python3
"""Solution for day 25 of Advent of Code 2016.
This is a copy of Day 23's solution, with an 'out' instruction added.
Manual testing showed the output repeats regularly, so we just run the program until there are 20 bits output.
TODO: Add a common class for handling the assembly code, as it's now repeated in 3 places.
"""
import itertools
def value(registers, x):
try:
return int(x)
except ValueError:
return registers[x]
def cpy(registers, src, dst):
registers[dst] = value(registers, src)
def inc(registers, reg):
registers[reg] += 1
def dec(registers, reg):
registers[reg] -= 1
def jnz(registers, val, tar):
registers['pc'] += 0 if value(registers, val) == 0 else value(registers, tar) - 1
def tgl(registers, ins):
mappings = {inc: dec, dec: inc, tgl: inc, jnz: cpy, cpy: jnz}
target = registers['pc'] + value(registers, ins)
registers['in'][target] = (mappings[registers['in'][target][0]], registers['in'][target][1])
def out(registers, val):
registers['out'].append(value(registers, val))
def try_multiply(registers):
try:
pc = registers['pc']
chunk = registers['in'][pc:pc+6]
instr, args = map(list, zip(*chunk))
if instr == [cpy, inc, dec, jnz, dec, jnz] \
and args[0][1] == args[2][0] == args[3][0] \
and args[4][0] == args[5][0] \
and args[1][0] != args[0][1] != args[4][0] != args[0][0] \
and args[3][1] == '-2' and args[5][1] == '-5':
registers[args[1][0]] += value(registers, args[0][0]) * value(registers, args[4][0])
registers[args[2][0]] = 0
registers[args[4][0]] = 0
registers['pc'] += 5
return True
except:
pass
return False
def step(registers):
if not try_multiply(registers):
try:
registers['in'][registers['pc']][0](registers, *registers['in'][registers['pc']][1])
except:
pass
def run(values):
registers = values
registers['pc'] = 0
registers['out'] = []
registers['in'] = instr.copy()
while registers['pc'] < len(instr) and len(registers['out']) < 20:
step(registers)
registers['pc'] += 1
return registers['out']
with open('data/25.txt', 'r') as file:
instr = map(str.split, map(str.strip, file.readlines()))
instr = [(globals()[i[0]], i[1:]) for i in instr]
for a in itertools.count():
if run({'a': a, 'b': 0, 'c': 0, 'd': 0}) == [0, 1] * 10:
print('Part one: %s' % a)
break