diff --git a/day11/py/intcode_changes_since_day_9.diff b/day11/py/intcode_changes_since_day_9.diff index a4d0bd1..a27fbe4 100644 --- a/day11/py/intcode_changes_since_day_9.diff +++ b/day11/py/intcode_changes_since_day_9.diff @@ -1,5 +1,5 @@ --- day9intcode.py 2019-12-11 01:02:10.952864966 -0500 -+++ day11intcode.py 2019-12-11 01:02:34.308613523 -0500 ++++ day11intcode.py 2019-12-11 01:14:04.585182158 -0500 @@ -1,7 +1,6 @@ import collections import sys @@ -9,7 +9,52 @@ # Halt indicates that the assembled program should terminate class Halt(Exception): -@@ -136,7 +135,6 @@ +@@ -35,14 +34,14 @@ + # Opcodes that write to memory as their last parameter + MEMORY_OPCODES = (OPCODE_ADD, OPCODE_MULTIPLY, OPCODE_INPUT, OPCODE_LESS_THAN, OPCODE_EQUALS) + +- def __init__(self, instruction: int): ++ def __init__(self, instruction: int, rel_base: int = 0): + # The opcode is the first two digits of the number, the rest are parameter modes + self.opcode: int = instruction % 100 + if self.opcode not in Operation.ALL_OPCODES: + raise ValueError(f"Bad opcode: {self.opcode}") + self.modes: Tuple[int, ...] = self._extract_parameter_modes(instruction//100) + self.output = None +- self.rel_base = 0 ++ self.rel_base = rel_base + + def _extract_parameter_modes(self, raw_modes) -> Tuple[int, ...]: + PARAMETER_COUNTS = { +@@ -69,8 +68,8 @@ + return tuple(modes) + + # Run the given operation, starting at the given instruction pointer +- # Returns the address that the instruction pointer should become, the relative base, followed by the output of the operation, if any +- def run(self, memory: Memory, instruction_pointer: int, rel_base: int = 0, program_input: Optional[int] = None) -> Tuple[int, int, Optional[int]]: ++ # Returns the address that the instruction pointer should become ++ def run(self, memory: Memory, instruction_pointer: int, program_input: Optional[int] = None) -> int: + OPERATION_FUNCS = { + # nop for terminate + Operation.OPCODE_TERMINATE: Operation.terminate, +@@ -87,7 +86,6 @@ + + # Reset the output and rel base of a previous run + self.output = None +- self.rel_base = rel_base + + args = [] + for i, mode in enumerate(self.modes): +@@ -120,7 +118,7 @@ + if jump_addr is not None: + out_addr = jump_addr + +- return out_addr, self.rel_base, self.output ++ return out_addr + + def terminate(self, memory: Memory) -> None: + raise Halt("catch fire") +@@ -136,7 +134,6 @@ def output(self, memory: Memory, value: int) -> None: self.output = value @@ -17,8 +62,14 @@ def jump_if_true(self, memory: Memory, test_value: int, new_instruction_pointer: int) -> Optional[int]: return new_instruction_pointer if test_value != 0 else None -@@ -154,13 +152,13 @@ - self.rel_base += rel_base +@@ -150,31 +147,33 @@ + def equals(self, memory: Memory, a: int, b: int, loc: int) -> None: + memory[loc] = int(a == b) + +- def set_rel_base(self, memory: Memory, rel_base: int) -> None: +- self.rel_base += rel_base ++ def set_rel_base(self, memory: Memory, base_delta: int) -> None: ++ self.rel_base += base_delta -# Executes the program, returning the instruction pointer to continue at (if the program paused) and a list of all @@ -26,7 +77,7 @@ -def execute_program(memory: Memory, program_inputs: List[int], initial_instruction_pointer: int = 0) -> (Optional[int], List[int]): +# Executes the program, returning the instruction pointer to continue at (if the program paused), the relative base, +# and a list of all outputs that occurred during the program's execution -+def execute_program(memory: Memory, program_inputs: List[int], initial_instruction_pointer: int = 0, initial_rel_base: int = 0) -> (Optional[int], int, List[int]): ++def execute_program(memory: Memory, program_inputs: List[int], initial_instruction_pointer: int = 0, initial_rel_base: int = 0) -> Tuple[Optional[int], int, List[int]]: i = initial_instruction_pointer input_cursor = 0 - rel_base = 0 @@ -34,8 +85,10 @@ + rel_base = initial_rel_base # Go up to the maximum address, not the number of addresses while i < max(memory.keys()): - operation = Operation(memory[i]) -@@ -169,7 +167,7 @@ +- operation = Operation(memory[i]) ++ operation = Operation(memory[i], rel_base) + program_input = None + # If we're looking for input if operation.opcode == Operation.OPCODE_INPUT: # If we are out of input, don't fail out, but rather just pause execution if input_cursor >= len(program_inputs): @@ -44,7 +97,15 @@ program_input = program_inputs[input_cursor] input_cursor += 1 -@@ -182,4 +180,4 @@ + try: +- i, rel_base, output = operation.run(memory, i, rel_base, program_input) ++ i = operation.run(memory, i, program_input) ++ output = operation.output ++ rel_base = operation.rel_base + except Halt: + break + +@@ -182,4 +181,4 @@ outputs.append(output) # The program is finished, and we are saying there is no instruction pointer diff --git a/day11/py/main.py b/day11/py/main.py index bad183a..cae2ea4 100644 --- a/day11/py/main.py +++ b/day11/py/main.py @@ -34,14 +34,14 @@ class Operation: # Opcodes that write to memory as their last parameter MEMORY_OPCODES = (OPCODE_ADD, OPCODE_MULTIPLY, OPCODE_INPUT, OPCODE_LESS_THAN, OPCODE_EQUALS) - def __init__(self, instruction: int): + def __init__(self, instruction: int, rel_base: int = 0): # The opcode is the first two digits of the number, the rest are parameter modes self.opcode: int = instruction % 100 if self.opcode not in Operation.ALL_OPCODES: raise ValueError(f"Bad opcode: {self.opcode}") self.modes: Tuple[int, ...] = self._extract_parameter_modes(instruction//100) self.output = None - self.rel_base = 0 + self.rel_base = rel_base def _extract_parameter_modes(self, raw_modes) -> Tuple[int, ...]: PARAMETER_COUNTS = { @@ -68,8 +68,8 @@ class Operation: return tuple(modes) # Run the given operation, starting at the given instruction pointer - # Returns the address that the instruction pointer should become, the relative base, followed by the output of the operation, if any - def run(self, memory: Memory, instruction_pointer: int, rel_base: int = 0, program_input: Optional[int] = None) -> Tuple[int, int, Optional[int]]: + # Returns the address that the instruction pointer should become + def run(self, memory: Memory, instruction_pointer: int, program_input: Optional[int] = None) -> int: OPERATION_FUNCS = { # nop for terminate Operation.OPCODE_TERMINATE: Operation.terminate, @@ -86,7 +86,6 @@ class Operation: # Reset the output and rel base of a previous run self.output = None - self.rel_base = rel_base args = [] for i, mode in enumerate(self.modes): @@ -119,7 +118,7 @@ class Operation: if jump_addr is not None: out_addr = jump_addr - return out_addr, self.rel_base, self.output + return out_addr def terminate(self, memory: Memory) -> None: raise Halt("catch fire") @@ -148,20 +147,20 @@ class Operation: def equals(self, memory: Memory, a: int, b: int, loc: int) -> None: memory[loc] = int(a == b) - def set_rel_base(self, memory: Memory, rel_base: int) -> None: - self.rel_base += rel_base + def set_rel_base(self, memory: Memory, base_delta: int) -> None: + self.rel_base += base_delta # Executes the program, returning the instruction pointer to continue at (if the program paused), the relative base, # and a list of all outputs that occurred during the program's execution -def execute_program(memory: Memory, program_inputs: List[int], initial_instruction_pointer: int = 0, initial_rel_base: int = 0) -> (Optional[int], int, List[int]): +def execute_program(memory: Memory, program_inputs: List[int], initial_instruction_pointer: int = 0, initial_rel_base: int = 0) -> Tuple[Optional[int], int, List[int]]: i = initial_instruction_pointer input_cursor = 0 outputs = [] rel_base = initial_rel_base # Go up to the maximum address, not the number of addresses while i < max(memory.keys()): - operation = Operation(memory[i]) + operation = Operation(memory[i], rel_base) program_input = None # If we're looking for input if operation.opcode == Operation.OPCODE_INPUT: @@ -172,7 +171,9 @@ def execute_program(memory: Memory, program_inputs: List[int], initial_instructi input_cursor += 1 try: - i, rel_base, output = operation.run(memory, i, rel_base, program_input) + i = operation.run(memory, i, program_input) + output = operation.output + rel_base = operation.rel_base except Halt: break