def mapit(self): start_coords = (0, 0) network = defaultdict(set) self.make_network([start_coords], network) xs = {coords[0] for coords in network.keys()} ys = {coords[1] for coords in network.keys()} offset_x = -min(xs) offset_y = -min(ys) dim_x = max(xs) + 1 dim_y = max(ys) + 1 def convert(x, y): return (x + offset_x) * 2 + 1, (y + offset_y) * 2 + 1 castle = CharMap(width_height=convert(dim_x, dim_y), default_repr='#') for current, options in network.items(): castle[convert(*current)] = '.' if current != start_coords else 'X' for destination in options: direction = ( destination[0] - current[0], destination[1] - current[1], ) if direction[0] != 0: display = '|' else: display = '-' interface = add_coordinates(convert(*current), direction) castle[interface] = display castle.echo()
def _generate_corners(self): any_point = self.bots[0][0] for bot, radius in self.bots: for i in any_point: for d in (-radius, radius): delta = (d if j == i else 0 for j in any_point) corner = add_coordinates(bot, delta) yield (corner)
def next_coordinates(self, from_coordinates): """ Generate the next possible coordinates to progress :param from_coordinates: The coordinates to progress from :return: a generator of the next coordinates """ for delta in ADJACENT_COORDINATES_DELTAS: yield add_coordinates(from_coordinates, delta)
def counts_around(self, coordinates): counts = Counter({content: 0 for content in (OPEN, TREES, LUMBER)}) for delta in ADJACENT_DELTAS: try: value = self[add_coordinates(coordinates, delta)] counts[value] += 1 except IndexError: pass return counts
def traverse_string(direction_string, start, network): current = start for direction in direction_string: step = DIRECTIONS[direction] following = add_coordinates(current, step) network[current].add(following) network[following].add(current) current = following return current
def parse_wire(wire, start=(0, 0)): segments = wire.split(',') position = list(start) for segment in segments: direction = segment[0] step = steps[direction] num_steps = int(segment[1:]) for i in range(num_steps): position = add_coordinates(position, step) yield position
def iterate(self): adjustments = defaultdict(Counter) for coordinates, state in self.items(): counts = self._counts[coordinates] next_state = self.next_state(state, counts) if next_state != state: self[coordinates] = next_state for delta in ADJACENT_DELTAS: adjacent = add_coordinates(coordinates, delta) adjustments[adjacent][state] -= 1 adjustments[adjacent][next_state] += 1 for coordinates, adjustment in adjustments.items(): if coordinates in self._counts: self._counts[coordinates] += adjustment
def best_spot(self): dimension = len(self.bots[0][0]) origin = tuple(0 for _ in range(dimension)) corners = frozenset(self._generate_corners()) overlaps = {corner: self._num_overlaps(corner) for corner in corners} best_corner_count = max(overlaps.values()) best_corners = { corner: count for corner, count in overlaps.items() if count == best_corner_count } directions = [(1, 1, 0), (-1, 1, 0), (1, -1, 0), (-1, -1, 0), (1, 0, 1), (-1, 0, 1), (1, 0, -1), (-1, 0, -1), (0, 1, 1), (0, -1, 1), (0, 1, -1), (0, -1, -1)] best_point = None best_point_distance = None best_point_count = None for point, count in best_corners.items(): for direction in directions: current_point = point while True: current_distance = manhattan_distance( origin, current_point) current_count = self._num_overlaps(current_point) if (best_point is None or current_count > best_point_count or (current_count == best_point_count and current_distance < best_point_distance)): best_point = current_point best_point_count = current_count best_point_distance = current_distance elif current_count < best_point_count: break current_point = add_coordinates(current_point, direction) return best_point, best_point_distance, best_point_count
def progress_to(coordinates, direction): progress = PROGRESS_STEPS[direction] return add_coordinates(coordinates, progress)
def offset(self, coordinates): return add_coordinates(coordinates, self.offsets)
def add_vectors(u, v): return add_coordinates(u, v)