# Advent of Code Day 7¶

In [14]:
def params(program, i, count):
modes = str(program[i] // 100)[::-1]
result = []

for x in range(count - 1):
arg = program[i + 1 + x]
if x >= len(modes) or modes[x] == "0":
result.append(program[arg])
else:
result.append(arg)

result.append(program[i + count]) # output

return result
In [64]:
def add(program, i, **kwargs):
assert program[i] % 100 == 1
a, b, out = params(program, i, 3)
program[out] = a + b
return i + 4, None

def mul(program, i, **kwargs):
assert program[i] % 100 == 2
a, b, out = params(program, i, 3)
program[out] = a * b
return i + 4, None

def inp(program, i, input_values, **kwargs):
assert program[i] % 100 == 3
out, = params(program, i, 1)
program[out] = input_values.pop(0)
# print(f"> program[{out}] = {program[out]}")
return i + 2, None

def out(program, i, **kwargs):
assert program[i] % 100 == 4
val, _ = params(program, i, 2)
# print(f"> {val}")
return i + 2, val

def jit(program, i, **kwargs):
assert program[i] % 100 == 5
test, ip, _ = params(program, i, 3)
if test != 0:
return ip, None
return i + 3, None

def jif(program, i, **kwargs):
assert program[i] % 100 == 6
test, ip, _ = params(program, i, 3)
if test == 0:
return ip, None
return i + 3, None

def lt(program, i, **kwargs):
assert program[i] % 100 == 7
a, b, out = params(program, i, 3)
program[out] = int(a < b)
return i + 4, None

def eq(program, i, **kwargs):
assert program[i] % 100 == 8
a, b, out = params(program, i, 3)
program[out] = int(a == b)
return i + 4, None

operations = { 1: add, 2: mul, 3: inp, 4: out, 5: jit, 6: jif, 7: lt, 8: eq }
In [146]:
def compute(program, input_values, debug=False):
l = len(program)
i = 0
output_value = None
last_output = None

while i < l:
op = program[i]
if op == 99:
if debug:
print(f">> exit {output_value}")
yield None

if debug:
print(f">> {i}, {list(enumerate(program))[max(0, i-15):i+15]}")

i, output_value = operations[op % 100](program, i, input_values=input_values)

if output_value is not None:
yield output_value

raise Exception("Didn't terminate properly")

def process(listing):
return list(map(int, listing.split(",")))
In [147]:
testinput="3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0"
In [148]:
def check_phases(program):
max_set = None

for permutation in permutations(list(range(5))):
inp = 0
for p in permutation:
computation = compute(process(program), [p, inp])
inp = next(computation)

if not max_set or max_set[0] < inp:
max_set = (inp, permutation)

return max_set

check_phases(testinput)
Out[148]:
(43210, [4, 3, 2, 1, 0])
In [149]:
def permutations(x):
if len(x) == 1:
yield x
else:
cur = x[0]
rest = x[1:]

for inner in permutations(rest):
for posn in range(len(inner) + 1):
option = inner[:]
option.insert(posn, cur)
yield option
In [150]:
check_phases("3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0")
Out[150]:
(54321, [0, 1, 2, 3, 4])
In [151]:
with open("AoC/input7.txt") as inputfile:
print( check_phases(inputfile.read().strip()))
(262086, [2, 1, 4, 0, 3])
In [152]:
test_input2 = "3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5"
In [153]:
def check_phases2(permutation, program):
inputs = [[p] for p in permutation]
inputs[0].append(0)
amplifiers = [compute(process(program), inp) for inp in inputs]
last_outputs = [None] * len(permutation)

i = 0
while True:
out = next(amplifiers[i])
if out is None:
break
elif out != "blocked":
inputs[(i + 1) % 5].append(out)
last_outputs[i] = out

i = (i + 1) % 5

return last_outputs

def find_max(program):
max_set = None

for permutation in permutations(list(range(5, 10))):
result = check_phases2(permutation, program)
if not max_set or result[4] > max_set[0]:
max_set = (result[4], permutation)

return max_set

find_max(test_input2)
Out[153]:
(139629729, [9, 8, 7, 6, 5])
In [154]:
list(range(9, 4, -1))
Out[154]:
[9, 8, 7, 6, 5]
In [155]:
with open("AoC/input7.txt") as inputfile:
print( find_max(inputfile.read().strip()))
(5371621, [5, 7, 6, 8, 9])

Rough solution again: received my highest rank till date - ranked 338 on the second star. Python's coroutines make this significantly easier to reason about.