def run_program(computer: Computer) -> bool: try: computer.run() return True except Exception as e: print(str(e)) return False
def find_phase_sequence(registers: List[int], amplifiers: int) -> Tuple[Tuple[int, ...], int]: # Python libraries help me cheat in generating permutations :D sequence_scores = {x: None for x in permutations(range(amplifiers))} for curr_sequence in sequence_scores.keys(): input_val = 0 for amp_number in range(amplifiers): comp = Computer(copy_registers(registers), inputs=[curr_sequence[amp_number], input_val]) outputs = comp.run() input_val = outputs[0] sequence_scores[curr_sequence] = input_val return max([(k, v) for k, v in sequence_scores.items()], key=lambda x: x[1])
def find_phase_sequence(registers: List[int], amplifiers: int) -> Tuple[Tuple[int, ...], int]: sequence_scores = {x: None for x in permutations(range(amplifiers, amplifiers * 2))} for curr_sequence in sequence_scores.keys(): # Instantiate the computers computers = [Computer(copy_registers(registers), inputs=[curr_sequence[amp_number]]) for amp_number in range(amplifiers)] # Track their outputs outputs = {i: [] for i in range(amplifiers)} # Starting from the first amplifier, feed in the appropriate input and run until producing an output. # Then move to the next amplifier in the loop, feeding that output as the next input. Continue until # the final amplifier halts, then read the final input value from the last amplifier curr_computer = 0 input_val = 0 while True: computers[curr_computer].inputs.append(input_val) input_val = computers[curr_computer].run_until_output() # Getting a value of None back from Computer.run_until_output() indicates that the program halted if input_val is None: if curr_computer == amplifiers - 1: break else: outputs[curr_computer].append(input_val) curr_computer = (curr_computer + 1) % amplifiers sequence_scores[curr_sequence] = outputs[amplifiers - 1][-1] return max([(k, v) for k, v in sequence_scores.items()], key=lambda x: x[1])
def run_painting(computer: Computer, start_color: int) -> Dict[Tuple[int, int], int]: robot_coord = (0, 0) direction = (0, -1) surface = dict() computer.inputs.append(start_color) while True: color = computer.run_until_output() if color is None: break surface[robot_coord] = color turn_direction = computer.run_until_output() if turn_direction is None: break direction = turn(direction, turn_direction) robot_coord = tuple( (robot_coord[0] + direction[0], robot_coord[1] + direction[1])) computer.inputs.append(get_surface_color(surface, robot_coord)) return surface
def load() -> List[int]: with open("input/input07.txt", "r") as f: return Computer.parse_registers(f.read())
def play_game(computer: Computer, bounds: Tuple[int, int], render_speed: Optional[int] = None, max_screen_size: Tuple[int, int] = (1920, 1080)) \ -> Tuple[Dict[Tuple[int, int], int], int]: """ Plays the game. @param computer: The Intcode computer to run @param bounds: The bounds of the playing field @param render_speed: How quickly to render the game. render_speed == None :: Do not render at all render_speed == 0 :: Render frame by frame, waiting for mouse clicks to advance to next frame render_speed == 1 :: Render every frame render_speed > 1 :: Render every n frames (n = render_speed), don't render frames in between render_speed < 0 :: Render every frame, pause n milliseconds between each frame (n = -render_speed) @param max_screen_size: Tuple of the maximum width and height of the render screen. Guarantees that at either the width or the height will exactly match its corresponding maximum, and the other dimension will be less than or equal to its corresponding maximum """ screen, scale = build_game_screen(bounds, max_width=max_screen_size[0], max_height=max_screen_size[1]) \ if render_speed is not None else (None, 1) # Set a function to call whenever input is required to give joystick inputs computer.input_method = ai screen_info = dict() score = 0 initial_render_complete = False steps = 0 while True: steps += 1 # Get set of outputs outputs = computer.run_until_outputs(3) # If program halted, quit if outputs is None: break # Check if this is a score output if outputs[0] == -1 and outputs[1] == 0: score = outputs[2] print(score) else: # Otherwise treat it as rendering output screen_info[(outputs[0], outputs[1])] = outputs[2] # When the last wall square is done, the entire initial grid has been rendered if (outputs[0], outputs[1]) == bounds: initial_render_complete = True if render_speed is not None: render(screen, screen_info, None, scale, False) # If we're rendering to screen, wait until initial render is complete, and then follow rules set by # the render speed if render_speed is not None and initial_render_complete: if outputs[2] == 0: render(screen, screen_info, (outputs[0], outputs[1]), scale, pause_for_clicks=False, flip=False) elif render_speed <= 0 or render_speed <= steps: render(screen, screen_info, (outputs[0], outputs[1]), scale, pause_for_clicks=render_speed == 0 and initial_render_complete) steps = 0 # If the render speed is less than zero, pause the program for an amount of # milliseconds = the absolute value of that render speed if render_speed < 0: time.sleep(-render_speed / 1000) return screen_info, score
def load() -> Computer: with open("input/input13.txt", "r") as f: return Computer.from_string(f.read())
def replace(computer: Computer, replacements: Dict[int, int]): for pos, val in replacements.items(): computer.registers[pos] = val