def load_map(program): """run the game""" board = {} output, _, _, _ = run_intcode_program(program, []) for i in range(0, len(output) - 2, 3): board[tuple(output[i:i + 2])] = output[i + 2] return board
def run_intcode_program(self): """run the program with current state until further input is needed""" out, pointer, relative_base, code = run_intcode_program( self.intcode, self.input, pointer_start=self.code_pointer, relative_base_start=self.code_relative_base) self.input = [] # reset input self.code_pointer = pointer self.code_relative_base = relative_base self.intcode = code return out, pointer is None
def get_amplification_score(program, sequence) -> int: """ Get the final score of connected amplifiers :param program: intcode program :param sequence: current sequence to test the output of :return: value of the last amplifier """ signal = 0 for phase_value in sequence: out, _, _, _ = run_intcode_program(intcode=program.copy(), program_input=[phase_value, signal], show_output=False) signal = out[-1] return signal
def find_shortest_path(program: List[int], valid_programs: List[List[int]]) -> (int, List[int]): """find the length of the shortest path by generating all paths with length n""" new_valid_programs = [] for valid in valid_programs: for curr_dir in dirs.keys(): new_input = valid + [curr_dir] outp, _, _, _ = run_intcode_program(program, new_input) # Status (output[0]) # 0: The repair droid hit a wall. Its position has not changed. # 1: The repair droid has moved one step in the requested direction. # 2: The repair droid has moved one step in the requested direction; new pos == oxygen system pos. if outp: # 1 or 2 # add new found program to possible descendants new_valid_programs.append(new_input) if outp == 2: return len(new_input), new_input return find_shortest_path(program, new_valid_programs)
def get_feedback_loop_score(amp_input: list, sequence: tuple) -> int: """ Get the final score of amplifiers connected via a feedback loop :param amp_input: intcode program :param sequence: current sequence to test the output of :return: value of the last amplifier at the end of the loop """ signal = 0 amplifiers = [{ "in": [], "out": [], "pointer": 0, "code": amp_input.copy() } for _ in range(len(sequence))] # add init conditions for j, amp in enumerate(amplifiers): amp["in"].append(sequence[j]) # input first signal amplifiers[0]["in"].append(signal) # run loop until last pointer points to none i_amp = 0 while amplifiers[-1]["pointer"] is not None: # get current and last amplifier curr_amp = amplifiers[i_amp] last_amp = amplifiers[(i_amp + 4) % 5] # add output of last amplifier to current input and remove it from last amp curr_amp["in"] += last_amp["out"] last_amp["out"] = [] # run next amplifier new_out, new_pointer, _, new_code = run_intcode_program( intcode=curr_amp["code"], program_input=curr_amp["in"], pointer_start=curr_amp["pointer"]) # update current amplifier with updated values curr_amp["out"] += new_out curr_amp["pointer"] = new_pointer curr_amp["new_code"] = new_code # increase pointer i_amp = (i_amp + 1) % 5 # return the las value of the last amp return amplifiers[-1]["out"][-1]
def play_game(program, initial_code_input, selfplay=False): """read joystick inputs to play the game, play as long as there are blocks on the board""" blocks = 1 score = 0 control = initial_code_input instr_pointer, rb_pointer = 0, 0 board = {} while blocks > 0: output, instr_pointer, rb_pointer, program = run_intcode_program(program, control, pointer_start=instr_pointer if instr_pointer else 0, relative_base_start=rb_pointer if rb_pointer else 0 ) # read board values for i in range(0, len(output) - 2, 3): board[tuple(output[i:i + 2])] = output[i + 2] # get score and remove field from board score = board.pop((-1, 0), score) blocks = sum(val == 2 for val in board.values()) if selfplay: print_map(board) print('Score = %d' % score) if selfplay: # get user control joystick_input = input("What is your move? (left a, nothing s, right d)") control = list([-1 if joystick_input == "a" else (1 if joystick_input == "d" else 0)]) else: ball_pos = (0, 0) paddle_pos = (0, 0) for key, val in board.items(): if val == 4: ball_pos = key elif val == 3: paddle_pos = key control = list([-1 if ball_pos[0] < paddle_pos[0] else (1 if ball_pos[0] > paddle_pos[0] else 0)]) return score
def test_computer_output_in_range(self, code, inp, value_range): out = run_intcode_program(code, inp)[0][0] self.assertGreaterEqual(out, value_range[0]) self.assertLessEqual(out, value_range[1])
def test_computer_output(self, code, inp, output): out, pointer, _, _ = run_intcode_program(code, inp) self.assertIsNone(pointer) self.assertListEqual(out, output)
], [], [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ]], [[104, 1125899906842624, 99], [], [1125899906842624]], [[109, 10, 204, -8, 99], [], [204]], [puzzle_input.copy(), [1], [2316632620]]]) def test_computer_output(self, code, inp, output): out, pointer, _, _ = run_intcode_program(code, inp) self.assertIsNone(pointer) self.assertListEqual(out, output) @parameterized.expand([ [[1102, 34915192, 34915192, 7, 4, 7, 99, 0], [], (1e15, 1e16)], ]) def test_computer_output_in_range(self, code, inp, value_range): out = run_intcode_program(code, inp)[0][0] self.assertGreaterEqual(out, value_range[0]) self.assertLessEqual(out, value_range[1]) if __name__ == '__main__': print(">>> Start Main 09:") print("Part 1):") run_intcode_program(puzzle_input.copy(), [1], show_output=True) print("Part 2):") run_intcode_program(puzzle_input.copy(), [2], show_output=True) print("End Main 09<<<")