advent-of-code/2024/16/one_opti.py
2024-12-25 12:59:49 +01:00

94 lines
2.1 KiB
Python

#!/usr/bin/env python3
import pprint
import sys
input_file = sys.argv[1]
with open(input_file) as fd:
lines = [line.rstrip() for line in fd.readlines()]
height = len(lines)
width = len(lines[0])
vec = tuple[int, int]
directions = [
(-1, 0), # ^ North
(0, 1), # > East
(1, 0), # v South
(0, -1), # < West
]
directions_keys = ("^", ">", "v", "<")
min_scores: list[list[list[None | int]]] = list()
for _ in range(height):
line: list[list[None | int]] = list()
for _ in range(width):
cell: list[None | int] = [None] * len(directions)
line.append(cell)
min_scores.append(line)
start = height - 2, 1
def walk(pos: vec, dir: int, score: int, depth: int = 0) -> int | None:
i, j = pos
char = lines[i][j]
if depth > 1000:
return None
# print("-" * depth, 28, pos, char, directions_keys[dir], score)
if char == "E":
return score
elif char == "#":
return None
min_score = min_scores[i][j][dir]
for d, min_score in enumerate(min_scores[i][j]):
if min_score is None:
continue
if d == dir:
if score >= min_score:
return None
else:
if score >= min_score + 1000:
return None
min_scores[i][j][dir] = score
mscore = None
for ndir, direction in enumerate(directions):
ii, jj = i + direction[0], j + direction[1]
price = 1 if dir == ndir else 1001
nscore = walk((ii, jj), ndir, score + price, depth + 1)
if nscore is None:
continue
if mscore is None or nscore < mscore:
mscore = nscore
return mscore
sys.setrecursionlimit(3000)
tot_score = walk(start, 1, 0)
# Viz
for i in range(height):
cline = ""
for j in range(width):
char = lines[i][j]
min_score = None
for d in range(len(directions)):
score = min_scores[i][j][d]
if score is None:
continue
if min_score is None or score < min_score:
char = directions_keys[d]
min_score = score
cline += char
print(cline)
print()
print(tot_score)