diff --git a/days/comp.py b/days/comp.py index a359669..509c5bc 100644 --- a/days/comp.py +++ b/days/comp.py @@ -1,4 +1,4 @@ -from typing import List, Tuple, Iterator +from typing import List, Dict, Tuple, Iterator class OpcodeComputer(): @@ -15,18 +15,18 @@ class OpcodeComputer(): """ __last_result: int = 0 - __initial_mem: List[int] = [] - memory: List[int] = [] + __initial_mem: Dict[int, int] + memory: Dict[int, int] def __init__(self, file: str = None, mem: str = '99') -> None: inp = mem if file: with open(file) as fp: inp = fp.readline() - self.__initial_mem = [int(k) for k in inp.split(',')] + self.__initial_mem = dict(enumerate([int(k) for k in inp.split(',')])) self.memory = self.__initial_mem - def parse_param(self, pc: int, mem: List[int]) \ + def parse_param(self, pc: int, mem: Dict[int, int], base: int) \ -> Tuple[int, int, int, int]: """Parse Intcode and return parameters as specified by parameter mode @@ -42,15 +42,21 @@ class OpcodeComputer(): b: int = 0 c: int = 0 try: - a = pc+1 if i[2] == '1' else mem[pc+1] - b = pc+2 if i[1] == '1' else mem[pc+2] - c = pc+3 if i[0] == '1' else mem[pc+3] - except IndexError: + a = pc+1 if i[2] == '1'\ + else mem[pc+1] + base if i[2] == '2'\ + else mem[pc+1] + b = pc+2 if i[1] == '1'\ + else mem[pc+2] + base if i[1] == '2'\ + else mem[pc+2] + c = pc+3 if i[0] == '1'\ + else mem[pc+3] + base if i[0] == '2'\ + else mem[pc+3] + except KeyError: pass return (int(i[-2:]), a, b, c) def process_op(self, inp: List[int] = [])\ - -> Iterator[str]: + -> Iterator[int]: """Run program code Args: @@ -59,26 +65,33 @@ class OpcodeComputer(): Returns: int: Content in memory at position 0 """ + def read(position: int) -> int: + try: + return mem[position] + except KeyError: + return 0 + + base = 0 pc: int = 0 mem = self.memory - cmd: int = self.memory[pc] + cmd: int = mem[pc] while cmd != 99: - cmd, a, b, c = self.parse_param(pc, mem) + cmd, a, b, c = self.parse_param(pc, mem, base) if cmd == 1: - mem[c] = mem[a] + mem[b] + mem[c] = read(a) + read(b) pc += 4 elif cmd == 2: - mem[c] = mem[a] * mem[b] + mem[c] = read(a) * read(b) pc += 4 elif cmd == 3: mem[a] = int(inp.pop(0)) pc += 2 elif cmd == 4: - yield str(mem[a]) + yield read(a) pc += 2 elif cmd == 5: - pc = mem[b] if mem[a] != 0 else pc + 3 + pc = read(b) if read(a) != 0 else pc + 3 elif cmd == 6: pc = mem[b] if mem[a] == 0 else pc + 3 elif cmd == 7: @@ -87,6 +100,9 @@ class OpcodeComputer(): elif cmd == 8: mem[c] = 1 if mem[a] == mem[b] else 0 pc += 4 + elif cmd == 9: + base += mem[a] + pc += 2 else: raise Exception(f'Unknown Opcode encountered: {cmd}') cmd = mem[pc] @@ -97,4 +113,4 @@ class OpcodeComputer(): return self.__last_result def reset(self): - self.memory = list(self.__initial_mem) + self.memory = self.__initial_mem.copy() diff --git a/days/input/day9_input b/days/input/day9_input new file mode 100644 index 0000000..42ed263 --- /dev/null +++ b/days/input/day9_input @@ -0,0 +1 @@ +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,1101,234,0,1027,1101,0,568,1023,1102,844,1,1025,1101,0,23,1008,1102,1,1,1021,1102,27,1,1011,1101,0,26,1004,1102,1,586,1029,1102,29,1,1014,1101,0,22,1015,1102,36,1,1016,1101,35,0,1013,1102,20,1,1003,1102,1,37,1019,1101,30,0,1006,1102,34,1,1000,1101,571,0,1022,1102,1,28,1005,1101,39,0,1009,1102,38,1,1017,1102,591,1,1028,1102,1,31,1007,1102,24,1,1010,1101,0,33,1001,1101,0,21,1018,1101,0,0,1020,1101,25,0,1002,1102,32,1,1012,1101,0,237,1026,1101,0,853,1024,109,29,1206,-9,195,4,187,1106,0,199,1001,64,1,64,1002,64,2,64,109,-26,2102,1,0,63,1008,63,23,63,1005,63,223,1001,64,1,64,1105,1,225,4,205,1002,64,2,64,109,16,2106,0,8,1106,0,243,4,231,1001,64,1,64,1002,64,2,64,109,-19,21101,40,0,10,1008,1010,40,63,1005,63,265,4,249,1106,0,269,1001,64,1,64,1002,64,2,64,109,-2,2107,31,8,63,1005,63,289,1001,64,1,64,1105,1,291,4,275,1002,64,2,64,109,2,1208,7,28,63,1005,63,307,1106,0,313,4,297,1001,64,1,64,1002,64,2,64,109,-1,1207,9,24,63,1005,63,335,4,319,1001,64,1,64,1105,1,335,1002,64,2,64,109,5,1201,0,0,63,1008,63,25,63,1005,63,355,1105,1,361,4,341,1001,64,1,64,1002,64,2,64,109,-13,1202,9,1,63,1008,63,34,63,1005,63,383,4,367,1105,1,387,1001,64,1,64,1002,64,2,64,109,32,1205,-3,403,1001,64,1,64,1106,0,405,4,393,1002,64,2,64,109,-14,2108,31,-2,63,1005,63,423,4,411,1105,1,427,1001,64,1,64,1002,64,2,64,109,11,1206,1,439,1105,1,445,4,433,1001,64,1,64,1002,64,2,64,109,-21,1208,4,20,63,1005,63,467,4,451,1001,64,1,64,1105,1,467,1002,64,2,64,109,6,1207,-5,33,63,1005,63,487,1001,64,1,64,1106,0,489,4,473,1002,64,2,64,109,-12,1202,8,1,63,1008,63,34,63,1005,63,509,1106,0,515,4,495,1001,64,1,64,1002,64,2,64,109,28,1205,0,529,4,521,1106,0,533,1001,64,1,64,1002,64,2,64,109,3,21101,41,0,-9,1008,1015,38,63,1005,63,557,1001,64,1,64,1106,0,559,4,539,1002,64,2,64,109,-11,2105,1,10,1105,1,577,4,565,1001,64,1,64,1002,64,2,64,109,23,2106,0,-8,4,583,1105,1,595,1001,64,1,64,1002,64,2,64,109,-15,21108,42,42,-6,1005,1015,613,4,601,1106,0,617,1001,64,1,64,1002,64,2,64,109,-14,21107,43,44,8,1005,1015,639,4,623,1001,64,1,64,1106,0,639,1002,64,2,64,109,11,2107,38,-9,63,1005,63,661,4,645,1001,64,1,64,1106,0,661,1002,64,2,64,109,-2,21107,44,43,3,1005,1019,677,1105,1,683,4,667,1001,64,1,64,1002,64,2,64,109,-7,21108,45,42,1,1005,1010,703,1001,64,1,64,1106,0,705,4,689,1002,64,2,64,109,-5,2102,1,1,63,1008,63,28,63,1005,63,727,4,711,1106,0,731,1001,64,1,64,1002,64,2,64,109,13,21102,46,1,0,1008,1017,46,63,1005,63,753,4,737,1106,0,757,1001,64,1,64,1002,64,2,64,109,-4,2101,0,-5,63,1008,63,20,63,1005,63,781,1001,64,1,64,1105,1,783,4,763,1002,64,2,64,109,1,21102,47,1,0,1008,1014,48,63,1005,63,803,1105,1,809,4,789,1001,64,1,64,1002,64,2,64,109,-3,2101,0,-4,63,1008,63,31,63,1005,63,835,4,815,1001,64,1,64,1105,1,835,1002,64,2,64,109,6,2105,1,7,4,841,1001,64,1,64,1105,1,853,1002,64,2,64,109,-21,2108,33,10,63,1005,63,873,1001,64,1,64,1105,1,875,4,859,1002,64,2,64,109,6,1201,4,0,63,1008,63,30,63,1005,63,901,4,881,1001,64,1,64,1105,1,901,4,64,99,21102,27,1,1,21102,1,915,0,1106,0,922,21201,1,64720,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1105,1,922,21202,1,1,-1,21201,-2,-3,1,21101,957,0,0,1105,1,922,22201,1,-1,-2,1105,1,968,21202,-2,1,-2,109,-3,2106,0,0 \ No newline at end of file diff --git a/days/test_comp.py b/days/test_comp.py index 7259a6d..7c92984 100644 --- a/days/test_comp.py +++ b/days/test_comp.py @@ -9,58 +9,78 @@ inputfile = os.path.join(os.path.dirname(__file__), "input/day9_input") def test_addition(): com = OpcodeComputer(mem="1,0,0,0,99") com.process_all() - assert com.memory == [2, 0, 0, 0, 99] + assert list(com.memory.values()) == [2, 0, 0, 0, 99] def test_multiplication(): com = OpcodeComputer(mem="2,3,0,3,99") com.process_all() - assert com.memory == [2, 3, 0, 6, 99] + assert list(com.memory.values()) == [2, 3, 0, 6, 99] def test_multiplication2(): com = OpcodeComputer(mem="2,4,4,5,99,0") com.process_all() - assert com.memory == [2, 4, 4, 5, 99, 9801] + assert list(com.memory.values()) == [2, 4, 4, 5, 99, 9801] def test_addition2(): com = OpcodeComputer(mem="1,1,1,4,99,5,6,0,99") com.process_all() - assert com.memory == [30, 1, 1, 4, 2, 5, 6, 0, 99] + assert list(com.memory.values()) == [30, 1, 1, 4, 2, 5, 6, 0, 99] def test_position1(): com = OpcodeComputer(mem="3,9,8,9,10,9,4,9,99,-1,8") res = list(com.process_op([8])) - assert res[0] == '1' + assert res[0] == 1 def test_position2(): com = OpcodeComputer(mem="3,9,7,9,10,9,4,9,99,-1,8") res = list(com.process_op([7])) - assert res[0] == '1' + assert res[0] == 1 def test_immediate1(): com = OpcodeComputer(mem="3,3,1108,-1,8,3,4,3,99") res = list(com.process_op([8])) - assert res[0] == '1' + assert res[0] == 1 def test_immediate2(): com = OpcodeComputer(mem="3,3,1107,-1,8,3,4,3,99") res = list(com.process_op([7])) - assert res[0] == '1' + assert res[0] == 1 def test_jump_position(): com = OpcodeComputer(mem="3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9") res = list(com.process_op([0])) - assert res[0] == '0' + assert res[0] == 0 def test_jump_immediate(): com = OpcodeComputer(mem="3,3,1105,-1,9,1101,0,0,12,4,12,99,1") res = list(com.process_op([0])) - assert res[0] == '0' + assert res[0] == 0 + + +def test_rel_base_copy(): + com = OpcodeComputer(mem="109,1,204,-1,1001,100,1,100,1008,100,16,101,\ + 1006,101,0,99") + res = list(com.process_op([])) + assert res == [109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, + 1006, 101, 0, 99] + + +def test_rel_base_16digit(): + com = OpcodeComputer(mem="1102,34915192,34915192,7,4,7,99,0") + res = list(com.process_op([])) + assert len(str(res[0])) == 16 + + +def test_rel_base_large(): + com = OpcodeComputer(mem="104,1125899906842624,99") + res = list(com.process_op([0])) + assert res[0] == 1125899906842624 diff --git a/days/test_day2.py b/days/test_day2.py index cec0be0..4017400 100644 --- a/days/test_day2.py +++ b/days/test_day2.py @@ -20,8 +20,8 @@ def test_day2b(): b: int = 0 for a, b in [(x, y) for x in range(100) for y in range(100)]: comp.reset() - comp.memory[1] = int(a) - comp.memory[2] = int(b) + comp.memory[1] = a + comp.memory[2] = b result = comp.process_all() if result == 19690720: diff --git a/days/test_day5.py b/days/test_day5.py index b46545b..bb1991e 100644 --- a/days/test_day5.py +++ b/days/test_day5.py @@ -10,11 +10,11 @@ def test_day5a(): sut = OpcodeComputer(inputfile) outp = list(sut.process_op([1])) - assert int(outp[-1]) == 8332629 + assert outp[-1] == 8332629 def test_day5b(): sut = OpcodeComputer(inputfile) outp = list(sut.process_op([5])) - assert int(outp[0]) == 8805067 + assert outp[0] == 8805067 diff --git a/days/test_day7.py b/days/test_day7.py index 3dc3f4a..1326a44 100644 --- a/days/test_day7.py +++ b/days/test_day7.py @@ -15,7 +15,7 @@ def test_day7a(): for conf in configs: sig: int = 0 for phase in conf: - sig = int(list(com.process_op([phase, sig]))[0]) + sig = list(com.process_op([phase, sig]))[0] res = sig if sig > res else res assert res == 21000 @@ -38,7 +38,7 @@ def test_day7b(): while True: for i in range(5): buffer[i].append(sig) - sig = int(next(comps[i])) + sig = next(comps[i]) except StopIteration: pass res = sig if sig > res else res diff --git a/days/test_day9.py b/days/test_day9.py new file mode 100644 index 0000000..7906aeb --- /dev/null +++ b/days/test_day9.py @@ -0,0 +1,19 @@ +import itertools +import os + +from .comp import OpcodeComputer + + +inputfile = os.path.join(os.path.dirname(__file__), "input/day9_input") + + +def test_day9a(): + comp = OpcodeComputer(inputfile) + res = list(comp.process_op([1])) + assert res[0] == 3638931938 + + +def test_day9b(): + comp = OpcodeComputer(inputfile) + res = list(comp.process_op([2])) + assert res[0] == 86025