|
1 | 1 | #!/usr/bin/env python |
2 | 2 | import networkx as nx |
3 | 3 |
|
4 | | - |
5 | | -def path(graph, source, target): |
6 | | - try: |
7 | | - return nx.shortest_path_length(graph, source, target) |
8 | | - except: |
9 | | - return -1 |
10 | | - |
11 | | - |
12 | | -# fmt: off |
13 | 4 | t = { |
14 | | - complex(r, c): ord(s) |
| 5 | + k: ord(v) -ord("a") |
15 | 6 | for r, line in enumerate(open(0)) |
16 | | - for c, s in enumerate(line.strip()) |
| 7 | + for c, v in enumerate(line.strip()) |
| 8 | + for k in [complex(r, c)] |
| 9 | + if (v == "S" and (s := k)) or (v == "E" and (e := k)) or True |
17 | 10 | } |
18 | | -# fmt: on |
19 | | -s = next(k for k, v in t.items() if v == ord("S")) |
20 | | -e = next(k for k, v in t.items() if v == ord("E")) |
21 | | - |
22 | | -t[s] = ord("a") |
23 | | -t[e] = ord("z") |
24 | | - |
25 | | -G = nx.DiGraph() |
26 | | - |
27 | | -for k, v in t.items(): |
28 | | - for d in (-1, 1, -1j, 1j): |
29 | | - if (n := k + d) in t: |
30 | | - if t[n] - v <= 1: |
31 | | - G.add_edge(k, n) |
32 | | - |
33 | | -print(nx.shortest_path_length(G, s, e)) |
34 | | -# fmt: off |
35 | | -print(min( |
36 | | - l |
37 | | - for k, v in t.items() |
38 | | - if v == ord("a") and (l := path(G, k, e)) >= 0 |
39 | | -)) |
| 11 | +t[s], t[e] = 0, ord("z") - ord("a") |
| 12 | +G = nx.DiGraph( |
| 13 | + incoming_graph_data=( |
| 14 | + (k, n) |
| 15 | + for k, v in t.items() |
| 16 | + for d in (-1, 1, -1j, 1j) |
| 17 | + if (n := k + d) in t and t[n] - v <= 1 |
| 18 | + ) |
| 19 | +) |
| 20 | +paths = list(nx.single_target_shortest_path_length(G, e)) |
| 21 | +print(next(v for k, v in paths if k == s)) |
| 22 | +print(min(v for k, v in paths if t[k] == 0)) |
| 23 | + |
| 24 | +## BFS example, but slower than networkx |
| 25 | +# |
| 26 | +# from collections import deque |
| 27 | +# |
| 28 | +# |
| 29 | +# def bfs(t, s, e): |
| 30 | +# queue, seen = deque([(s, 0)]), set([s]) |
| 31 | +# |
| 32 | +# while queue: |
| 33 | +# k, size = queue.popleft() |
| 34 | +# |
| 35 | +# if k == e: |
| 36 | +# return size |
| 37 | +# |
| 38 | +# for d in (-1, 1, -1j, 1j): |
| 39 | +# if (n := k + d) in t and n not in seen and t[n] - t[k] <= 1: |
| 40 | +# queue.append((n, size + 1)) |
| 41 | +# seen.add(n) |
| 42 | +# |
| 43 | +# |
| 44 | +# print(bfs(t, s, e)) |
0 commit comments