-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path20.py
103 lines (87 loc) · 2.99 KB
/
20.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from lib import *
input = read_input(2019, 20)
(*maze,) = map(list, input.splitlines())
hei = len(maze)
wid = len(maze[0])
portals = {}
links = {}
for i in range(2, hei - 2):
for j in range(2, wid - 2):
if maze[i][j] != ".":
continue
if "A" <= maze[i][j - 1] <= "Z":
maze[i][j] = (maze[i][j - 2] + maze[i][j - 1]).lower()
if "A" <= maze[i][j + 1] <= "Z":
maze[i][j] = (maze[i][j + 1] + maze[i][j + 2]).lower()
if "A" <= maze[i - 1][j] <= "Z":
maze[i][j] = (maze[i - 2][j] + maze[i - 1][j]).lower()
if "A" <= maze[i + 1][j] <= "Z":
maze[i][j] = (maze[i + 1][j] + maze[i + 2][j]).lower()
name = maze[i][j]
if name == ".":
continue
if name in portals:
portals[name].append((i, j))
links[portals[name][0]] = portals[name][1]
links[portals[name][1]] = portals[name][0]
else:
portals[name] = [(i, j)]
visited = set()
Q = [(0, *portals["aa"][0])]
while Q:
d, i, j = heapq.heappop(Q)
if (i, j) in visited:
continue
visited.add((i, j))
if maze[i][j] == "zz":
print(d)
break
if (i, j) in links:
heapq.heappush(Q, (d + 1, *links[(i, j)]))
for p, q in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if maze[p][q] == "." or "aa" <= maze[p][q] <= "zz":
heapq.heappush(Q, (d + 1, p, q))
(*maze,) = map(list, input.splitlines())
hei = len(maze)
wid = len(maze[0])
portals = {}
links = {}
for i in range(2, hei - 2):
for j in range(2, wid - 2):
if maze[i][j] != ".":
continue
if "A" <= maze[i][j - 1] <= "Z":
maze[i][j] = (maze[i][j - 2] + maze[i][j - 1]).lower()
if "A" <= maze[i][j + 1] <= "Z":
maze[i][j] = (maze[i][j + 1] + maze[i][j + 2]).lower()
if "A" <= maze[i - 1][j] <= "Z":
maze[i][j] = (maze[i - 2][j] + maze[i - 1][j]).lower()
if "A" <= maze[i + 1][j] <= "Z":
maze[i][j] = (maze[i + 1][j] + maze[i + 2][j]).lower()
name = maze[i][j]
if name == ".":
continue
inner = i not in (2, hei - 3) and j not in (2, wid - 3)
if name in portals:
portals[name].append((i, j))
links[portals[name][0]] = (portals[name][1], 1 - 2 * inner)
links[portals[name][1]] = (portals[name][0], 2 * inner - 1)
else:
portals[name] = [(i, j)]
visited = set()
Q = [(0, *portals["aa"][0], 0)]
while Q:
d, i, j, m = heapq.heappop(Q)
if (i, j, m) in visited:
continue
visited.add((i, j, m))
if maze[i][j] == "zz" and m == 0:
print(d)
break
if (i, j) in links:
link, change = links[(i, j)]
if m + change >= 0:
heapq.heappush(Q, (d + 1, *link, m + change))
for p, q in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if maze[p][q] == "." or "aa" <= maze[p][q] <= "zz":
heapq.heappush(Q, (d + 1, p, q, m))