class PaintingRobot(object): def __init__(self, program: List[int]) -> None: self.computer = IntcodeComputer(program) self.x: int = 0 self.y: int = 0 self.direction: int = 90 def step(self, panel: DefaultDict[Tuple[int, int], int]) -> bool: current_panel_color = panel[(self.x, self.y)] color_to_paint = self.computer.run_and_halt(current_panel_color) if color_to_paint is None: return True direction_to_turn = self.computer.run_and_halt() if direction_to_turn is None: return True direction_to_turn = 90 if direction_to_turn == 0 else -90 panel[(self.x, self.y)] = color_to_paint self.direction += direction_to_turn self.x = int(round(self.x + cos(radians(self.direction)))) self.y = int(round(self.y + sin(radians(self.direction)))) return False
def main_rendered(screen: Any, program: List[int]) -> None: ''' Navigate through the maze to find the end and display progress on screen. ''' curses.curs_set(0) # A dict, keyed on coordinates, with the number of times each direction has been traversed exploration_history: Dict[Tuple[int, int], int] = defaultdict(lambda: 0) # A dict, keyed on coordinates, with the character to render for that location maze_map: Dict[Tuple[int, int], str] = defaultdict(lambda: UNKNOWN) current_location: Tuple[int, int] = (0, 0) status: int = None # used to store result of the last instruction exploration_history[current_location] += 1 maze_map[current_location] = START robot = IntcodeComputer(program) steps = 0 while True: render_scene(screen, current_location, maze_map) direction_to_move = get_next_direction(current_location, exploration_history) status = robot.run_until_input_required(direction_to_move)[0] if status == HIT_WALL: exploration_history[destination_coordinate( current_location, direction_to_move)] = LARGE_NUMBER maze_map[destination_coordinate(current_location, direction_to_move)] = WALL elif status == MOVED: current_location = destination_coordinate(current_location, direction_to_move) exploration_history[current_location] += 1 if maze_map[current_location] == UNKNOWN: maze_map[current_location] = PATH else: # GOAL current_location = destination_coordinate(current_location, direction_to_move) exploration_history[current_location] += 1 maze_map[current_location] = GOAL steps += 1 time.sleep(1 / REFRESH_RATE) if steps % 100 == 0 and is_exploration_complete(maze_map): break serialize_maze(maze_map, 'day15_maze_map.json') render_scene(screen, (0, 0), maze_map) screen.addstr(0, 0, ('{:^' + str(NX) + 's}').format('MAZE MAPPED!')) screen.getch()
def __init__(self, screen: Any, program: List[int], free_play: bool=True) -> None: if free_play: tmp = program.copy() tmp[0] = 2 else: tmp = program.copy() self.score: int = 0 self.paddle_x_position = -1 self.ball_x_position = -1 self.computer = IntcodeComputer(tmp) self.screen = screen initial_screen = self.computer.run_until_input_required() self.render_screen(initial_screen) curses.curs_set(0)
def run_amplifiers(program: List[int], input_value: int, phases: List[int]) -> int: amplifiers: List[IntcodeComputer] = [IntcodeComputer(program) for name in 'ABCDE'] for phase, amp in zip(phases, amplifiers): output = amp.run(phase, input_value)[0] input_value = output return output
def run_amplifiers_with_feedback(program: List[int], input_value: int, phases: List[int]) -> int: amplifiers: List[IntcodeComputer] = [IntcodeComputer(program) for name in 'ABCDE'] program_state: List[int] = [-1 for name in 'ABCDE'] # -1 for not initialized, 0 for executing, 1 for done while program_state[-1] <= 0: for i, amp in enumerate(amplifiers): if program_state[i] < 0: output = amp.run_and_halt(phases[i], input_value) program_state[i] = 0 elif program_state[i] == 0: output = amp.run_and_halt(input_value) else: continue if output is not None: input_value = output else: program_state[i] = 1 return input_value
class ArcadeCabinet(object): tile_rendering = { 0: ' ', # Blank 1: '$', # Wall 2: '#', # Block 3: '-', # Paddle 4: 'o' # Ball } def __init__(self, screen: Any, program: List[int], free_play: bool=True) -> None: if free_play: tmp = program.copy() tmp[0] = 2 else: tmp = program.copy() self.score: int = 0 self.paddle_x_position = -1 self.ball_x_position = -1 self.computer = IntcodeComputer(tmp) self.screen = screen initial_screen = self.computer.run_until_input_required() self.render_screen(initial_screen) curses.curs_set(0) def render_screen(self, tiles: List[int]) -> None: for i in range(0, len(tiles), 3): if tiles[i] == -1 and tiles[i+1] == 0: new_score = tiles[i+2] if new_score > self.score: self.score = new_score self.screen.addstr(0, 0, f'Score: {self.score:>10}') else: self.screen.addch( tiles[i+1] + 1, tiles[i], self.tile_rendering[tiles[i+2]] ) if tiles[i+2] == 3: self.paddle_x_position = tiles[i] if tiles[i+2] == 4: self.ball_x_position = tiles[i] self.screen.refresh() def game_loop(self, bot_player: bool=False) -> None: while True: if not bot_player: key = self.screen.getch() if key == curses.KEY_LEFT: input_value = -1 elif key == curses.KEY_RIGHT: input_value = 1 else: input_value = 0 else: diff = self.ball_x_position - self.paddle_x_position if diff > 0: input_value = 1 elif diff < 0: input_value = -1 else: input_value = 0 time.sleep(0.01) tiles = self.computer.run_until_input_required(input_value) if tiles is None: self.screen.addstr(18, 13, f'GAME OVER') self.screen.addstr(19, 13, f'SCORE: {self.score}') key = self.screen.getch() break else: self.render_screen(tiles)
if tiles is None: self.screen.addstr(18, 13, f'GAME OVER') self.screen.addstr(19, 13, f'SCORE: {self.score}') key = self.screen.getch() break else: self.render_screen(tiles) def main(screen: Any, bot_player: bool): program = read_program('./inputs/day13.txt') cabinet = ArcadeCabinet(screen, program) cabinet.game_loop(bot_player=bot_player) if __name__ == '__main__': program = read_program('./inputs/day13.txt') computer = IntcodeComputer(program) output = computer.run() print(f"Number of block tiles: {sum([1 for i in range(2, len(output), 3) if output[i] == 2])}") if len(sys.argv) > 1: bot_player = int(sys.argv[1]) == 1 else: bot_player = False curses.wrapper(main, bot_player)
def __init__(self, program: List[int]) -> None: self.computer = IntcodeComputer(program) self.x: int = 0 self.y: int = 0 self.direction: int = 90
from day05 import IntcodeComputer, read_program if __name__ == "__main__": test_program = [109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99] test_computer = IntcodeComputer(test_program) output = test_computer.run() assert len(output) == len(test_program) assert all(o == p for o, p in zip(output, test_program)) test_program = [109, -1, 4, 1, 99] # -1 test_program = [109, -1, 104, 1, 99] # 1 test_program = [109, -1, 204, 1, 99] # 109 test_program = [109, 1, 9, 2, 204, -6, 99] # 204 test_program = [109, 1, 109, 9, 204, -6, 99] # 204 test_program = [109, 1, 209, -1, 204, -106, 99] # 204 test_computer = IntcodeComputer(test_program) output = test_computer.run() assert output[0] == 204 test_program = [109, 1, 3, 3, 204, 2, 99] # input test_program = [109, 1, 203, 2, 204, 2, 99] # input test_computer = IntcodeComputer(test_program) output = test_computer.run(234) print(test_computer.memory) assert output[0] == 234 test_program = [1102,34915192,34915192,7,4,7,99,0] test_computer = IntcodeComputer(test_program) output = test_computer.run()[0] assert len(str(output)) == 16