Exemplo n.º 1
0
def _find_least_risk_path(grid: IntGrid, tiles: int) -> list[tuple[int, int]]:
    start = (0, 0)
    end = (tiles * grid.get_height() - 1, tiles * grid.get_width() - 1)
    q = PriorityQueue()
    q.put((0, start))
    best = defaultdict(lambda: 1E9)
    best[start] = 0
    seen = {start}
    parent = {}
    while not q.empty():
        risk, cell = q.get()
        if cell == end:
            path = [end]
            curr = end
            while curr in parent:
                curr = parent[curr]
                path.append(curr)
            return path
        seen.add(cell)
        c_total = best[cell]
        for n in _find_neighbours(grid, *cell, tiles):
            if n in seen:
                continue
            new_risk = c_total + _get_risk(grid, *n)
            if new_risk < best[n]:
                best[n] = new_risk
                parent[n] = cell
                q.put((new_risk, n))
    raise RuntimeError("Unsolvable")
Exemplo n.º 2
0
def _cycle(grid: IntGrid) -> int:
    [grid.increment(c) for c in grid.get_cells()]
    flashes = Flashes()
    [
        _flash(grid, c, flashes) for c in grid.get_cells()
        if grid.get_value(c) > 9
    ]
    return flashes.get()
Exemplo n.º 3
0
def _get_risk(grid: IntGrid, row: int, col: int) -> int:
    value = grid.get_value_at(row % grid.get_height(),
                              col % grid.get_width()) \
            + row // grid.get_height() \
            + col // grid.get_width()
    while value > 9:
        value -= 9
    return value
Exemplo n.º 4
0
def _size_of_basin_around_low(grid: IntGrid, c: Cell) -> int:
    basin = set[Cell]()
    q = deque[Cell]()
    q.append(c)
    while len(q) > 0:
        cell = q.popleft()
        basin.add(cell)
        for n in _find_neighbours(grid, cell):
            if n not in basin and grid.get_value(n) != 9:
                q.append(n)
    log(basin)
    log(len(basin))
    return len(basin)
Exemplo n.º 5
0
def _flash(grid: IntGrid, c: Cell, flashes: Flashes) -> None:
    grid.set_value(c, 0)
    flashes.increment()
    for n in _find_neighbours(grid, c):
        if grid.get_value(n) == 0:
            continue
        grid.increment(n)
        if grid.get_value(n) > 9:
            _flash(grid, n, flashes)
Exemplo n.º 6
0
def _parse(inputs: tuple[str]) -> IntGrid:
    return IntGrid([[int(_) for _ in list(r)] for r in inputs])
Exemplo n.º 7
0
def _find_neighbours(grid: IntGrid, c: Cell) -> Generator[Cell]:
    return (Cell(c.row + d.x, c.col + d.y) for d in Headings.OCTANTS()
            if c.row + d.x >= 0 and c.row + d.x < grid.get_height() and c.col +
            d.y >= 0 and c.col + d.y < grid.get_width())
Exemplo n.º 8
0
def _find_lows(grid: IntGrid) -> Generator[Cell]:
    for low in (c for c in grid.get_cells() if (all(
            grid.get_value(c) < grid.get_value(n)
            for n in _find_neighbours(grid, c)))):
        log(low)
        yield low
Exemplo n.º 9
0
def _find_neighbours(grid: IntGrid, c: Cell) -> Generator[Cell]:
    return (Cell(c.row + dr, c.col + dc)
            for dr, dc in ((-1, 0), (0, 1), (1, 0), (0, -1))
            if c.row + dr >= 0 and c.row + dr < grid.get_height() and c.col +
            dc >= 0 and c.col + dc < grid.get_width())
Exemplo n.º 10
0
def _find_neighbours(grid: IntGrid, row: int, col: int, tiles: int) \
        -> Generator[tuple[int, int]]:
    return ((row + dr, col + dc)
            for dr, dc in ((-1, 0), (0, 1), (1, 0), (0, -1))
            if row + dr >= 0 and row + dr < tiles * grid.get_height() and col +
            dc >= 0 and col + dc < tiles * grid.get_width())