Skip to content

Commit b23f24c

Browse files
committed
Implement 2024 day 16 part 2
1 parent f0556c6 commit b23f24c

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

2024/src/aoc/days/day16.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,75 @@
22

33
import numpy
44

5-
from . import SeparateRunner
5+
from . import CombinedRunner
66

77
TURNS = (
88
(-1, 1),
99
(1, -1),
1010
)
1111

1212

13-
class DayRunner(SeparateRunner):
13+
class DayRunner(CombinedRunner):
1414
@classmethod
15-
def part1(cls, input: str) -> int:
15+
def run_both(cls, input: str) -> tuple[int, int]:
1616
grid = numpy.array([list(line) for line in input.strip().split("\n")])
1717

1818
y, x = numpy.where(grid == "S")
1919
x, y = x[0], y[0]
2020

2121
todo = [(0, x, y, 1, 0)]
2222
best = {
23-
(x, y, 1, 0): 0,
23+
(x, y, 1, 0): (0, []),
2424
}
2525

26-
def enqueue(dist, x, y, dx, dy):
26+
def enqueue(dist, x, y, dx, dy, cx, cy, cdx, cdy):
2727
if grid[y, x] == "#":
2828
return
2929

30-
if (x, y, dx, dy) not in best or best[x, y, dx, dy] > dist:
31-
best[x, y, dx, dy] = dist
30+
if (x, y, dx, dy) not in best or best[x, y, dx, dy][0] > dist:
31+
best[x, y, dx, dy] = (dist, [(cx, cy, cdx, cdy)])
3232
heapq.heappush(todo, (dist, x, y, dx, dy))
33+
elif best[x, y, dx, dy][0] == dist:
34+
best[x, y, dx, dy][1].append((cx, cy, cdx, cdy))
35+
36+
shortest_dist = None
37+
finishes = set()
3338

3439
while todo:
3540
dist, x, y, dx, dy = heapq.heappop(todo)
3641

37-
if best[x, y, dx, dy] < dist:
42+
if best[x, y, dx, dy][0] < dist:
3843
continue
3944

45+
if shortest_dist is not None and shortest_dist < dist:
46+
break
47+
4048
if grid[y, x] == "E":
41-
return dist
49+
shortest_dist = dist
50+
finishes.add((x, y, dx, dy))
4251

43-
enqueue(dist + 1, x + dx, y + dy, dx, dy)
44-
enqueue(dist + 2001, x - dx, y - dy, dx, dy)
52+
enqueue(dist + 1, x + dx, y + dy, dx, dy, x, y, dx, dy)
53+
enqueue(dist + 2001, x - dx, y - dy, dx, dy, x, y, dx, dy)
4554

4655
for tx, ty in TURNS:
4756
ndx = dy * ty
4857
ndy = dx * ty
4958

50-
enqueue(dist + 1001, x + ndx, y + ndy, ndx, ndy)
59+
enqueue(dist + 1001, x + ndx, y + ndy, ndx, ndy, x, y, dx, dy)
5160

52-
raise ValueError("Did not find path to exit")
61+
assert shortest_dist is not None, "Should find a path to the exit"
5362

54-
@classmethod
55-
def part2(cls, input: str) -> int:
56-
pass
63+
visited_tiles = {(x, y) for x, y, _, _ in finishes}
64+
todo2 = [f for f in finishes]
65+
visited_states = set(todo2)
66+
67+
while todo2:
68+
state = todo2.pop()
69+
70+
for prev in best[state][1]:
71+
if prev not in visited_states:
72+
visited_states.add(prev)
73+
visited_tiles.add((prev[0], prev[1]))
74+
todo2.append(prev)
75+
76+
return shortest_dist, len(visited_tiles)

0 commit comments

Comments
 (0)