Skip to content

Commit c41e9f7

Browse files
committed
2024: Day 18 - Part 1 - A*
1 parent eaa70a3 commit c41e9f7

File tree

1 file changed

+27
-28
lines changed

1 file changed

+27
-28
lines changed

2024/python/day18/__main__.py

+27-28
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,41 @@
11
from collections.abc import Iterable, Container
2+
from heapq import heappush, heappop
23

34
from utils.file import read_input, int_list_line
45

56
falling_bytes = [complex(x,y) for x,y in (int_list_line(line, ",") for line in read_input(__package__))]
67
start = 0j
78
goal = 70+70j if len(falling_bytes) > 50 else 6+6j
89

9-
def neighbors(node: complex, walls: Container[complex]) -> Iterable[complex]:
10-
for direction in [1, -1, 1j, -1j]:
11-
neighbor = node + direction
12-
if neighbor.real < 0 or neighbor.imag < 0 or neighbor.real > goal.real or neighbor.imag > goal.imag:
13-
continue
14-
if neighbor not in walls:
15-
yield neighbor
16-
17-
def heuristic(node: complex, goal: complex) -> int:
18-
return int(abs(node.real - goal.real) + abs(node.imag - goal.imag)) + int(abs(node.real - node.imag))
1910

20-
def walk(corruption_size: int) -> Iterable[tuple[list[complex], int]]:
11+
def astar(corruption_size: int) -> int:
2112
corrupted = set(falling_bytes[:corruption_size])
13+
14+
def neighbors(current: complex) -> Iterable[complex]:
15+
for direction in [1, 1j, -1, -1j]:
16+
neighbor = current + direction
17+
if 0 <= neighbor.real <= goal.real and 0 <= neighbor.imag <= goal.imag and neighbor not in corrupted:
18+
yield neighbor
19+
20+
def heuristic(current: complex) -> int:
21+
return int(abs(current.real - goal.real) + abs(current.imag - goal.imag))
22+
2223
best_score = None
23-
visited = {start: 0}
24-
# position, score, path
25-
stack: list[tuple[complex, int, list[complex]]] = [(start, 0, [start])]
26-
while stack:
27-
stack.sort(key=lambda x: x[1] + heuristic(x[0], goal))
28-
node, score, path = stack.pop()
29-
if score > best_score:
24+
visited = {}
25+
h = []
26+
heappush(h, (0, 0, (start.real, start.imag)))
27+
28+
while h:
29+
_, score, node_t = heappop(h)
30+
node = complex(*node_t)
31+
if node in visited:
3032
continue
33+
if node == goal:
34+
return score
3135
visited[node] = score if node not in visited else min(score, visited[node])
32-
for neighbor in neighbors(node, corrupted):
36+
for neighbor in neighbors(node):
3337
new_score = score + 1
34-
if neighbor == goal:
35-
#print("Path found", new_score, len(stack))
36-
best_score = min(best_score, new_score) if best_score else new_score
37-
yield path + [neighbor], new_score
38-
if neighbor not in visited or new_score < visited[neighbor]:
39-
stack.append((neighbor, new_score, path + [neighbor]))
40-
41-
paths = list(walk(1024))
42-
print("Part 1:", min(score for path, score in paths))
38+
heappush(h, (new_score + heuristic(neighbor), new_score, (neighbor.real, neighbor.imag)))
39+
raise RuntimeError("No path found")
40+
41+
print("Part 1:", astar(1024))

0 commit comments

Comments
 (0)