def run_parallel(self, phase_settings: List[int], feedback=True) -> int: # TODO(tr) Linkling the input to output like that is a bit disgusting, we should create a special generator # so that we can reset the output on the start of run() programs = [ Program([m for m in self._initial_memory]), ] for i, setting in enumerate(phase_settings[1:], start=1): programs[i - 1].outputs = [setting] prog = Program([m for m in self._initial_memory], inputs=programs[i - 1].outputs) programs.append(prog) if feedback: programs[-1].outputs = [phase_settings[0], 0] programs[0].reset_inputs(programs[-1].outputs) else: programs[0].reset_inputs([phase_settings[0], 0]) input_errors = { i: False for i in range(0, len(programs)) } finished = { i: False for i in range(0, len(programs)) } global_pointer = 1 while not all(finished.values()): for i, p in enumerate(programs): try: if p.pointer is not None: p.pointer = p.execute(p.pointer) else: # print(f'Skipping program {i}') finished[i] = True except InputError: # print(f'Ignoring input error from program {i}') # IO wait input_errors[i] = True else: input_errors[i] = False if all(input_errors.values()): raise RuntimeError('Deadlock') global_pointer += 1 print(f'Done in {global_pointer} iterations') return programs[-1].outputs[-1]
def run(self, start_position: Position=None, start_colour: int=Black, debug=False): if start_position is None: start_position = Position(0, 0) self.reset(start_position) if start_colour != self.Black: self.hull[self.position] = self.White self.panels[0] = self.White program = Program(self.init_memory, self.panels, dynamic_memory=True) output_pointer = 0 program.reset_inputs() program.reset_memory() program.reset_pointers() while program.pointer is not None: program.pointer = program.execute(program.pointer) if len(program.outputs) >= output_pointer + 2: if debug: print(f'Got outputs: {", ".join(map(str, program.outputs[output_pointer:]))}') self.hull[self.position] = program.outputs[output_pointer] p, facing = self.position.move(self.facing, program.outputs[output_pointer + 1]) output_pointer += 2 old_position = self.position old_facing = self.facing self.move_to(p, facing) if debug: print(f'Robot is moving from {old_position} {old_facing} to {self.position} {self.facing}') print(f'Robot moved {output_pointer // 2} times')
def test_slow_question_2(): boost_prog = Program( Program.load_memory_from_file('input.txt'), inputs=[2], dynamic_memory=True, ) boost_prog.run() assert boost_prog.outputs == [86025]
def test_question_1(): test_prog = Program( Program.load_memory_from_file('input.txt'), inputs=[1], dynamic_memory=True, ) test_prog.run() assert test_prog.outputs == [3638931938]
def test_output_large(): prog = Program( [ 104, 1125899906842624, 99, ], dynamic_memory=True, ) prog.run() assert prog.outputs == [1125899906842624]
def run_serial(self, phase_settings: Iterable[int]) -> int: current_input = 0 for i, setting in enumerate(phase_settings): prog = Program( [m for m in self._initial_memory], [setting, current_input], ) prog.run() if not prog.outputs: raise RuntimeError(f'Setting {i}: {setting} with input {current_input} did not provide output') current_input = prog.outputs[0] return current_input
def test_ouput_16_digit(): prog = Program( [ 1102, 34915192, 34915192, 7, 4, 7, 99, 0, ], dynamic_memory=True, ) prog.run() assert prog.outputs == [1219070632396864]
def test_copy_itself(): prog = Program( [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, ], dynamic_memory=True, ) prog.run() assert prog.outputs == [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, ]
def run(self, init_memory: List[int], interactive=False, init_inputs=None, auto_play=False): self.reset() if init_inputs is None: inputs = [] else: inputs = init_inputs program = Program(init_memory, inputs=inputs, dynamic_memory=True) if interactive or auto_play: init_memory[0] = 2 output_idx = 0 max_blocks = None track = { Tile.Ball: None, Tile.HorizontalPaddle: None, } while program.pointer is not None: try: program.pointer = program.execute(program.pointer) if len(program.outputs) >= output_idx + 3: # Read one entry pos = Position( program.outputs[output_idx], program.outputs[output_idx + 1], ) if pos == self._score_position: self.score = program.outputs[output_idx + 2] else: tile = Tile(program.outputs[output_idx + 2]) self.screen[pos] = tile if auto_play and tile in track: print(f'Tracking {tile} as {pos}') track[tile] = pos except InputError: if interactive: n_blocks = sum( (1 for t in self.screen.values() if t == Tile.Block)) if max_blocks is None: max_blocks = n_blocks else: print(f'score/block={self.score / max_blocks}') print( f'Pointer: {program.pointer}, inputs={len(inputs)}, n_blocks={n_blocks}' ) self.print_screen() # Read console to know if we move the joystick key = input('Joystick (Q=left, P=Right): ') if not key: inputs.append(0) elif key.lower() == 'q': inputs.append(-1) elif key.lower() == 'p': inputs.append(1) else: raise elif auto_play: if None in track.values(): raise ball_pos = track[Tile.Ball] paddle_pos = track[Tile.HorizontalPaddle] if ball_pos.x > paddle_pos.x: inputs.append(1) elif ball_pos.x < paddle_pos.x: inputs.append(-1) else: inputs.append(0) self.print_screen() return inputs
from common.intcode import Program if __name__ == '__main__': test_prog = Program( Program.load_memory_from_file('input.txt'), inputs=[1], dynamic_memory=True, ) test_prog.run() print(f'Running test got {", ".join(map(str, test_prog.outputs))}' ) # 3638931938 boost_prog = Program( Program.load_memory_from_file('input.txt'), inputs=[2], dynamic_memory=True, ) boost_prog.run() print(f'Running boost got {", ".join(map(str, boost_prog.outputs))}')