adventofcode2019/7/7-2.py
2019-12-07 17:52:56 +00:00

163 lines
3.7 KiB
Python
Executable file

#!/usr/bin/env python3
import sys
class Amp:
def __init__(self, instructions, id):
self.instructions = instructions
self.pcounter = 0
self.finished = 0
self.ampid = id
self.inputs = []
def terminated(self):
return self.finished
def r(self, pos, mode):
if mode == 0:
return int(self.instructions[self.instructions[pos]])
else:
return int(self.instructions[pos])
def w(self, pos, v, mode):
if mode == 0:
self.instructions[self.instructions[pos]] = v
else:
print("broken!", self.instructions, pos, v, mode)
def perform(self, inputs):
outputs = []
for inp in inputs:
self.inputs.append(inp)
while 1:
fullopcode = self.instructions[self.pcounter]
opcode = fullopcode % 100
mode_c = (int(fullopcode/100) % 10)
mode_b = (int(fullopcode/1000) % 10)
mode_a = (int(fullopcode/10000) % 10)
pos_c = self.pcounter+1
pos_b = self.pcounter+2
pos_a = self.pcounter+3
#print(self.ampid, "OP:", opcode, mode_c, mode_b, mode_a, pos_c, pos_b, pos_a)
# add
if opcode == 1:
val = self.r(pos_c,mode_c) + self.r(pos_b,mode_b)
self.w(pos_a, val, mode_a)
self.pcounter += 4
# multiply
elif opcode == 2:
val = self.r(pos_c, mode_c) * self.r(pos_b, mode_b)
self.w(pos_a, val, mode_a)
self.pcounter += 4
# input
elif opcode == 3:
#print ("input:", self.inputs)
store = self.inputs.pop(0)
self.w(pos_c, store, mode_c)
self.pcounter += 2
# output
elif opcode == 4:
outputs.append(self.r(pos_c, mode_c))
self.pcounter += 2
#print("output:", outputs)
return (outputs, self.finished)
# jump-if-true
elif opcode == 5:
t = self.r(pos_c, mode_c)
if t != 0:
self.pcounter = self.r(pos_b, mode_b)
else:
self.pcounter += 3
# jump-if-false
elif opcode == 6:
t = self.r(pos_c, mode_c)
if t == 0:
self.pcounter = self.r(pos_b, mode_b)
else:
self.pcounter += 3
# less-than
elif opcode == 7:
c = self.r(pos_c, mode_c)
b = self.r(pos_b, mode_b)
if c < b:
self.w(pos_a, 1, mode_a)
else:
self.w(pos_a, 0, mode_a)
self.pcounter += 4
# equals
elif opcode == 8:
c = self.r(pos_c, mode_c)
b = self.r(pos_b, mode_b)
if c == b:
self.w(pos_a, 1, mode_a)
else:
self.w(pos_a, 0, mode_a)
self.pcounter += 4
# stop
elif opcode == 99:
self.finished = 1
break
return (outputs, self.finished)
def runamps(instructions, phase):
amps = []
r = [0]
# Set up amps
for i in range(0, 5):
ints = []
for j in instructions:
ints.append(int(j))
input = [phase[i], r[0]]
a = Amp(ints,i)
ret = a.perform(input)
amps.append(a)
r = ret[0]
# Loop over amps until they're done processing.
finished = 0
while 1:
if finished:
break
for i in range(0, 5):
input = [r[0]]
ret = amps[i].perform(input)
if amps[i].terminated():
finished = 1
else:
r = ret[0]
return(r)
def permute(nums):
result_perms = [[]]
for n in nums:
new_perms = []
for perm in result_perms:
for i in range(len(perm)+1):
new_perms.append(perm[:i] + [n] + perm[i:])
result_perms = new_perms
return result_perms
f = open(sys.argv[1], "r")
line = f.readline()
instructions = line.rstrip().split(',')
print(runamps(instructions,[9,7,8,5,6]))
for a in permute([5,6,7,8,9]):
ret = runamps(instructions, a)
print("%s %s" % (ret[0], a))