2024 day 16 no networkx.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Mikael CAPELLE 2024-12-16 16:26:35 +01:00
parent c3c73ee517
commit f965eea33a

View File

@ -1,7 +1,7 @@
import heapq
from collections import defaultdict
from typing import Any, Iterator, TypeAlias from typing import Any, Iterator, TypeAlias
import networkx as nx
from ..base import BaseSolver from ..base import BaseSolver
Position: TypeAlias = tuple[int, int] Position: TypeAlias = tuple[int, int]
@ -18,41 +18,45 @@ class Solver(BaseSolver):
target = next( target = next(
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E" (i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E"
) )
facing = (0, 1)
G = nx.DiGraph() queue: list[tuple[int, Position, Direction, tuple[Position, ...]]] = [
(0, rein, (0, 1), (rein,))
]
for i in range(1, n_rows - 1): max_score = n_rows * n_cols * 1000
for j in range(1, n_cols - 1): target_score: int = max_score
if grid[i][j] == "#": scores: dict[tuple[Position, Direction], int] = defaultdict(lambda: max_score)
continue visited: set[Position] = set()
for di, dj in ((-1, 0), (0, 1), (1, 0), (0, -1)): while queue:
if grid[i + di][j + dj] != "#": score, pos, dir, path = heapq.heappop(queue)
G.add_edge(
((i, j), (di, dj)), ((i + di, j + dj), (di, dj)), weight=1
)
if di == 0: if target_score < score:
G.add_edge(((i, j), (di, dj)), ((i, j), (1, 0)), weight=1000) break
G.add_edge(((i, j), (di, dj)), ((i, j), (-1, 0)), weight=1000)
else:
G.add_edge(((i, j), (di, dj)), ((i, j), (0, 1)), weight=1000)
G.add_edge(((i, j), (di, dj)), ((i, j), (0, -1)), weight=1000)
for di, dj in ((-1, 0), (0, 1), (1, 0), (0, -1)): if pos == target:
G.add_edge((target, (di, dj)), (target, (-1, -1)), weight=0) target_score = score
visited |= set(path)
continue
yield nx.shortest_path_length( scores[pos, dir] = score
G,
source=(rein, facing),
target=(target, (-1, -1)),
weight="weight",
)
nodes: set[tuple[int, int]] = set() row, col = pos
for path in nx.all_shortest_paths( d_row, d_col = dir
G, source=(rein, facing), target=(target, (-1, -1)), weight="weight"
): for cost, n_pos, n_dir in (
nodes.update(position for position, _ in path) (1, (row + d_row, col + d_col), dir),
yield len(nodes) (1000, pos, (1, 0) if d_row == 0 else (0, 1)),
(1000, pos, (-1, 0) if d_row == 0 else (0, -1)),
):
n_row, n_col = n_pos
score_n = score + cost
if grid[n_row][n_col] != "#" and score_n < scores[n_pos, n_dir]:
heapq.heappush(
queue,
(score_n, n_pos, n_dir, path + (n_pos,)),
)
assert target_score is not None
yield target_score
yield len(visited)