NEIGHBOR_DELTAS = [(1, 0), (0, -1), (-1, 0), (0, 1)] grid = {(x, y): int(r) for y, row in enumerate(puzzle_input_raw.splitlines()) for x, r in enumerate(row)} START = (0, 0) END = (max(c[0] for c in grid.keys()), max(c[1] for c in grid.keys())) class Graph: def __init__(self, grid): self.grid = grid def children(self, loc): return [ n for d in NEIGHBOR_DELTAS if (n := tuple(map(sum, zip(loc, d)))) in self.grid ] def cost(self, from_, to): return self.grid[to] graph = Graph(grid) problem = StartEndGraphProblem(graph, START, END) paths, _ = dijkstra(problem) shortest_path = reconstruct_path(paths, problem) print(sum(grid[x] for x in shortest_path) - grid[START])
for x, c in enumerate(r)} # get all number targets targets = {p: c for p, c in grid.items() if c.isdigit()} # get all combinations of paths hops = [(s, e) for s, e in itertools.combinations(targets, 2) if s != e] class Map(GridGraph): def __init__(self, grid): self.grid = grid def children(self, loc): return [ n for n in self.generate_4_neighbors(loc) if self.grid.get(n, "#") != "#" ] graph = Map(grid) shortest_paths = {} for start, end in hops: problem = StartEndGraphProblem(graph, start, end) paths, _ = dijkstra(problem) shortest_paths[frozenset( (grid[start], grid[end]))] = len(reconstruct_path(paths, problem)) - 1 edges = {x: [y for y in targets.values() if y != x] for x in targets.values()} tsp_graph = WeightedUndirectedGraph(edges, shortest_paths) print(travelling_salesman_problem(tsp_graph, "0"))