#!/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)