from typing import List, Dict, Tuple, Iterator class OpcodeComputer(): """OpcodeCOmputer for Advent of Code 2019 OpcodeComputer as specified by day 2 and 5 of the Advent of \ Code 2019 challenge. .. _Advent of Code 2019 day 2 https://adventofcode.com/2019/day/2 .. _Advent of Code 2019 day 5 https://adventofcode.com/2019/day/5 """ __last_result: int = 0 __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 = dict(enumerate([int(k) for k in inp.split(',')])) self.memory = self.__initial_mem 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 Args: pc (int): current instruction pointer mem (List[int]): program code Returns: Tuple[int, int, int, int]: current opcode, parameter a, b and c """ i: str = "{0:05d}".format(mem[pc]) a: int = 0 b: int = 0 c: int = 0 try: 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[int]: """Run program code Args: mem (List[int]): Memory to run OpcodeComputer on 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 = mem[pc] while cmd != 99: cmd, a, b, c = self.parse_param(pc, mem, base) if cmd == 1: mem[c] = read(a) + read(b) pc += 4 elif cmd == 2: mem[c] = read(a) * read(b) pc += 4 elif cmd == 3: mem[a] = int(inp.pop(0)) pc += 2 elif cmd == 4: yield read(a) pc += 2 elif cmd == 5: 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: mem[c] = 1 if mem[a] < mem[b] else 0 pc += 4 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] self.__last_result = mem[0] def process_all(self) -> int: list(self.process_op()) return self.__last_result def reset(self): self.memory = self.__initial_mem.copy()