aoc2023/day17.py
2023-12-17 13:13:44 +01:00

59 lines
1.8 KiB
Python

from heapq import heappush, heappop
from tools.aoc import AOCDay
from tools.coordinate import Coordinate
from tools.grid import Grid
from typing import Any
def walk(grid: Grid, start: Coordinate, min_steps: int = 0, max_steps: int = 3) -> int:
q = [(0, start, Coordinate(0, 0), 0)]
v = {}
while q:
cost, pos, last_dir, last_dir_count = heappop(q)
if (pos, last_dir, last_dir_count) in v:
continue
v[pos, last_dir, last_dir_count] = cost
if 0 < last_dir_count < min_steps:
n = pos + last_dir
if grid.isWithinBoundaries(n):
heappush(q, (cost + grid.get(n), n, last_dir, last_dir_count + 1))
else:
for n in grid.getNeighboursOf(pos, includeDiagonal=False, includeDefault=False):
new_dir = n - pos
new_dir_count = last_dir_count + 1 if new_dir == last_dir else 1
if new_dir.reverse() != last_dir and (new_dir != last_dir or last_dir_count < max_steps):
heappush(q, (cost + grid.get(n), n, new_dir, new_dir_count))
min_cost = int(1e9)
for (pos, _, _), cost in v.items():
if pos == Coordinate(grid.maxX, grid.maxY):
min_cost = min(min_cost, cost)
return min_cost
class Day(AOCDay):
inputs = [
[
(102, "input17_test"),
(870, "input17"),
],
[
(94, "input17_test"),
(1063, "input17"),
]
]
def part1(self) -> Any:
grid = Grid.from_data(self.getInput(), translate={'[0-9]': int})
return walk(grid, Coordinate(0, 0))
def part2(self) -> Any:
grid = Grid.from_data(self.getInput(), translate={'[0-9]': int})
return walk(grid, Coordinate(0, 0), 4, 10)
if __name__ == '__main__':
day = Day(2023, 17)
day.run(verbose=True)