Refactor day 7 intcode for part 2

This commit is contained in:
Gabriel Augendre 2020-03-05 22:31:54 +01:00
parent ba3b3b90ee
commit 98ad800491
No known key found for this signature in database
GPG key ID: 1E693F4CE4AEE7B4
3 changed files with 92 additions and 87 deletions

View file

@ -1,5 +1,5 @@
import itertools import itertools
from typing import List from typing import List, Union
NUMBER_OF_PARAMS_MAP = { NUMBER_OF_PARAMS_MAP = {
1: 3, 1: 3,
@ -24,36 +24,39 @@ LAST_IS_RESULT_MAP = {
} }
class Computer:
@staticmethod
def get_value(program, args, param_modes, index): def get_value(program, args, param_modes, index):
if param_modes[index] == 0: if param_modes[index] == 0:
return program[args[index]] return program[args[index]]
return args[index] return args[index]
@staticmethod
def parse_args(program, raw_args, param_modes, last_is_result=False): def parse_args(program, raw_args, param_modes, last_is_result=False):
args = [] args = []
limit = -1 if last_is_result else None limit = -1 if last_is_result else None
for i, arg in enumerate(raw_args[:limit]): for i, arg in enumerate(raw_args[:limit]):
args.append(get_value(program, raw_args, param_modes, i)) args.append(Computer.get_value(program, raw_args, param_modes, i))
if last_is_result: if last_is_result:
args.append(raw_args[-1]) args.append(raw_args[-1])
return args 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(lst: List[int], inputs: List[int] = None) -> List[int]: def compute(self, inputs: List[int] = None) -> Union[int, None]:
if inputs is None: if inputs is None:
inputs = [] inputs = []
self.inputs.extend(inputs)
program = lst.copy() # type: List[int]
outputs = [] # type: List[int]
pointer = 0 pointer = 0
while pointer < len(program): while pointer < len(self.program):
pointer_moved = False pointer_moved = False
instruction = str(program[pointer]) instruction = str(self.program[pointer])
code = int(instruction[-2:]) code = int(instruction[-2:])
if code == 99: if code == 99:
return outputs raise
number_of_params = NUMBER_OF_PARAMS_MAP[code] number_of_params = NUMBER_OF_PARAMS_MAP[code]
offset = number_of_params + 1 offset = number_of_params + 1
@ -62,28 +65,29 @@ def compute(lst: List[int], inputs: List[int] = None) -> List[int]:
param_modes = list(map(int, reversed(param_modes))) param_modes = list(map(int, reversed(param_modes)))
raw_params = [] raw_params = []
for i in range(1, offset): for i in range(1, offset):
raw_params.append(program[pointer + i]) raw_params.append(self.program[pointer + i])
last_is_result = LAST_IS_RESULT_MAP[code] last_is_result = LAST_IS_RESULT_MAP[code]
params = parse_args(program, raw_params, param_modes, last_is_result) params = self.parse_args(
self.program, raw_params, param_modes, last_is_result
)
if code == 1: if code == 1:
# Addition # Addition
program[params[2]] = params[0] + params[1] self.program[params[2]] = params[0] + params[1]
elif code == 2: elif code == 2:
# Multiplication # Multiplication
program[params[2]] = params[0] * params[1] self.program[params[2]] = params[0] * params[1]
elif code == 3: elif code == 3:
# Input # Input
try: try:
input_value = int(inputs.pop(0)) input_value = int(self.inputs.pop(0))
except IndexError: except IndexError:
input_value = int(input(f"Input for instruction {pointer}\n> ")) input_value = int(input(f"Input for instruction {pointer}\n> "))
program[params[0]] = input_value self.program[params[0]] = input_value
elif code == 4: elif code == 4:
# Output # Output
output_value = params[0] return params[0]
outputs.append(output_value)
elif code == 5: elif code == 5:
# Jump if true # Jump if true
if params[0] != 0: if params[0] != 0:
@ -97,15 +101,15 @@ def compute(lst: List[int], inputs: List[int] = None) -> List[int]:
elif code == 7: elif code == 7:
# Less than # Less than
if params[0] < params[1]: if params[0] < params[1]:
program[params[2]] = 1 self.program[params[2]] = 1
else: else:
program[params[2]] = 0 self.program[params[2]] = 0
elif code == 8: elif code == 8:
# Equals # Equals
if params[0] == params[1]: if params[0] == params[1]:
program[params[2]] = 1 self.program[params[2]] = 1
else: else:
program[params[2]] = 0 self.program[params[2]] = 0
else: else:
raise ValueError(f"Something bad happened, code={code}") raise ValueError(f"Something bad happened, code={code}")
@ -113,20 +117,19 @@ def compute(lst: List[int], inputs: List[int] = None) -> List[int]:
if not pointer_moved: if not pointer_moved:
pointer += offset pointer += offset
return program
def main(): def main():
with open("inputs/day07") as input_file: with open("inputs/day07") as input_file:
original_program = list(map(int, input_file.read().split(","))) original_program = list(map(int, input_file.read().split(",")))
values = set() values = set()
for phase in itertools.permutations("01234"): for phase in itertools.permutations("01234"):
amp1 = compute(original_program, [int(phase[0]), 0]) amp1 = Computer(original_program, [int(phase[0])]).compute([0])
amp2 = compute(original_program, [int(phase[1]), amp1[0]]) amp2 = Computer(original_program, [int(phase[1])]).compute([amp1])
amp3 = compute(original_program, [int(phase[2]), amp2[0]]) amp3 = Computer(original_program, [int(phase[2])]).compute([amp2])
amp4 = compute(original_program, [int(phase[3]), amp3[0]]) amp4 = Computer(original_program, [int(phase[3])]).compute([amp3])
amp5 = compute(original_program, [int(phase[4]), amp4[0]]) amp5 = Computer(original_program, [int(phase[4])]).compute([amp4])
values.add(amp5[0]) values.add(amp5)
print(max(values)) print(max(values))

1
2019/inputs/day07-ex4 Normal file
View file

@ -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

1
2019/inputs/day07-ex5 Normal file
View file

@ -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