class Scanner(object): def __init__(self, size): self._board = Board(size, size, do_translate=False) self._program = load_program("dec19") self._x_given = False self._current_pos = None self._positions = [(x, y) for x in range(size) for y in range(size)] def _input(self): if self._current_pos is None: self._current_pos = self._positions.pop(0) if self._x_given: result = self._current_pos[1] self._x_given = False return result else: result = self._current_pos[0] self._x_given = True return result def _output(self, value): if value == 0: self._board.set(self._current_pos[0], self._current_pos[1], ".") elif value == 1: self._board.set(self._current_pos[0], self._current_pos[1], "#") else: raise ValueError("Invalid output value") self._current_pos = None def scan(self): while self._positions: intcode = IntCode(self._program) intcode.execute(self._input, self._output) self._board.print() return self._board.count("#")
class Robot(object): def __init__(self, program): self._intcode = IntCode(program) self._position = Position(0, 0) self._direction = Vector(0, 1) self._board = Board(1000, 1000) self._output_mode = OutputMode.COLOR self._paint_counter = {} def set_start_white(self): self._board.set(0, 0, Colors.WHITE.char) def input(self): char = self._board.get(self._position.x, self._position.y) return Colors.char2value(char) def output(self, value): if self._output_mode == OutputMode.COLOR: char = Colors.value2char(value) self._board.set(self._position.x, self._position.y, char) self._paint_counter[self._position] = 1 elif self._output_mode == OutputMode.ROTATE: self._direction = self._direction.rotate(value) self._position += self._direction self._output_mode = OutputMode.alternate(self._output_mode) def run(self): self._intcode.execute(self.input, self.output) self._board.set(self._position.x, self._position.y, self._direction.char()) self._board.print() painted = sum(self._paint_counter.values()) print("The robot painted {} panels".format(painted))
def load_map(lines): board = Board(len(lines[0]), len(lines), do_translate=False) asteroids = [] for y, line in enumerate(lines): for x, c in enumerate(line.strip()): if c == "#": asteroid = Asteroid(x, y) asteroids.append(asteroid) board.set(x, y, asteroid) board.print() return asteroids, board
class Arcade(object): def __init__(self, program): self._board = Board(100, 100, flip=True) self._machine = IntCode(program) self._acc = [] self._score = 0 self._direction = 0 self._ball_x = None self._paddle_x = None def play(self): self._machine.execute(input_func=self._joystick, output_func=self._draw) self._board.print() return self._count(), self._score def _joystick(self): if self._ball_x and self._paddle_x: self._direction = self._ball_x - self._paddle_x return self._direction def _draw(self, value): self._acc.append(value) if len(self._acc) == 3: x, y, tile_value = self._acc if x == -1 and y == 0: self._score = tile_value print("New score: {}".format(self._score)) self._board.print() print() else: tile = Tiles.from_value(tile_value) if tile == Tiles.BALL: self._ball_x = x elif tile == Tiles.PADDLE: self._paddle_x = x self._board.set(x, y, tile.char) self._acc = [] def _count(self): return self._board.count(Tiles.BLOCK.char)
class Mapper(object): def __init__(self, intcode): self._board = Board(SIZE, SIZE) self._nodes = Board(SIZE, SIZE, fill_value=Node(0, NodeType.UNKNOWN, None, 9999), dtype=np.object_) for y in range(SIZE): for x in range(SIZE): self._nodes.grid[y][x] = Node(0, NodeType.UNKNOWN, None, 9999) self._x = self._y = 0 start_node = Node(1, NodeType.START, None, 0) self._nodes.set(self._x, self._y, start_node) self._board.set(self._x, self._y, self._nodes.get(self._x, self._y).type.value) self._current_direction = Directions.NORTH self._current_node = start_node self._intcode = intcode self._counter = 0 self._goal = None def map(self): try: self._intcode.execute(self._input, self._output) except Complete: self._draw_solved_map() return self._goal, self._nodes def _draw_solved_map(self): current = self._goal while current.type is not NodeType.START: c = self._board.get(current.x, current.y) self._board.set(current.x, current.y, Back.GREEN + c + Back.RESET) current = current.parent self._board.print() print("Distance to goal: {}".format(self._goal.distance)) def is_map_complete(self): if self._goal is None: return False for row in self._nodes.grid: if all(node.type is NodeType.UNKNOWN for node in row): continue if any(0 < node.visits < 4 for node in row): return False return True def _input(self): best = None for direction in Directions: x, y = direction.move(self._x, self._y) candidate = self._nodes.get(x, y) if best is None or candidate.visits < best[0].visits: best = (candidate, direction) self._current_direction = best[1] return self._current_direction def _output(self, v): if v == Status.WALL: x, y = self._current_direction.move(self._x, self._y) node = Node(9999, NodeType.WALL, self._current_node, 9999, x=x, y=y) self._nodes.set(x, y, node) self._board.set(x, y, node.type.value) else: self._x, self._y = self._current_direction.move(self._x, self._y) prev_node, node = self._current_node, self._nodes.get( self._x, self._y) self._current_node = node node.x = self._x node.y = self._y node.visits += 1 if node.distance > prev_node.distance: node.distance = prev_node.distance + 1 node.parent = prev_node if v == Status.GOAL: node.type = NodeType.GOAL self._goal = node elif node.type != NodeType.START: node.type = NodeType.OPEN self._board.set(self._x, self._y, node.type.value) self._counter += 1 if self._counter % 5 == 0: prev = self._board.set( self._x, self._y, Fore.RED + self._current_direction.char + Fore.RESET) self._board.print() self._board.set(self._x, self._y, prev) if self.is_map_complete(): raise Complete()