# Advent of Code Day 9¶

In [1]:
def readfile(path):
with open(path) as input_file:

In [157]:
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])
elif modes[x] == "2":
result.append(program[program.offset + arg])
else:
result.append(arg)

output = program[i + count]
if len(modes) >= count and modes[count - 1] == "2":
output += program.offset

result.append(output) # output
return result

In [158]:
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

def rbo(program, i, **kwargs):
assert program[i] % 100 == 9
delta, _ = params(program, i, 2)
program.offset += delta
# print (f"> rbo = {program.offset}" )
return i + 2, None

operations = { 1: add, 2: mul, 3: inp, 4: out, 5: jit, 6: jif, 7: lt, 8: eq, 9: rbo }

In [159]:
class Program(list):
def __init__(self, *args, **kwargs):
super(Program, self).__init__(args[0])
self.offset = 0

def compute(program, input_values, debug=False):
program = Program(program)

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}")
return

if debug:
print(f">> {i}, {list(enumerate(program))[i:i+5]}")

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):
lst = list(map(int, listing.split(",")))
lst.extend([0] * 100000)
return lst

In [161]:
list(compute(process(readfile("AoC/input9.txt")), input_values=[1], debug=False))

Out[161]:
[4261108180]
In [147]:
list(compute(process("104,1125899906842624,99"), input_values=[]))

> 1125899906842624

Out[147]:
[1125899906842624]
In [163]:
list(compute(process("109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99"), input_values=[], debug=False))

Out[163]:
[109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99]
In [164]:
list(compute(process(readfile("AoC/input9.txt")), input_values=[2], debug=False))

Out[164]:
[77944]

Took me almost an hour to complete this one, mainly because I ddin't really read the puzzle carefully enough, and I'd never handled the output memory addresses correctly before which cost me a remarkable amount of time. Happy to hear that the intcode computer is now complete, though! I wonder if there will be more intcode problems.