예제 #1
0
def solve_13(input_path, remove_crashed_carts=False):
    map_grid = parse_map(input_path)
    carts = []

    for y in range(0, len(map_grid)):
        for x in range(0, len(map_grid[0])):
            if map_grid[y][x] == '<' or map_grid[y][x] == '>':
                carts.append(Cart(map_grid[y][x], Point(x, y)))
                map_grid[y][x] = '-'
            elif map_grid[y][x] == '^' or map_grid[y][x] == 'v':
                carts.append(Cart(map_grid[y][x], Point(x, y)))
                map_grid[y][x] = '|'

    run = True
    result_loc = None
    while run:
        for cart in sorted(carts, key=lambda c: (c.loc.y, c.loc.x)):
            cart.move()
            if cart.collision(carts, remove_crashed_carts):
                if not remove_crashed_carts:
                    run = False
                    result_loc = Point(cart.loc.x, cart.loc.y)
                    # print_map(map_grid, carts)
                if len(carts) == 1:
                    run = False

            cart.rotate(map_grid[cart.loc.y][cart.loc.x])
        # print_map(map_grid, carts)
        if not run and remove_crashed_carts:
            result_loc = Point(carts[0].loc.x, carts[0].loc.y)
            # print_map(map_grid, carts)

    return result_loc
    def test_load_gml_for_debugging(self):
        g: nx.DiGraph = nx.read_gml('real-nodes.gml',
                                    destringizer=self.make_points)
        all_paths = nx.single_source_shortest_path(g, source=Point(0, 0))

        max_distance = 0
        i = 0
        node_count = len(g.nodes)
        greater_than_1000 = 0

        for k in all_paths.keys():
            i += 1

            if len(all_paths[k]) > max_distance:
                max_distance = len(all_paths[k])
            if len(all_paths[k]) >= 1001:
                greater_than_1000 += 1
            print('{}/{}'.format(i, node_count))
        print('max: {}'.format(max_distance - 1))
        print('more than 1000: {}'.format(greater_than_1000))

        for node in g.nodes:
            i += 1
            distance = nx.shortest_path_length(g,
                                               source=Point(0, 0),
                                               target=node)
            if distance > max_distance:
                max_distance = distance
        print(max_distance)
예제 #3
0
def simulate_flow(puzzle_input):
    clay = set()
    for line in puzzle_input:
        a, b, c = map(int, re.findall(r"([\d]+)", line))
        if line.startswith('x'):
            for y in range(b, c + 1):
                clay.add(Point(a, y))
        else:
            for x in range(b, c + 1):
                clay.add(Point(x, a))
    lowest_y = max(p.y for p in clay)
    water_spring = Point(500, 0)
    still = set()
    flowing = set()
    to_fall = set()
    to_spread = set()

    to_fall.add(water_spring)
    while to_fall or to_spread:
        while to_fall:
            falling_point = to_fall.pop()
            res = fall(falling_point, lowest_y, clay, flowing)
            if res:
                to_spread.add(res)
        while to_spread:
            spreading_point = to_spread.pop()
            res_left, res_right = spread(spreading_point, clay, flowing, still)
            if not res_left and not res_right:
                to_spread.add(Point(spreading_point.x, spreading_point.y - 1))
            else:
                if res_left:
                    to_fall.add(res_left)
                if res_right:
                    to_fall.add(res_right)
    return flowing, still, clay
def solve_22_part_2(depth, target):
    cave = {}
    for x in range(0, target.x + 50):
        for y in range(0, target.y + 50):
            region = Region(Point(x, y), target, cave, depth)
            cave[Point(x, y)] = region

    g = nx.Graph()

    for k, region in cave.items():
        allowed_tools = region.allowed_tools()
        g.add_edge(region.nodes[allowed_tools[0]],
                   region.nodes[allowed_tools[1]],
                   weight=7)

        for direction in [Point(-1, 0), Point(0, -1)]:
            if (region.loc.x == 0
                    and direction.x == -1) or (region.loc.y == 0
                                               and direction.y == -1):
                continue

            neighbor = cave[region.loc + direction]
            for tool in allowed_tools:
                if tool in neighbor.allowed_tools():
                    g.add_edge(region.nodes[tool],
                               neighbor.nodes[tool],
                               weight=1)

    path_length = nx.dijkstra_path_length(g,
                                          source=cave[Point(0, 0)].nodes['T'],
                                          target=cave[target].nodes['T'])
    return path_length
예제 #5
0
def on_paint(cr):
    if client.width_mm == 0 or client.height_mm == 0:
        print("Wayland reports bogus monitor dimensions!")
        scale = Point(1, 1)
    else:
        scale = Point(client.width_pixels / client.width_mm,
                      client.height_pixels / client.height_mm)
    script.run(cr, scale, window)
def compute_destination(input):
    counter = Counter(input)

    # We're using a normal grid, but every orthogonal move is +2 and diagonal moves are +1, +1
    loc = Point(0, 0)
    for direction, count in counter.items():
        loc.x = loc.x + (dir_offsets[direction].x * count)
        loc.y = loc.y + (dir_offsets[direction].y * count)
    return loc
예제 #7
0
 def getScale(self, widget):
     """Return the dpi of the current monitor as a Point."""
     s = widget.get_screen()
     m = s.get_monitor_at_window(widget.get_window())
     geom = s.get_monitor_geometry(m)
     mm = Point(s.get_monitor_width_mm(m),
                s.get_monitor_height_mm(m))
     size = Point(float(geom.width), float(geom.height))
     return size / mm
예제 #8
0
def get_input():
    data = process_input()
    data = [re.findall(r"(-?\d+)", d) for d in data]
    data = [list(map(int, d)) for d in data]
    data = [
        Particle(Point(a, b, c), Point(d, e, f), Point(g, h, i))
        for a, b, c, d, e, f, g, h, i in data
    ]
    return data
예제 #9
0
def spread_vertical(pos, off, clay, still, tmp):
    pos1 = pos
    while pos1 not in clay:
        tmp.add(pos1)
        pos2 = Point(pos1.x, pos1.y + 1)
        if pos2 not in clay and pos2 not in still:
            return pos1
        pos1 = Point(pos1.x + off.x, pos1.y + off.y)
    return None
def setup_grid_and_start(entries):
    grid = defaultdict(lambda: '.')
    for y in range(len(entries)):
        for x in range(len(entries[y])):
            grid[Point(x, y)] = entries[y][x]

    start = Point(len(entries[0]) / 2, len(entries) / 2)

    return grid, start
예제 #11
0
def spread(pos, clay, flowing, still):
    tmp = set()
    pl = spread_vertical(pos, Point(-1, 0), clay, still, tmp)
    pr = spread_vertical(pos, Point(1, 0), clay, still, tmp)
    if not pl and not pr:
        still.update(tmp)
    else:
        flowing.update(tmp)
    return pl, pr
예제 #12
0
def convert_points(entries: List[str]) -> List[Point]:
    points = []
    i = 0
    for entry in entries:
        x, y = map(lambda v: int(v), entry.split(','))
        p = Point(x, y)
        p.id = i
        points.append(p)
        i += 1

    return points
def solve_22_part_1(depth, target):
    cave = {}
    risk = 0
    for x in range(0, target.x + 1):
        for y in range(0, target.y + 1):
            region = Region(Point(x, y), target, cave, depth)
            cave[Point(x, y)] = region

            risk += region.type()

    return risk
예제 #14
0
 def __parse_map(self, puzzle_input, elf_attack_power):
     for y in range(len(puzzle_input)):
         for x, c in enumerate(puzzle_input[y]):
             if c == 'E':
                 self.units.append(
                     Unit(Point(x, y),
                          Team.ELF,
                          attack_power=elf_attack_power))
             elif c == 'G':
                 self.units.append(Unit(Point(x, y), Team.GOBLIN))
             elif c == '#':
                 self.walls.add(Point(x, y))
예제 #15
0
def traverse_grid(origin, side_length, input, target_max=None):
    if target_max == 1:
        return origin

    grid = []
    for x in range(0, side_length):
        grid.append([])
        for y in range(0, side_length):
            grid[x].append(0)

    d = deque(
        [Point(x=1, y=0),
         Point(x=0, y=-1),
         Point(x=-1, y=0),
         Point(x=0, y=1)])

    cell = Point(x=origin.x, y=origin.y)
    grid[cell.x][cell.y] = 1

    cell += d[0]
    grid[cell.x][cell.y] = 1

    d.rotate(-1)

    i = 3
    temp_side_limit = 1
    inc_toggle = True

    while i <= input:

        for l in range(0, temp_side_limit):
            cell += d[0]

            if i == input:
                return cell

            value = compute_value(cell, grid)
            grid[cell.x][cell.y] = value

            if target_max is not None and value > target_max:
                print(
                    'Part 2: found larger than target value: {}'.format(value))
                exit()

            i += 1

        if inc_toggle:
            temp_side_limit += 1
            inc_toggle = False
        else:
            inc_toggle = True

        d.rotate(-1)
def compute_farthest_point(input):
    # We're using a normal grid, but every orthogonal move is +2 and diagonal moves are +1, +1
    positions = set()

    loc = Point(0, 0)
    for direction in input:
        loc.x = loc.x + dir_offsets[direction].x
        loc.y = loc.y + dir_offsets[direction].y
        positions.add(Point(loc.x, loc.y))

    return max(map(lambda p: (p, compute_shortest_distance(p)), positions),
               key=lambda p: p[1])
예제 #17
0
파일: gtk.py 프로젝트: emdash/cairo_sandbox
 def draw(self, widget, cr):
     helper = Helper(cr)
     alloc = widget.get_allocation()
     window = Rect.from_top_left(Point(0, 0), alloc.width, alloc.height)
     with helper.box(window.inset(5), clip=False) as bounds:
         radius = min(bounds.width, bounds.height) * 0.5
         helper.circle(bounds.center, radius)
         cr.set_line_width(2.5)
         cr.stroke()
         cr.rotate(self.value)
         helper.circle(Point(radius/2, 0), radius/4)
         cr.fill()
예제 #18
0
 def __find_closest_enemy(self, unit):
     frontier = deque()
     start = Point(unit.pos.x, unit.pos.y)
     frontier.append(start)
     came_from = {}
     came_from[start] = None
     team_mates = set(
         [u.pos for u in self.units if u.team == unit.team and u.alive])
     while frontier:
         current = frontier.popleft()
         for new_position in sorted(get_adjecent_4(current),
                                    key=lambda p: (p.y, p.x)):
             if new_position not in self.walls and new_position not in came_from and new_position not in team_mates:
                 frontier.append(new_position)
                 came_from[new_position] = current
     targets = []
     for u in self.units:
         if u.team != unit.team and u.alive:
             targets.extend(get_adjecent_4(u.pos))
     paths = []
     for current in sorted(targets, key=lambda p: (p.y, p.x)):
         if current in came_from:
             path = []
             while current != start:
                 path.append(current)
                 current = came_from[current]
             path.append(start)
             path.reverse()
             paths.append(path)
     if len(paths) == 0:
         return None
     return min(paths, key=len)
def compute_shortest_distance(loc):
    # Since all we care about is distance, let's make it easy on ourselves
    # and make everything positive
    _loc = Point(abs(loc.x), abs(loc.y))

    # Now let's walk back to the start
    # Easy cases, we're already on an axis
    if _loc.x == 0:
        return _loc.y / 2
    if _loc.y == 0:
        return _loc.x / 2
    # Now we're not on an axis, so:
    # - get to an axis on a diagonal
    # - and then walk on axis back to origin
    dist = 0
    if _loc.x < _loc.y:
        dist += _loc.x
        dist += (_loc.y - _loc.x) / 2
    elif _loc.y < _loc.x:
        dist += _loc.y
        dist += (_loc.x - _loc.y) / 2
    else:
        dist = _loc.x
    # answer: 834
    return int(dist)
def fill_grid(serial_number):
    grid = defaultdict(dict)

    for x in range(0, GRID_SIZE + 1):
        for y in range(0, GRID_SIZE + 1):
            grid[x][y] = compute_cell(Point(x, y), serial_number)

    return grid
예제 #21
0
def fall(pos, lowest_y, clay, flowing):
    while pos.y < lowest_y:
        pos_down = Point(pos.x, pos.y + 1)
        if pos_down not in clay:
            flowing.add(pos_down)
            pos = pos_down
        elif pos_down in clay:
            return pos
    return None
예제 #22
0
def solve_3(input, target_max=None):
    # Adding 5 to give us some buffer
    side_length = math.ceil(math.sqrt(input)) + 5

    center_index = math.floor(side_length / 2.0)
    origin = Point(x=center_index, y=center_index, id=1)

    target = traverse_grid(origin, side_length, input, target_max)

    return manhattan_distance(origin, target)
예제 #23
0
def find_start_pos(network_map):
    # Find starting position
    start = None
    x = 0
    while start is None:
        if network_map[(x, 0)] == '|':
            start = Point(x, 0)
        x += 1

    return start
def print_state(time_id, grid):
    print('Time: {}'.format(time_id))

    min_x, max_x, min_y, max_y = get_min_max(list(grid.keys()))
    for x in range(min_x, max_x + 1):
        for y in range(min_y, max_y + 1):
            print(grid[Point(x, y)], end='')
        print('')
    print('')
    print('')
예제 #25
0
    def test_find_aa(self):
        # Should be 88 locations
        entries = read_raw_entries('tests/find-accessible-test.txt')
        grid_map, elves, goblins = parse_map(entries)
        filled_map = fill_temp_map(elves + goblins, grid_map)

        aa = find_accessible_areas_from_point(goblins[0].loc + Point(1, 0),
                                              filled_map, [])
        print(len(set(aa)))

        self.assertEqual(329, len(set(aa)))
    def geo_index(self):
        if self._geo_index is not None:
            return self._geo_index

        if self.loc == Point(0, 0):
            self._geo_index = 0
        elif self.loc == self.target:
            self._geo_index = 0
        elif self.loc.y == 0:
            self._geo_index = self.loc.x * 16807
        elif self.loc.x == 0:
            self._geo_index = self.loc.y * 48271
        else:
            x_minus_one = self.cave[Point(self.loc.x - 1,
                                          self.loc.y)].erosion_level()
            y_minus_one = self.cave[Point(self.loc.x,
                                          self.loc.y - 1)].erosion_level()
            self._geo_index = x_minus_one * y_minus_one

        return self._geo_index
예제 #27
0
def part2():
    g: nx.DiGraph = nx.read_gml('real-nodes.gml', destringizer=make_points)
    all_paths = nx.single_source_shortest_path(g, source=Point(0, 0))

    greater_than_1000 = 0

    for k in all_paths.keys():
        # greater than 1001 since every path start at (and includes) the origin
        if len(all_paths[k]) >= 1001:
            greater_than_1000 += 1

    return greater_than_1000
예제 #28
0
 def test_shortest_path_go_right(self):
     paths = shortest_path(Point(1, 1), Point(4, 1))
     self.assertEqual(len(paths), 1)
     self.assertEqual(
         paths[0],
         [Point(1, 1), Point(2, 1),
          Point(3, 1), Point(4, 1)])
def print_state(clay, water, min_x, max_x, min_y, max_y):
    f = open("test_out.txt", "w")

    for x in range(min_x-1, max_x + 2):
        if x == 500:
            print('x', end='')
            f.write('x\n')
        else:
            print('.', end='')
            f.write('.')
    print('')
    f.write('\n')

    for y in range(min_y-1, max_y + 2):
        for x in range(min_x-1, max_x + 2):
            if Point(x, y) in clay:
                print(clay[Point(x, y)], end='')
                f.write(clay[Point(x, y)])
            elif Point(x, y) in water:
                print(water[Point(x, y)], end='')
                f.write(water[Point(x, y)])
            else:
                print('.', end='')
                f.write('.')
        print('')
        f.write('\n')
    print('')
    f.write('\n')
    f.close()
def parse_real_input(input_path):
    entries = read_raw_entries(input_path)
    points = []
    for entry in entries:
        parts = entry.split()

        if 'x' in parts[0]:
            x = parts[0].split('=')[1].replace(',', '')

            s, e = parts[1].split('=')[1].split('..')
            for y in range(int(s), int(e) + 1):
                p = Point(x, y)
                points.append(p)
        else:
            y = parts[0].split('=')[1].replace(',', '')

            s, e = parts[1].split('=')[1].split('..')
            for x in range(int(s), int(e) + 1):
                p = Point(x, y)
                points.append(p)

    return points