Skip to content

Instantly share code, notes, and snippets.

@theglauber
Last active December 11, 2019 15:08
Show Gist options
  • Save theglauber/97866e54d6d425941460f07a4daba747 to your computer and use it in GitHub Desktop.
Save theglauber/97866e54d6d425941460f07a4daba747 to your computer and use it in GitHub Desktop.
Advent of code 2019 day 9
#!python
"""
https://adventofcode.com/2019/day/9
This starts again with the interpreter from day 5.
This runs both of the day 9 problems (after running the test data).
First:
::
Computing data
please enter a number: 1
Output: 2427443564
Second:
::
Computing data
please enter a number: 2
Output: 87221
Done
Opcodes:
-------
::
ABCDE
1002
DE - two-digit opcode, 02 == opcode 2
C - mode of 1st parameter, 0 == position mode
B - mode of 2nd parameter, 1 == immediate mode
A - mode of 3rd parameter, 0 == position mode,
omitted due to being a leading zero
"""
import copy
import operator
def compute(program):
"""
Program is a sequence of integers.
This deep-copies it, so the original program is unchanged.
Returns the last number output, and final status of the program.
"""
ip = 0 # instruction pointer
rp_base = 0 # relative parameter base
my_program = copy.deepcopy(program)
def magic_read(alist, pos, default=0):
"""
Read from "infinite" list. If the position is past the end,
return the default value.
"""
if pos < 0:
raise IndexError("Index cannot be negative")
try:
return alist[pos]
except IndexError:
return default
def magic_write(alist, pos, newval, default=0):
"""
Write to "infinite" list. If the position is past the end,
extend list with the default value.
"""
if pos < 0:
raise IndexError("Index cannot be negative")
try:
alist[pos] = newval
except IndexError:
alist.extend((pos + 1 - len(alist)) * [default])
alist[pos] = newval
def get_input(alist, pos, mode):
nonlocal rp_base
n = magic_read(alist, pos)
if mode == 0:
return magic_read(alist, n)
elif mode == 1:
return n
elif mode == 2:
return magic_read(alist, n + rp_base)
else:
raise ValueError("Invalid mode: {}".format(mode))
def store(alist, pointer, value, mode):
if mode == 1:
raise ValueError("store mode cannot be 1")
elif mode == 2:
pointer += rp_base
magic_write(alist, pointer, value)
while True:
output = None
# modes: 0 = position, 1 = immediate, 2 = relative position
rawcode = magic_read(my_program, ip)
opcode = rawcode % 100
mode1 = rawcode // 100 % 10
mode2 = rawcode // 1000 % 10
mode3 = rawcode // 10000 % 10
# print(opcode, mode1, mode2, mode3)
if (opcode == 1) or (opcode == 2):
# add or multiply
input1 = get_input(my_program, ip + 1, mode1)
input2 = get_input(my_program, ip + 2, mode2)
out_pos = magic_read(my_program, ip + 3)
functor = operator.add if opcode == 1 else operator.mul
output = functor(input1, input2)
store(my_program, out_pos, output, mode3)
ip += 4
elif opcode == 3:
# input
input1 = int(input("please enter a number: "))
# out_pos = get_input(my_program, ip + 1, mode1)
out_pos = magic_read(my_program, ip + 1)
store(my_program, out_pos, input1, mode1)
ip += 2
elif opcode == 4:
# output
input1 = get_input(my_program, ip + 1, mode1)
print("Output: {}".format(input1))
ip += 2
elif (opcode == 5) or (opcode == 6):
# jump if true, jump if false
input1 = get_input(my_program, ip + 1, mode1)
input2 = get_input(my_program, ip + 2, mode2)
if (opcode == 5) and (input1 != 0):
ip = input2
elif (opcode == 6) and (input1 == 0):
ip = input2
else:
ip += 3
elif (opcode == 7) or (opcode == 8):
# less-then or equal
input1 = get_input(my_program, ip + 1, mode1)
input2 = get_input(my_program, ip + 2, mode2)
comparator = operator.lt if opcode == 7 else operator.eq
# int(True) == 1, int(False) == 0
out_pos = magic_read(my_program, ip + 3)
output = int(comparator(input1, input2))
store(my_program, out_pos, output, mode3)
ip += 4
elif opcode == 9:
input1 = get_input(my_program, ip + 1, mode1)
rp_base += input1
ip += 2
elif opcode == 99:
# halt
print("Done")
break # the end
else:
raise Exception("Invalid opcode: {}".format(opcode))
return (output, my_program)
def read_data(filename):
"""
Each line is a "program":
name1:op1,op2,...opX
"""
alldata = {}
with open(filename) as f:
for line in f:
(name, prog) = line.rstrip().split(':')
alldata[name] = [int(x) for x in prog.split(',')]
return alldata
def main():
data = read_data('zzz-day9-data.txt')
for pname in ['test1', 'test2', 'test3', 'data']:
print("Computing {}".format(pname))
compute(data[pname])
print("--------------------------")
print()
if __name__ == "__main__":
main()
data:1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,26,1,1005,1101,0,24,1019,1102,1,32,1007,1101,0,704,1027,1102,0,1,1020,1101,0,348,1029,1102,28,1,1002,1101,34,0,1016,1102,29,1,1008,1102,1,30,1013,1102,25,1,1012,1101,0,33,1009,1102,1,37,1001,1101,31,0,1017,1101,245,0,1022,1102,39,1,1000,1101,27,0,1011,1102,770,1,1025,1101,0,22,1015,1102,1,1,1021,1101,711,0,1026,1101,20,0,1004,1101,0,23,1018,1101,242,0,1023,1102,21,1,1003,1101,38,0,1010,1101,0,35,1014,1101,0,36,1006,1101,0,357,1028,1102,1,775,1024,109,-3,2102,1,9,63,1008,63,36,63,1005,63,203,4,187,1105,1,207,1001,64,1,64,1002,64,2,64,109,8,21101,40,0,5,1008,1010,41,63,1005,63,227,1106,0,233,4,213,1001,64,1,64,1002,64,2,64,109,16,2105,1,2,1105,1,251,4,239,1001,64,1,64,1002,64,2,64,109,1,21107,41,40,-4,1005,1018,271,1001,64,1,64,1105,1,273,4,257,1002,64,2,64,109,-18,1207,0,21,63,1005,63,295,4,279,1001,64,1,64,1105,1,295,1002,64,2,64,109,-3,1207,0,36,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,6,2108,20,-3,63,1005,63,339,4,323,1001,64,1,64,1106,0,339,1002,64,2,64,109,28,2106,0,-7,4,345,1001,64,1,64,1106,0,357,1002,64,2,64,109,-18,1206,4,373,1001,64,1,64,1105,1,375,4,363,1002,64,2,64,109,-6,2107,31,-4,63,1005,63,397,4,381,1001,64,1,64,1105,1,397,1002,64,2,64,109,1,21102,42,1,-1,1008,1011,39,63,1005,63,421,1001,64,1,64,1106,0,423,4,403,1002,64,2,64,109,-2,2108,26,-2,63,1005,63,439,1106,0,445,4,429,1001,64,1,64,1002,64,2,64,109,6,21102,43,1,-5,1008,1011,43,63,1005,63,467,4,451,1105,1,471,1001,64,1,64,1002,64,2,64,109,6,21101,44,0,-3,1008,1019,44,63,1005,63,493,4,477,1105,1,497,1001,64,1,64,1002,64,2,64,109,-9,1206,7,511,4,503,1105,1,515,1001,64,1,64,1002,64,2,64,109,14,1205,-7,531,1001,64,1,64,1106,0,533,4,521,1002,64,2,64,109,-27,1201,0,0,63,1008,63,39,63,1005,63,555,4,539,1105,1,559,1001,64,1,64,1002,64,2,64,109,10,2101,0,-5,63,1008,63,24,63,1005,63,583,1001,64,1,64,1105,1,585,4,565,1002,64,2,64,109,-11,2107,21,5,63,1005,63,601,1105,1,607,4,591,1001,64,1,64,1002,64,2,64,109,10,1208,0,36,63,1005,63,627,1001,64,1,64,1106,0,629,4,613,1002,64,2,64,109,15,21108,45,45,-9,1005,1015,647,4,635,1105,1,651,1001,64,1,64,1002,64,2,64,109,-19,2101,0,-4,63,1008,63,37,63,1005,63,677,4,657,1001,64,1,64,1106,0,677,1002,64,2,64,109,22,1205,-6,695,4,683,1001,64,1,64,1105,1,695,1002,64,2,64,109,-10,2106,0,10,1001,64,1,64,1105,1,713,4,701,1002,64,2,64,109,-9,1201,-8,0,63,1008,63,36,63,1005,63,733,1105,1,739,4,719,1001,64,1,64,1002,64,2,64,109,7,21107,46,47,0,1005,1015,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,14,2105,1,-5,4,767,1105,1,779,1001,64,1,64,1002,64,2,64,109,-34,2102,1,6,63,1008,63,39,63,1005,63,799,1105,1,805,4,785,1001,64,1,64,1002,64,2,64,109,25,21108,47,49,-4,1005,1016,825,1001,64,1,64,1106,0,827,4,811,1002,64,2,64,109,-6,1208,-8,36,63,1005,63,845,4,833,1106,0,849,1001,64,1,64,1002,64,2,64,109,-10,1202,2,1,63,1008,63,36,63,1005,63,875,4,855,1001,64,1,64,1105,1,875,1002,64,2,64,109,-5,1202,10,1,63,1008,63,30,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21101,27,0,1,21101,0,915,0,1105,1,922,21201,1,65916,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1105,1,922,21201,1,0,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,22102,1,-2,-2,109,-3,2105,1,0
test1:109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99
test2:1102,34915192,34915192,7,4,7,99,0
test3:104,1125899906842624,99
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment