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 solve(lines): board = Board(do_translate=False, fill_value=0, dtype=np.int_) for line in lines: for point in line.points(): cur = board.get(point.x, point.y) board.set(point.x, point.y, cur + 1) return np.sum(board.grid >= 2)
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()