diff --git a/2019/day07-intcode.py b/2019/day07-intcode.py index 17f18b8..36295e6 100644 --- a/2019/day07-intcode.py +++ b/2019/day07-intcode.py @@ -1,5 +1,5 @@ import itertools -from typing import List +from typing import List, Union NUMBER_OF_PARAMS_MAP = { 1: 3, @@ -24,96 +24,98 @@ LAST_IS_RESULT_MAP = { } -def get_value(program, args, param_modes, index): - if param_modes[index] == 0: - return program[args[index]] - return args[index] +class Computer: + @staticmethod + def get_value(program, args, param_modes, index): + if param_modes[index] == 0: + return program[args[index]] + return args[index] + @staticmethod + def parse_args(program, raw_args, param_modes, last_is_result=False): + args = [] + limit = -1 if last_is_result else None + for i, arg in enumerate(raw_args[:limit]): + args.append(Computer.get_value(program, raw_args, param_modes, i)) + if last_is_result: + args.append(raw_args[-1]) + return args -def parse_args(program, raw_args, param_modes, last_is_result=False): - args = [] - limit = -1 if last_is_result else None - for i, arg in enumerate(raw_args[:limit]): - args.append(get_value(program, raw_args, param_modes, i)) - if last_is_result: - args.append(raw_args[-1]) - return args + def __init__(self, initial_program: List[int], inputs: List[int] = None): + self.program = initial_program.copy() # type: List[int] + self.inputs = inputs.copy() # type: List[int] + def compute(self, inputs: List[int] = None) -> Union[int, None]: + if inputs is None: + inputs = [] + self.inputs.extend(inputs) -def compute(lst: List[int], inputs: List[int] = None) -> List[int]: - if inputs is None: - inputs = [] + pointer = 0 + while pointer < len(self.program): + pointer_moved = False + instruction = str(self.program[pointer]) + code = int(instruction[-2:]) + if code == 99: + raise - program = lst.copy() # type: List[int] - outputs = [] # type: List[int] + number_of_params = NUMBER_OF_PARAMS_MAP[code] + offset = number_of_params + 1 + param_modes = instruction[:-2] + param_modes = param_modes.zfill(number_of_params) + param_modes = list(map(int, reversed(param_modes))) + raw_params = [] + for i in range(1, offset): + raw_params.append(self.program[pointer + i]) - pointer = 0 - while pointer < len(program): - pointer_moved = False - instruction = str(program[pointer]) - code = int(instruction[-2:]) - if code == 99: - return outputs + last_is_result = LAST_IS_RESULT_MAP[code] + params = self.parse_args( + self.program, raw_params, param_modes, last_is_result + ) - number_of_params = NUMBER_OF_PARAMS_MAP[code] - offset = number_of_params + 1 - param_modes = instruction[:-2] - param_modes = param_modes.zfill(number_of_params) - param_modes = list(map(int, reversed(param_modes))) - raw_params = [] - for i in range(1, offset): - raw_params.append(program[pointer + i]) + if code == 1: + # Addition + self.program[params[2]] = params[0] + params[1] + elif code == 2: + # Multiplication + self.program[params[2]] = params[0] * params[1] + elif code == 3: + # Input + try: + input_value = int(self.inputs.pop(0)) + except IndexError: + input_value = int(input(f"Input for instruction {pointer}\n> ")) + self.program[params[0]] = input_value + elif code == 4: + # Output + return params[0] + elif code == 5: + # Jump if true + if params[0] != 0: + pointer = params[1] + pointer_moved = True + elif code == 6: + # Jump if false + if params[0] == 0: + pointer = params[1] + pointer_moved = True + elif code == 7: + # Less than + if params[0] < params[1]: + self.program[params[2]] = 1 + else: + self.program[params[2]] = 0 + elif code == 8: + # Equals + if params[0] == params[1]: + self.program[params[2]] = 1 + else: + self.program[params[2]] = 0 - last_is_result = LAST_IS_RESULT_MAP[code] - params = parse_args(program, raw_params, param_modes, last_is_result) - - if code == 1: - # Addition - program[params[2]] = params[0] + params[1] - elif code == 2: - # Multiplication - program[params[2]] = params[0] * params[1] - elif code == 3: - # Input - try: - input_value = int(inputs.pop(0)) - except IndexError: - input_value = int(input(f"Input for instruction {pointer}\n> ")) - program[params[0]] = input_value - elif code == 4: - # Output - output_value = params[0] - outputs.append(output_value) - elif code == 5: - # Jump if true - if params[0] != 0: - pointer = params[1] - pointer_moved = True - elif code == 6: - # Jump if false - if params[0] == 0: - pointer = params[1] - pointer_moved = True - elif code == 7: - # Less than - if params[0] < params[1]: - program[params[2]] = 1 else: - program[params[2]] = 0 - elif code == 8: - # Equals - if params[0] == params[1]: - program[params[2]] = 1 - else: - program[params[2]] = 0 + raise ValueError(f"Something bad happened, code={code}") - else: - raise ValueError(f"Something bad happened, code={code}") - - if not pointer_moved: - pointer += offset - - return program + if not pointer_moved: + pointer += offset def main(): @@ -121,12 +123,13 @@ def main(): original_program = list(map(int, input_file.read().split(","))) values = set() for phase in itertools.permutations("01234"): - amp1 = compute(original_program, [int(phase[0]), 0]) - amp2 = compute(original_program, [int(phase[1]), amp1[0]]) - amp3 = compute(original_program, [int(phase[2]), amp2[0]]) - amp4 = compute(original_program, [int(phase[3]), amp3[0]]) - amp5 = compute(original_program, [int(phase[4]), amp4[0]]) - values.add(amp5[0]) + amp1 = Computer(original_program, [int(phase[0])]).compute([0]) + amp2 = Computer(original_program, [int(phase[1])]).compute([amp1]) + amp3 = Computer(original_program, [int(phase[2])]).compute([amp2]) + amp4 = Computer(original_program, [int(phase[3])]).compute([amp3]) + amp5 = Computer(original_program, [int(phase[4])]).compute([amp4]) + values.add(amp5) + print(max(values)) diff --git a/2019/inputs/day07-ex4 b/2019/inputs/day07-ex4 new file mode 100644 index 0000000..4363e8e --- /dev/null +++ b/2019/inputs/day07-ex4 @@ -0,0 +1 @@ +3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5 \ No newline at end of file diff --git a/2019/inputs/day07-ex5 b/2019/inputs/day07-ex5 new file mode 100644 index 0000000..5ed292b --- /dev/null +++ b/2019/inputs/day07-ex5 @@ -0,0 +1 @@ +3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10 \ No newline at end of file