-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday_12.py
123 lines (86 loc) · 3.14 KB
/
day_12.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import heapq
from typing import Tuple, Dict
class Node:
def __init__(self, id_: Tuple[int, int], height: int):
self.id_ = id_
self.height = height
self.neighbors = []
def add_neighbor(self, neighbor):
self.neighbors.append(neighbor)
def __str__(self) -> str:
i, j = self.id_
return f"[{i},{j}]"
def __eq__(self, other):
return True
def __lt__(self, other):
return True
def __hash__(self):
return self.id_
def read() -> Tuple[Dict[int, Node], Node, Node]:
with open("input.txt") as file:
lines = file.readlines()
lines = list(map(lambda s: s.strip("\n"), lines))
graph = {}
start_index = None
end_index = None
for i, line in enumerate(lines):
for j, c in enumerate(line):
if c == "S":
height = char_to_height("a")
start_index = (i, j)
elif c == "E":
height = char_to_height("z")
end_index = (i, j)
else:
height = char_to_height(c)
print(f"{height},", end="")
graph[(i, j)] = Node((i, j), height)
print("")
print(f"Num nodes parsed: {len(graph)}")
for (row, col), node in graph.items():
up_idx = (row + 1, col)
down_idx = (row - 1, col)
left_idx = (row, col - 1)
right_idx = (row, col + 1)
for neighbor_idx in [up_idx, down_idx, left_idx, right_idx]:
row, col = neighbor_idx
if row < 0 or col < 0 or row >= len(lines) or col >= len(lines[0]):
continue
if neighbor_idx in graph:
neighbor = graph[neighbor_idx]
if neighbor.height <= node.height + 1:
node.add_neighbor(neighbor)
return graph, graph[start_index], graph[end_index]
def char_to_height(char: str) -> int:
return ord(char) - ord("a")
def get_length_of_shortest_path(start: Node, end: Node) -> int:
queue = []
heapq.heappush(queue, (0, start))
explored = set()
while len(queue) > 0:
distance, node = heapq.heappop(queue)
if node.id_ in explored:
continue
explored.add(node.id_)
if node.id_ == end.id_:
return distance
for neighbor in node.neighbors:
if neighbor.id_ not in explored and neighbor.id_:
heapq.heappush(queue, (distance + 1, neighbor))
raise ValueError("No path was found!")
def main():
graph, start, end = read()
distance = get_length_of_shortest_path(start, end)
print(f"Min distance from start: {distance}")
min_distance = float("inf")
for node in graph.values():
if node.height == 0:
try:
distance = get_length_of_shortest_path(node, end)
if distance < min_distance:
min_distance = distance
except ValueError:
pass
print(f"Global min distance: {min_distance}")
if __name__ == "__main__":
main()