From 944bad6c5749a5b3fc4150d354155debcd449412 Mon Sep 17 00:00:00 2001 From: Xevion Date: Sat, 7 Dec 2019 15:45:13 -0600 Subject: [PATCH] day 5 part 1 & 2 rehaul study copy --- 2019/day-5/python/main.py | 158 +++++++++++++++++++++++++------------- 1 file changed, 106 insertions(+), 52 deletions(-) diff --git a/2019/day-5/python/main.py b/2019/day-5/python/main.py index 9f4d29d..8fc138e 100644 --- a/2019/day-5/python/main.py +++ b/2019/day-5/python/main.py @@ -1,60 +1,114 @@ import os import sys -PATH = os.path.join(sys.path[0], '..', 'input') -memory = list(open(PATH, 'r').read().split(',')) +class IntCodeExit(Exception): + pass -def getParams(pos, opcode, type1, type2, type3): - params = [] - if opcode in ['03', '04']: - params.append(memory[pos + 1]) - # if type1 == '0': - # params[-1] = memory[int(params[-1])] - elif opcode in ['01', '02']: - params.append(memory[pos + 1]) - if type1 == '0': - params[-1] = memory[int(params[-1])] - params.append(memory[pos + 2]) - if type2 == '0': - params[-1] = memory[int(params[-1])] - params.append(memory[pos + 3]) - # if type3 == '0': - # params[-1] = memory[int(params[-1])] - # print(memory[pos:pos+4]) - elif opcode in ['99']: - pass - return params +class IntCodeStatus(Exception): + def __init__(self, code): + self.code = code + return super().__init__(f"Status code '{self.code}' was raised by the Intcode Computer.") -inputs = [1] -pos = 0 +class IntcodeComputer(object): + def __init__(self, memory, _input=[], pointer=0, silent=True): + self.memory = memory + self._input = iter(_input) + self.pointer = pointer + self.silent = silent -while pos < len(memory) - 4: - if len(memory[pos]) < 5: - memory[pos] = ('0' * (5 - len(memory[pos]))) + memory[pos] - opcode = memory[pos][-2:] + self.READ_MODES = { + 0: (self.point, self.point, self.point), + 100: (self.point, self.point, self.value), + 10: (self.point, self.value, self.point), + 110: (self.point, self.value, self.value), + 1: (self.value, self.point, self.point), + 101: (self.value, self.point, self.value), + 11: (self.value, self.value, self.point), + 111: (self.value, self.value, self.value), + } - type1 = memory[pos][-3] - type2 = memory[pos][-4] - type3 = memory[pos][-5] + self.OP_CODES = { + 1 : (self.op_add, 3), + 2 : (self.op_multiply, 3), + 3 : (self.op_input, 1), + 4 : (self.op_print, 1), + 5 : (self.op_jit, 2), + 6 : (self.op_jif, 2), + 7 : (self.op_lth, 3), + 8 : (self.op_eq, 3), + 99 : (self.op_exit, 0) + } - params = getParams(pos, opcode, type1, type2, type3) - if opcode == '01': - memory[int(params[2])] = str(int(params[0]) + int(params[1])) - pos += 4 - elif opcode == '02': - memory[int(params[2])] = str(int(params[0]) * int(params[1])) - pos += 4 - elif opcode == '03': - memory[int(params[0])] = str(inputs.pop(0)) - pos += 2 - elif opcode == '04': - print(f'OUTPUT: {params[0]}') - pos += 2 - elif opcode == '99': - print('PROGRAM BREAK') - pos += 1 - break - else: - print(f'Unknown Opcode "{opcode}"') - break - print(f'#{pos // 4} {type3}{type2}{type1}{opcode} {params}') \ No newline at end of file + def hasNext(self): + return self.pointer < len(self.memory) + + def next(self): + op, params, offset = self.read(self.pointer) + self.pointer += offset + op(*params) + + def run(self): + statuses = [] + while self.hasNext(): + try: + self.next() + except IntCodeStatus as s: + statuses.append(s.code) + except IntCodeExit: + return statuses[-1] + + def read(self, pointer): + code = self.memory[pointer] + readmodes, opcode = divmod(code, 100) + op, nargs = self.OP_CODES[opcode] + argument_functions = self.READ_MODES[readmodes][:nargs] + parameters = [f(ptr) for f, ptr in zip(argument_functions, range(pointer+1, pointer+4))] + return op, parameters, nargs + 1 + + def op_add(self, param1, param2, param3): + self.memory[param3] = self.memory[param1] + self.memory[param2] + + def op_multiply(self, param1, param2, param3): + self.memory[param3] = self.memory[param1] * self.memory[param2] + + def op_input(self, param1): + self.memory[param1] = next(self._input) + + def op_print(self, param1): + if not self.silent: + print(self.memory[param1]) + raise IntCodeStatus(self.memory[param1]) + + def op_exit(self): + raise IntCodeExit() + + def op_jit(self, param1, param2): + if self.memory[param1] != 0: + self.pointer = self.memory[param2] + + def op_jif(self, param1, param2): + if self.memory[param1] == 0: + self.pointer = self.memory[param2] + + def op_lth(self, param1, param2, param3): + self.memory[param3] = 1 if self.memory[param1] < self.memory[param2] else 0 + + def op_eq(self, param1, param2, param3): + self.memory[param3] = 1 if self.memory[param1] == self.memory[param2] else 0 + + def value(self, location): + return location + + def point(self, location): + ptr = self.memory[location] + return ptr + +def day5(memory, _input, silent=True): + computer = IntcodeComputer(memory.copy(), _input=_input, silent=silent) + print(computer.run()) + +path = os.path.join(sys.path[0], '..', 'input') +data = list(map(int, open(path, 'r').read().split(','))) + +day5(data, _input=[1]) +day5(data, _input=[5]) \ No newline at end of file