-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpart2.py
68 lines (46 loc) · 1.94 KB
/
part2.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
from collections import defaultdict
DIRECTIONS = [(0, 1), (1, 0), (0, -1), (-1, 0)]
with open('input.txt') as file:
terrain = list(filter(None, map(str.strip, file)))
width, height = len(terrain[0]), len(terrain)
start_y, start_x = 0, terrain[0].index('.')
end_y, end_x = height - 1, terrain[height - 1].index('.')
def get_neighbours(x: int, y: int) -> list[tuple[int, int]]:
yield from (
(x + dx, y + dy)
for dy, dx in DIRECTIONS
if 0 <= x + dx < width and 0 <= y + dy < height
)
def find_intersections(x, y, prev=None, distance=0):
if prev and sum(terrain[test_y][test_x] != '#' for test_x, test_y in get_neighbours(x, y)) > 2:
yield ((x, y), distance)
return
for new_x, new_y in get_neighbours(x, y):
if (new_x, new_y) == prev:
continue
if terrain[new_y][new_x] != '#':
yield from find_intersections(new_x, new_y, (x, y), distance + 1)
first_intersection, before_first_distance = next(find_intersections(start_x, start_y))
last_intersection, after_last_distance = next(find_intersections(end_x, end_y))
intesections_graph = defaultdict(dict)
todo = [first_intersection]
while todo:
x, y = todo.pop()
intesections_graph[y][x] = list(find_intersections(x, y))
todo.extend(
(x, y)
for (x, y), _ in intesections_graph[y][x]
if x not in intesections_graph.get(y, [])
)
def find_logest_path(x: int, y: int, visited: list[list[bool]]) -> int:
if (x, y) == last_intersection:
return 0
length = float('-inf')
visited[y][x] = True
for (new_x, new_y), distance in intesections_graph[y][x]:
if not visited[new_y][new_x]:
length = max(length, find_logest_path(new_x, new_y, visited) + distance)
visited[y][x] = False
return length
visited = [[False] * width for _ in range(height)]
print(before_first_distance + find_logest_path(*first_intersection, visited) + after_last_distance)