aboutsummaryrefslogtreecommitdiff
path: root/2021/day15/15a.py
blob: d7c984b5a67f22cd10ff3546d3468e556773b19f (plain)
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
import heapq

grid = [[int(x) for x in l] for l in open("./input").read().strip().split("\n")]

def in_bounds(c):
    x, y = c
    return x >= 0 and y >= 0 and y < len(grid) and x < len(grid[y])

def next_steps(path):
    sx, sy = path[0]
    for c in [(sx + 1, sy), (sx - 1, sy), (sx, sy + 1), (sx, sy - 1)]:
        if c not in path and in_bounds(c):
            yield c

def step_path(path):
    for c in next_steps(path):
        yield [c] + path

def total_risk(path):
    acc = 0
    for x, y in path:
        if (x, y) == (0, 0):
            continue
        risk = grid[y][x]
        acc += risk

    return acc

def manhattan(a, b):
    dx = abs(a[0] - b[0])
    dy = abs(a[1] - b[1])
    return dx + dy

def heuristic(path):
    return total_risk(path) - manhattan(path[0], (len(grid), len(grid[0])))

class HeapItem:
    def __init__(self, path):
        self.heur = heuristic(path)
        self.path = path

    def __lt__(self, other):
        return self.heur < other.heur

def find_path(start):
    q = []
    visited = set()
    heapq.heappush(q, HeapItem([start]))
    while True:
        path = heapq.heappop(q).path
        if path[0] == (len(grid) - 1, len(grid[0]) - 1):
            return path

        if path[0] in visited:
            continue
        visited.add(path[0])

        for new in step_path(path):
            heapq.heappush(q, HeapItem(new))

path = find_path((0, 0))
print(path)
print(total_risk(path))