This repository has been archived by the owner on May 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path24_air_duct_spelunking.py
80 lines (64 loc) · 2.38 KB
/
24_air_duct_spelunking.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
#######################################
# --- Day 24: Air Duct Spelunking --- #
#######################################
import AOCUtils
from collections import deque
from itertools import permutations
#######################################
ducts = AOCUtils.loadInput(24)
points = dict()
for x in range(len(ducts)):
for y in range(len(ducts[0])):
if ducts[x][y] in "0123456789":
points[ducts[x][y]] = (x, y)
# Get minimum distance from all points to all points
allDistances = dict()
for a, start in points.items():
for b, dest in points.items():
if (b, a) in allDistances:
allDistances[(a, b)] = allDistances[(b, a)]
continue
if a == b:
allDistances[(a, b)] = 0
continue
queue = deque([(start, 0)])
visited = set()
while queue:
cur, dist = queue.popleft()
if cur in visited: continue
visited.add(cur)
# Optimization (not worth it for this problem size, might be good for larger maps):
# If it's computing a->b and it's at c and c->b has already been computed, a->b = a->c + c->b
# c = ducts[cur[0]][cur[1]]
# if c in "0123456789":
# if (c, b) in allDistances:
# dist += allDistances[(c, b)]
# if (a, b) not in allDistances or dist < allDistances[(a, b)]:
# allDistances[(a, b)] = dist
# continue
if cur == dest:
allDistances[(a, b)] = dist
break
for move in [(0, -1), (0, 1), (-1, 0), (1, 0)]:
nxt = (cur[0]+move[0], cur[1]+move[1])
if ducts[nxt[0]][nxt[1]] != "#":
queue.append((nxt, dist+1))
dests = set(points.keys())
dests.remove("0")
minDist = None
for order in permutations(dests):
order = "0" + "".join(order)
dist = 0
for i in range(1, len(order)):
dist += allDistances[(order[i-1], order[i])]
minDist = min(minDist, dist) if minDist else dist
print("Part 1: {}".format(minDist))
minDist = None
for order in permutations(dests):
order = "0" + "".join(order) + "0"
dist = 0
for i in range(1, len(order)):
dist += allDistances[(order[i-1], order[i])]
minDist = min(minDist, dist) if minDist else dist
print("Part 2: {}".format(minDist))
AOCUtils.printTimeTaken()