aboutsummaryrefslogtreecommitdiff
path: root/2021/15/puzzles.py
blob: 0b294f5271d5dd8ec471dcfb444484523a5cd88e (plain) (blame)
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
#!/usr/bin/env python3

from heapq import heappop, heappush
from itertools import product
from typing import NamedTuple

from libaoc import matrix, read_int_matrix


class Node(NamedTuple):
	x: int
	y: int
	r: int

	def __lt__(self, other: tuple[int, int, int]) -> bool:
		return self.r < other.r


def elongate(grid: matrix[int]) -> matrix[int]:
	ngrid: matrix[int] = []
	inc = lambda n: 1 if n == 9 else n + 1
	for p1 in grid:
		p2 = list(map(inc, p1))
		p3 = list(map(inc, p2))
		p4 = list(map(inc, p3))
		p5 = list(map(inc, p4))
		ngrid.append(p1 + p2 + p3 + p4 + p5)

	for i, j in product(range(4), range(l := len(grid))):
		ngrid.append(list(map(inc, ngrid[i * l + j])))

	return ngrid


def main() -> None:
	with open("input", "r", encoding="utf-8") as f:
		data = read_int_matrix(f)

	# START PART 2
	data = elongate(data)
	# END PART 2

	X_UPPER = len(data)
	Y_UPPER = len(data[0])

	heap = [Node(0, 0, 0)]
	visited = {(0, 0)}

	while heap:
		node = heappop(heap)
		if node.x == X_UPPER - 1 and node.y == Y_UPPER - 1:
			print(node.r)
			return

		for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
			xi = node.x + dx
			yi = node.y + dy

			if 0 <= xi < X_UPPER and 0 <= yi < Y_UPPER and (xi, yi) not in visited:
				visited.add((xi, yi))
				heappush(heap, Node(xi, yi, node.r + data[xi][yi]))


if __name__ == "__main__":
	main()