mirror of
https://github.com/Crocmagnon/advent-of-code.git
synced 2024-11-21 22:18:12 +01:00
Solve day 9 part 1
This commit is contained in:
parent
8c3b6556a7
commit
aee6beea29
5 changed files with 194 additions and 0 deletions
190
2019/day09-intcode.py
Normal file
190
2019/day09-intcode.py
Normal file
|
@ -0,0 +1,190 @@
|
|||
import itertools
|
||||
from collections import defaultdict
|
||||
from typing import List, Union
|
||||
|
||||
RELATIVE_MODE = 2
|
||||
POSITION_MODE = 0
|
||||
VALUE_MODE = 1
|
||||
NUMBER_OF_PARAMS_MAP = {
|
||||
1: 3,
|
||||
2: 3,
|
||||
3: 1,
|
||||
4: 1,
|
||||
5: 2,
|
||||
6: 2,
|
||||
7: 3,
|
||||
8: 3,
|
||||
9: 1,
|
||||
}
|
||||
|
||||
LAST_IS_RESULT_MAP = {
|
||||
1: True,
|
||||
2: True,
|
||||
3: True,
|
||||
4: False,
|
||||
5: False,
|
||||
6: False,
|
||||
7: True,
|
||||
8: True,
|
||||
9: False,
|
||||
}
|
||||
|
||||
|
||||
class IntcodeOutput(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
|
||||
class Computer:
|
||||
def __init__(self, initial_program: List[int], inputs: List[int] = None):
|
||||
self.program = defaultdict(int, enumerate(initial_program))
|
||||
if inputs is None:
|
||||
inputs = []
|
||||
self.inputs = inputs.copy() # type: List[int]
|
||||
self.pointer = 0
|
||||
self.pointer_moved = False
|
||||
self.relative_base = 0
|
||||
|
||||
def get_value(self, args, param_modes, index):
|
||||
if param_modes[index] == RELATIVE_MODE:
|
||||
return self.program[self.relative_base + args[index]]
|
||||
if param_modes[index] == POSITION_MODE:
|
||||
return self.program[args[index]]
|
||||
return args[index]
|
||||
|
||||
def parse_args(self, raw_args, param_modes, code):
|
||||
args = []
|
||||
last_is_result = LAST_IS_RESULT_MAP[code]
|
||||
limit = -1 if last_is_result else None
|
||||
for i, arg in enumerate(raw_args[:limit]):
|
||||
args.append(self.get_value(raw_args, param_modes, i))
|
||||
if last_is_result:
|
||||
if param_modes[-1] == RELATIVE_MODE:
|
||||
args.append(raw_args[-1] + self.relative_base)
|
||||
else:
|
||||
args.append(raw_args[-1])
|
||||
return args
|
||||
|
||||
def _move_pointer(self, position):
|
||||
self.pointer = position
|
||||
self.pointer_moved = True
|
||||
|
||||
def _update_pointer(self, code):
|
||||
offset = self.get_offset(code)
|
||||
if not self.pointer_moved:
|
||||
self.pointer += offset
|
||||
self.pointer_moved = False
|
||||
|
||||
def compute(self, additional_inputs: List[int] = None) -> int:
|
||||
if additional_inputs is None:
|
||||
additional_inputs = []
|
||||
self.inputs.extend(additional_inputs)
|
||||
|
||||
while self.pointer < len(self.program):
|
||||
code = self.get_code()
|
||||
try:
|
||||
self.handle_operation(code)
|
||||
except IntcodeOutput as e:
|
||||
print(e.value)
|
||||
finally:
|
||||
self._update_pointer(code)
|
||||
|
||||
def get_params(self, code):
|
||||
offset = self.get_offset(code)
|
||||
param_modes = self.get_instruction()[:-2]
|
||||
param_modes = param_modes.zfill(offset - 1)
|
||||
param_modes = list(map(int, reversed(param_modes)))
|
||||
raw_params = []
|
||||
for i in range(1, offset):
|
||||
raw_params.append(self.program[self.pointer + i])
|
||||
|
||||
params = self.parse_args(raw_params, param_modes, code)
|
||||
return params
|
||||
|
||||
def get_offset(self, code):
|
||||
number_of_params = NUMBER_OF_PARAMS_MAP[code]
|
||||
return number_of_params + 1
|
||||
|
||||
def get_code(self):
|
||||
instruction = self.get_instruction()
|
||||
code = int(instruction[-2:])
|
||||
if code == 99:
|
||||
raise StopIteration
|
||||
return code
|
||||
|
||||
def get_instruction(self):
|
||||
instruction = str(self.program[self.pointer])
|
||||
return instruction
|
||||
|
||||
def handle_operation(self, code):
|
||||
params = self.get_params(code)
|
||||
if code == 1:
|
||||
self.handle_addition(params)
|
||||
elif code == 2:
|
||||
self.handle_multiplication(params)
|
||||
elif code == 3:
|
||||
self.handle_input(params)
|
||||
elif code == 4:
|
||||
self.handle_output(params)
|
||||
elif code == 5:
|
||||
self.handle_jump_if_true(params)
|
||||
elif code == 6:
|
||||
self.handle_jump_if_false(params)
|
||||
elif code == 7:
|
||||
self.handle_less_than(params)
|
||||
elif code == 8:
|
||||
self.handle_equals(params)
|
||||
elif code == 9:
|
||||
self.handle_adjust_relative_base(params)
|
||||
else:
|
||||
raise ValueError(f"Something bad happened, code={code}")
|
||||
|
||||
def handle_addition(self, params):
|
||||
self.program[params[2]] = params[0] + params[1]
|
||||
|
||||
def handle_multiplication(self, params):
|
||||
self.program[params[2]] = params[0] * params[1]
|
||||
|
||||
def handle_input(self, params):
|
||||
self.program[params[0]] = int(self.inputs.pop(0))
|
||||
|
||||
def handle_output(self, params):
|
||||
raise IntcodeOutput(params[0])
|
||||
|
||||
def handle_jump_if_true(self, params):
|
||||
if params[0] != 0:
|
||||
self._move_pointer(params[1])
|
||||
|
||||
def handle_jump_if_false(self, params):
|
||||
if params[0] == 0:
|
||||
self._move_pointer(params[1])
|
||||
|
||||
def handle_equals(self, params):
|
||||
if params[0] == params[1]:
|
||||
self.program[params[2]] = 1
|
||||
else:
|
||||
self.program[params[2]] = 0
|
||||
|
||||
def handle_less_than(self, params):
|
||||
if params[0] < params[1]:
|
||||
self.program[params[2]] = 1
|
||||
else:
|
||||
self.program[params[2]] = 0
|
||||
|
||||
def handle_adjust_relative_base(self, params):
|
||||
self.relative_base += params[0]
|
||||
|
||||
|
||||
def main():
|
||||
with open("inputs/day09") as input_file:
|
||||
original_program = list(map(int, input_file.read().split(",")))
|
||||
computer = Computer(original_program)
|
||||
try:
|
||||
result = computer.compute([1])
|
||||
print(result)
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1
2019/inputs/day09
Normal file
1
2019/inputs/day09
Normal file
|
@ -0,0 +1 @@
|
|||
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,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,32,1,1016,1101,38,0,1012,1102,1,693,1022,1102,1,27,1007,1101,0,190,1025,1102,20,1,1019,1102,1,33,1008,1102,28,1,1013,1101,0,1,1021,1102,1,851,1026,1102,22,1,1018,1101,29,0,1005,1101,0,21,1004,1101,36,0,1009,1101,0,195,1024,1101,0,39,1002,1101,0,848,1027,1102,1,34,1003,1102,23,1,1015,1102,1,30,1010,1101,0,26,1017,1102,1,35,1001,1102,1,489,1028,1102,1,484,1029,1102,1,686,1023,1102,0,1,1020,1102,25,1,1006,1102,1,31,1014,1101,37,0,1000,1102,1,24,1011,109,23,2105,1,1,4,187,1105,1,199,1001,64,1,64,1002,64,2,64,109,-18,2102,1,-3,63,1008,63,41,63,1005,63,223,1001,64,1,64,1106,0,225,4,205,1002,64,2,64,109,2,2101,0,1,63,1008,63,33,63,1005,63,251,4,231,1001,64,1,64,1105,1,251,1002,64,2,64,109,13,21107,40,41,-8,1005,1012,269,4,257,1106,0,273,1001,64,1,64,1002,64,2,64,109,9,1205,-8,287,4,279,1105,1,291,1001,64,1,64,1002,64,2,64,109,-38,2101,0,9,63,1008,63,34,63,1005,63,315,1001,64,1,64,1106,0,317,4,297,1002,64,2,64,109,18,21108,41,38,1,1005,1010,337,1001,64,1,64,1106,0,339,4,323,1002,64,2,64,109,-5,2107,30,1,63,1005,63,359,1001,64,1,64,1106,0,361,4,345,1002,64,2,64,109,14,21101,42,0,-7,1008,1011,42,63,1005,63,387,4,367,1001,64,1,64,1106,0,387,1002,64,2,64,109,-18,1208,0,39,63,1005,63,403,1106,0,409,4,393,1001,64,1,64,1002,64,2,64,109,3,1207,-1,38,63,1005,63,425,1106,0,431,4,415,1001,64,1,64,1002,64,2,64,109,-8,1201,5,0,63,1008,63,35,63,1005,63,455,1001,64,1,64,1106,0,457,4,437,1002,64,2,64,109,30,1206,-4,469,1106,0,475,4,463,1001,64,1,64,1002,64,2,64,109,10,2106,0,-7,4,481,1106,0,493,1001,64,1,64,1002,64,2,64,109,-24,21102,43,1,3,1008,1014,40,63,1005,63,517,1001,64,1,64,1105,1,519,4,499,1002,64,2,64,109,-4,2108,41,-5,63,1005,63,539,1001,64,1,64,1106,0,541,4,525,1002,64,2,64,109,18,21101,44,0,-8,1008,1017,47,63,1005,63,561,1105,1,567,4,547,1001,64,1,64,1002,64,2,64,109,-24,1202,6,1,63,1008,63,27,63,1005,63,589,4,573,1106,0,593,1001,64,1,64,1002,64,2,64,109,7,1208,-5,34,63,1005,63,611,4,599,1106,0,615,1001,64,1,64,1002,64,2,64,109,-5,1207,6,37,63,1005,63,637,4,621,1001,64,1,64,1106,0,637,1002,64,2,64,109,23,1206,-6,655,4,643,1001,64,1,64,1105,1,655,1002,64,2,64,109,-10,2107,32,-8,63,1005,63,673,4,661,1105,1,677,1001,64,1,64,1002,64,2,64,109,5,2105,1,2,1001,64,1,64,1106,0,695,4,683,1002,64,2,64,109,-17,1202,0,1,63,1008,63,20,63,1005,63,715,1106,0,721,4,701,1001,64,1,64,1002,64,2,64,109,-4,1201,4,0,63,1008,63,21,63,1005,63,743,4,727,1106,0,747,1001,64,1,64,1002,64,2,64,109,10,1205,10,763,1001,64,1,64,1105,1,765,4,753,1002,64,2,64,109,1,21102,45,1,1,1008,1012,45,63,1005,63,787,4,771,1105,1,791,1001,64,1,64,1002,64,2,64,109,-4,2102,1,-2,63,1008,63,29,63,1005,63,813,4,797,1105,1,817,1001,64,1,64,1002,64,2,64,109,-4,2108,33,5,63,1005,63,835,4,823,1105,1,839,1001,64,1,64,1002,64,2,64,109,23,2106,0,1,1106,0,857,4,845,1001,64,1,64,1002,64,2,64,109,-12,21108,46,46,1,1005,1015,879,4,863,1001,64,1,64,1106,0,879,1002,64,2,64,109,10,21107,47,46,-5,1005,1019,899,1001,64,1,64,1105,1,901,4,885,4,64,99,21101,27,0,1,21101,915,0,0,1105,1,922,21201,1,52134,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1105,1,922,22101,0,1,-1,21201,-2,-3,1,21101,0,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,21201,-2,0,-2,109,-3,2106,0,0
|
1
2019/inputs/day09-ex1
Normal file
1
2019/inputs/day09-ex1
Normal file
|
@ -0,0 +1 @@
|
|||
109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99
|
1
2019/inputs/day09-ex2
Normal file
1
2019/inputs/day09-ex2
Normal file
|
@ -0,0 +1 @@
|
|||
1102,34915192,34915192,7,4,7,99,0
|
1
2019/inputs/day09-ex3
Normal file
1
2019/inputs/day09-ex3
Normal file
|
@ -0,0 +1 @@
|
|||
104,1125899906842624,99
|
Loading…
Reference in a new issue