Last active
December 11, 2019 15:08
-
-
Save theglauber/97866e54d6d425941460f07a4daba747 to your computer and use it in GitHub Desktop.
Advent of code 2019 day 9
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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