My Advent of Code solutions in Python.
kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code
python
1import fileinput
2from itertools import permutations
3
4
5def parse_mode(tape, mode_op, a, b, c):
6 op = mode_op % 100
7 mode_a = (mode_op // 100) % 10
8 mode_b = (mode_op // 1000) % 10
9 mode_c = (mode_op // 10000) % 10
10
11 return op, mode_a, mode_b, mode_c
12
13
14GLOBAL_INPUTS = [0, 0, 0, 0, 0]
15
16
17def emulate(phase, amp_num, pc=0):
18 tape = TAPE[:]
19 outs = []
20 read_phase = False
21
22 while pc < len(tape):
23 mode_op, a, b, c = tape[pc:pc+4]
24 op, mode_a, mode_b, mode_c = parse_mode(tape, mode_op, a, b, c)
25 modes = [mode_a, mode_b, mode_c]
26 last_pc = pc
27
28 # ADD a b c
29 if op == 1:
30 tape[c] = (a if mode_a else tape[a]) + (b if mode_b else tape[b])
31 pc += 4
32
33 # MUL a b c
34 elif op == 2:
35 tape[c] = (a if mode_a else tape[a]) * (b if mode_b else tape[b])
36 pc += 4
37
38 # INP a
39 elif op == 3:
40 if read_phase:
41 tape[a] = GLOBAL_INPUTS[amp_num]
42 else:
43 tape[a] = phase
44 read_phase = True
45 pc += 2
46
47 # OUT b
48 elif op == 4:
49 outs.append(a if mode_a else tape[a])
50 yield a if mode_a else tape[a]
51 pc += 2
52
53 # JZ a b
54 elif op == 5:
55 if (a if mode_a else tape[a]) != 0:
56 pc = (b if mode_b else tape[b])
57 else:
58 pc += 3
59
60 # JNZ a b
61 elif op == 6:
62 if (a if mode_a else tape[a]) == 0:
63 pc = (b if mode_b else tape[b])
64 else:
65 pc += 3
66
67 # LT a b c
68 elif op == 7:
69 tape[c] = 1 if (a if mode_a else tape[a]) < (b if mode_b else tape[b]) else 0
70 pc += 4
71
72 # EQ a b c
73 elif op == 8:
74 tape[c] = 1 if (a if mode_a else tape[a]) == (b if mode_b else tape[b]) else 0
75 pc += 4
76
77 # HALT
78 elif op == 99:
79 raise StopIteration()
80
81
82def emulate_sequence(phases):
83 global GLOBAL_INPUTS
84 GLOBAL_INPUTS = [0] * 5
85 amps = [emulate(phases[i], i) for i in range(5)]
86 inp = 0
87 on_amp = 0
88 last_output = 0
89
90 try:
91 while True:
92 inp = next(amps[on_amp])
93 last_output = inp
94 on_amp = (on_amp + 1) % 5
95 GLOBAL_INPUTS[on_amp] = inp
96 except StopIteration:
97 return last_output
98
99
100# Read input
101TAPE = [int(x) for x in fileinput.input()[0].split(',')]
102TAPE += [None, None, None, None]
103
104print "Part 1:", max(emulate_sequence(p) for p in permutations(range(5), 5))
105print "Part 2:", max(emulate_sequence(p) for p in permutations(range(5, 10), 5))