-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday12.py
More file actions
87 lines (74 loc) · 2.45 KB
/
Copy pathday12.py
File metadata and controls
87 lines (74 loc) · 2.45 KB
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
from typing import List, Optional, Dict, Set, Tuple
from dataclasses import dataclass
import heapq
@dataclass(frozen=True)
class Coords:
x: int
y: int
@dataclass
class Map:
locations: List[List[int]]
start: Coords
end: Coords
def neighbours(self, loc: Coords) -> List[Coords]:
deltas = [(-1, 0), (0, -1), (1, 0), (0, 1)]
neigh = []
for delta in deltas:
newX = delta[0] + loc.x
newY = delta[1] + loc.y
if (
newX >= 0
and newX < len(self.locations[0])
and newY >= 0
and newY < len(self.locations)
):
neigh.append(Coords(x=newX, y=newY))
return neigh
def get_height(self, loc: Coords) -> int:
return self.locations[loc.y][loc.x]
def parse_map(lines: List[str]) -> Map:
locations = []
for idy, line in enumerate(lines):
row = []
for idx, char in enumerate(line.strip()):
if char == "S":
start = Coords(x=idx, y=idy)
row.append(0)
elif char == "E":
end = Coords(x=idx, y=idy)
row.append(ord("z") - ord("a"))
else:
row.append(ord(char) - ord("a"))
locations.append(row)
return Map(locations=locations, start=start, end=end)
def find_path(start: Coords, map: Map) -> int | None:
queue = [(start, 0)]
loc = start
explored = {}
while len(queue) > 0:
loc, distance = queue.pop(0)
if loc in explored:
continue
explored[loc] = True
if loc == map.end:
return distance
height = map.get_height(loc)
for neighbour in map.neighbours(loc):
if neighbour not in explored:
neighbour_height = map.get_height(neighbour)
if neighbour_height <= (height + 1):
queue.append((neighbour, distance + 1))
return None
with open("day12.txt", "r") as file:
map = parse_map(file.readlines())
print(find_path(map.start, map))
min_dist = None
for y in range(len(map.locations)):
for x in range(len(map.locations[0])):
if map.get_height(Coords(x, y)) == 0:
dist = find_path(Coords(x, y), map)
if min_dist is None:
min_dist = dist
elif dist is not None:
min_dist = min(dist, min_dist)
print(min_dist)