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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
import itertools
import queue
import sys
params = {1:3, 2:3, 3:1, 4:1, 5:2, 6:2, 7:3, 8:3, 99:0}
ADD = 1
MULT = 2
IN = 3
OUT = 4
JNZ = 5
JEZ = 6
LET = 7
EQV = 8
HAL = 99
class Computer(object):
def __init__(self, program):
self.memory = program.copy()
self.pointer = 0
self.phase_read = False
self.input = None
self.output = None
def parse_op(self, op):
code = op % 100
return [code] + [(op // 10**(i+2)) % 10**(i+1) for i in range(params[code])]
def clear_flags(self):
self.input = None
self.output = None
def get_param(self, inst, num):
return self.memory[self.pointer + num] if inst[num] == True else\
self.memory[self.memory[self.pointer + num]]
def step(self):
inst = self.parse_op(self.memory[self.pointer])
if inst[0] == HAL:
return
elif inst[0] == ADD:
self.memory[self.memory[self.pointer+3]] = \
self.get_param(inst, 1) + self.get_param(inst, 2)
self.pointer += 4
elif inst[0] == MULT:
self.memory[self.memory[self.pointer+3]] = \
self.get_param(inst, 1) * self.get_param(inst, 2)
self.pointer += 4
elif inst[0] == IN:
self.memory[self.memory[self.pointer+1]] = self.input
self.input = None
self.pointer += 2
elif inst[0] == OUT:
self.output = self.get_param(inst, 1)
self.pointer += 2
elif inst[0] == JNZ:
if self.get_param(inst, 1) != 0:
self.pointer = self.get_param(inst, 2)
else:
self.pointer += 3
elif inst[0] == JEZ:
if self.get_param(inst, 1) == 0:
self.pointer = self.get_param(inst, 2)
else:
self.pointer += 3
elif inst[0] == LET:
self.memory[self.memory[self.pointer+3]] = 1 if \
self.get_param(inst, 1) < self.get_param(inst, 2) \
else 0
self.pointer += 4
elif inst[0] == EQV:
self.memory[self.memory[self.pointer+3]] = 1 if \
self.get_param(inst, 1) == self.get_param(inst, 2) \
else 0
self.pointer += 4
else:
print(self.memory)
print(self.pointer)
print("invalid instruction", self.memory[self.pointer])
print(inst)
sys.exit()
def pt2(program):
highest_signal = 0
highest_sequence = None
for phase_seq in list(itertools.permutations(list(range(5,10)))):
signal = 0
q = queue.Queue(5)
for phase in phase_seq:
q.put(phase)
amps = [Computer(program) for i in range(5)]
for amp in amps:
amp.input = q.get()
signal = 0
current_amp = 0
while True:
amp = amps[current_amp]
amp.step()
if amp.input == None:
if amp.phase_read == False:
amp.phase_read = True
amp.input = signal
else:
pass
if amp.output is not None:
signal = amp.output
amp.output = None
current_amp = (current_amp + 1) % 5
if amps[current_amp].phase_read == True:
amps[current_amp].input = signal
continue
if amp.memory[amp.pointer] == 99:
if current_amp == 4:
break
current_amp = (current_amp + 1) % 5
amps[current_amp].input = signal
continue
if signal > highest_signal:
highest_signal = signal
highest_sequence = phase_seq
return highest_signal
if __name__ == "__main__":
f = open("../input/07", "r")
program = [int(x) for x in f.readline().split(",")]
import cProfile
import timeit
print(pt2(program))
print(timeit.timeit('pt2(program)', globals=globals(), number=1)*1000, "ms")
cProfile.run("pt2(program)")
|