diff --git a/2022/day12.py b/2022/day12.py new file mode 100644 index 0000000..7c4bdb1 --- /dev/null +++ b/2022/day12.py @@ -0,0 +1,131 @@ +# -*- encoding: utf-8 -*- + +import heapq +import sys + + +def dijkstra( + start: tuple[int, int], end: tuple[int, int], grid: list[list[int]] +) -> list[tuple[int, int]] | None: + n_rows = len(grid) + n_cols = len(grid[0]) + + def heuristic(row: int, col: int) -> int: + return abs(end[0] - row) + abs(end[1] - col) + + queue: list[tuple[tuple[int, int], tuple[int, int]]] = [] + visited: set[tuple[int, int]] = set() + lengths: dict[tuple[int, int], int] = {} + parents: dict[tuple[int, int], tuple[int, int]] = {} + + heapq.heappush(queue, ((heuristic(start[0], start[1]), 0), start)) + + while queue: + (_, length), (c_row, c_col) = heapq.heappop(queue) + + visited.add((c_row, c_col)) + + if (c_row, c_col) == end: + break + + for n_row, n_col in ( + (c_row - 1, c_col), + (c_row + 1, c_col), + (c_row, c_col - 1), + (c_row, c_col + 1), + ): + + if not (n_row >= 0 and n_row < n_rows and n_col >= 0 and n_col < n_cols): + continue + + if (n_row, n_col) in visited: + continue + + if grid[n_row][n_col] > grid[c_row][c_col] + 1: + continue + + if length + 1 < lengths.get((n_row, n_col), n_rows * n_cols): + lengths[n_row, n_col] = length + 1 + parents[n_row, n_col] = (c_row, c_col) + + heapq.heappush( + queue, + ( + (heuristic(n_row, n_col) + length + 1, length + 1), + (n_row, n_col), + ), + ) + + if end not in visited: + return None + + path: list[tuple[int, int]] = [end] + + while path[-1] != start: + path.append(parents[path[-1]]) + + return list(reversed(path)) + + +def print_path(path: list[tuple[int, int]], n_rows: int, n_cols: int) -> None: + _, end = path[0], path[-1] + + graph = [["." for _c in range(n_cols)] for _r in range(n_rows)] + graph[end[0]][end[1]] = "E" + + for i in range(0, len(path) - 1): + cr, cc = path[i] + nr, nc = path[i + 1] + + if cr == nr and nc == cc - 1: + graph[cr][cc] = "<" + elif cr == nr and nc == cc + 1: + graph[cr][cc] = ">" + elif cr == nr - 1 and nc == cc: + graph[cr][cc] = "v" + elif cr == nr + 1 and nc == cc: + graph[cr][cc] = "^" + else: + assert False, "{} -> {} infeasible".format(path[i], path[i + 1]) + + print("\n".join("".join(row) for row in graph)) + + +lines = sys.stdin.read().splitlines() + +grid = [[ord(cell) - ord("a") for cell in line] for line in lines] + +start: tuple[int, int] +end: tuple[int, int] + +# for part 2 +start_s: list[tuple[int, int]] = [] + +for i_row, row in enumerate(grid): + for i_col, col in enumerate(row): + if chr(col + ord("a")) == "S": + start = (i_row, i_col) + start_s.append(start) + elif chr(col + ord("a")) == "E": + end = (i_row, i_col) + elif col == 0: + start_s.append((i_row, i_col)) + +# fix values +grid[start[0]][start[1]] = 0 +grid[end[0]][end[1]] = ord("z") - ord("a") + +path = dijkstra(start, end, grid) +assert path is not None + +print_path(path, n_rows=len(grid), n_cols=len(grid[0])) + +answer_1 = len(path) - 1 +print(f"answer 1 is {answer_1}") + +answer_2 = min( + len(path) - 1 + for start in start_s + if (path := dijkstra(start, end, grid)) is not None +) +print(f"answer 2 is {answer_2}") diff --git a/2022/inputs/day12.txt b/2022/inputs/day12.txt new file mode 100644 index 0000000..5dab450 --- /dev/null +++ b/2022/inputs/day12.txt @@ -0,0 +1,41 @@ +abcccccccaaaaaaaaccccccccccaaaaaaccccccaccaaaaaaaccccccaacccccccccaaaaaaaaaaccccccccccccccccccccccccccccccccaaaaa +abcccccccaaaaaaaaacccccccccaaaaaacccccaaacaaaaaaaaaaaccaacccccccccccaaaaaaccccccccccccccccccccccccccccccccccaaaaa +abcccccccaaaaaaaaaaccccccccaaaaaacaaacaaaaaaaaaaaaaaaaaaccccccccccccaaaaaaccccccccccccccaaacccccccccccccccccaaaaa +abaaacccccccaaaaaaacccccccccaaacccaaaaaaaaaaaaaaaaaaaaaaaaacccccccccaaaaaaccccccccccccccaaacccccccccccccccccaaaaa +abaaaaccccccaaaccccccccccccccccccccaaaaaaaaacaaaacacaaaaaacccccccccaaaaaaaacccccccccccccaaaaccaaacccccccccccaccaa +abaaaaccccccaaccccaaccccccccccccccccaaaaaaacaaaaccccaaaaaccccccccccccccccacccccccccccccccaaaaaaaaacccccccccccccca +abaaaaccccccccccccaaaacccccccccaacaaaaaaaacccaaacccaaacaacccccccccccccccccccccccccccciiiiaaaaaaaacccccccccccccccc +abaaacccccccccccaaaaaacccccccccaaaaaaaaaaacccaaacccccccaacccccccccccaacccccccccccccciiiiiiijaaaaccccccccaaccccccc +abaaaccccccccccccaaaacccccccccaaaaaaaacaaacccaaaccccccccccccccccccccaaacaaacccccccciiiiiiiijjjacccccccccaaacccccc +abcccccaacaacccccaaaaaccccccccaaaaaacccccacaacccccccccccccccccccccccaaaaaaaccccccciiiinnnoijjjjjjjjkkkaaaaaaacccc +abcccccaaaaacccccaacaaccccccccccaaaacccaaaaaaccccccccccccccccccccccccaaaaaaccccccciiinnnnooojjjjjjjkkkkaaaaaacccc +abccccaaaaacccccccccccccccccccccaccccccaaaaaaaccccccccccccccccccccaaaaaaaaccccccchhinnnnnoooojjooopkkkkkaaaaccccc +abccccaaaaaaccccccccccccccccccccccccccccaaaaaaacccccccccccccccccccaaaaaaaaacccccchhhnnntttuooooooopppkkkaaaaccccc +abccccccaaaaccccccccccacccccccccccccccccaaaaaaacccaaccccccccccccccaaaaaaaaaaccccchhhnnttttuuoooooppppkkkaaaaccccc +abccccccaccccccccccccaaaacaaaccccccccccaaaaaacaaccaacccaaccccccccccccaaacaaacccchhhnnnttttuuuuuuuuupppkkccaaccccc +abccccccccccccccaaccccaaaaaaaccccccccccaaaaaacaaaaaacccaaaaaaccccccccaaacccccccchhhnnntttxxxuuuuuuupppkkccccccccc +abcccccccccccccaaaacccaaaaaaacccaccccccccccaaccaaaaaaacaaaaaaccccccccaacccaaccchhhhnnnttxxxxuuyyyuupppkkccccccccc +abcccccccccccccaaaaccaaaaaaaaacaaacccccccccccccaaaaaaaaaaaaaccccccccccccccaaachhhhmnnnttxxxxxxyyyuvppkkkccccccccc +abcccccccccccccaaaacaaaaaaaaaaaaaaccccccccccccaaaaaacaaaaaaaccccccccccccccaaaghhhmmmttttxxxxxyyyyvvpplllccccccccc +abccacccccccccccccccaaaaaaaaaaaaaaccccccccccccaaaaaacccaaaaaacccaacaacccaaaaagggmmmttttxxxxxyyyyvvppplllccccccccc +SbaaaccccccccccccccccccaaacaaaaaaaacccccccccccccccaacccaaccaacccaaaaacccaaaagggmmmsttxxxEzzzzyyvvvppplllccccccccc +abaaaccccccccccccccccccaaaaaaaaaaaaacaaccccccccccccccccaaccccccccaaaaaccccaagggmmmsssxxxxxyyyyyyvvvqqqlllcccccccc +abaaacccccccccccccccccccaaaaaaaaaaaaaaaaacccccccccccccccccccccccaaaaaaccccaagggmmmsssxxxwywyyyyyyvvvqqlllcccccccc +abaaaaacccccccccccccccccccaacaaaccaaaaaaacccccccccccccccccccccccaaaaccccccaagggmmmssswwwwwyyyyyyyvvvqqqllcccccccc +abaaaaaccccccccccccccccccccccaaaccccaaaacccccccccccccccccaaccaacccaaccccccccgggmmmmssssswwyywwvvvvvvqqqlllccccccc +abaaaaacccccccccccccaccacccccaaaccccaaaacccccccccccccccccaaaaaacccccccccccaaggggmllllsssswwywwwvvvvqqqqlllccccccc +abaaccccccccccccccccaaaaccccccccccccaccaccccccccccccccccccaaaaacccccccccccaaagggglllllssswwwwwrrqqqqqqmmllccccccc +abaaccccccccccccccccaaaaaccccccaaccaaccccccccccccccccccccaaaaaaccaacccccccaaaaggfffllllsswwwwrrrrqqqqqmmmcccccccc +abacaaaccccccccccccaaaaaaccccccaaaaaaccccccaacccccccccccaaaaaaaacaaacaaccccaaaaffffflllsrrwwwrrrmmmmmmmmmcccccccc +abaaaaaccccccccccccaaaaaaccccccaaaaaccccccaaaaccccccccccaaaaaaaacaaaaaaccccaaaaccfffflllrrrrrrkkmmmmmmmccccaccccc +abaaaacccccccccccccccaaccccccccaaaaaacccccaaaacccccccccccccaaccaaaaaaaccccccccccccffflllrrrrrkkkmmmmmccccccaccccc +abaaacccccccccccccccccccccccccaaaaaaaaccccaaaacccccccccccccaaccaaaaaaacccccccccccccfffllkrrrkkkkmddddcccccaaacccc +abaaacccccccccccccccccccccccccaaaaaaaacccccccccccccccccccccccccccaaaaaaccccccccccccfffllkkkkkkkdddddddcaaaaaacccc +abaaaacccccccccccccccccccccccccccaaccccccccccccccccccccccccccccccaacaaacccccccccccccfeekkkkkkkddddddcccaaaccccccc +abcaaacccccccccccaaaccccccccaacccaaccccaaaaaccccaaaccccccccccccccaaccccccccccccccccceeeeekkkkdddddccccccaaccccccc +abccccccccccccccaaaaaaccccccaaacaaccacaaaaaaaccaaaaccccccccccaccaaccccccccccccccccccceeeeeeeedddacccccccccccccccc +abccccccccccccccaaaaaacccccccaaaaacaaaaaccaaaaaaaacccccccccccaaaaacccccccccccccccccccceeeeeeedaaacccccccccccccaaa +abccccccaaacccccaaaaacccccccaaaaaacaaaaaaaaaaaaaaaccccccccccccaaaaaccccccccccccccccccccceeeeecaaacccccccccccccaaa +abccccccaaaccccccaaaaacccccaaaaaaaaccaaaaacaaaaaaccccccccccccaaaaaacccccccccccccccccccccaaaccccaccccccccccccccaaa +abccccaacaaaaacccaaaaacccccaaaaaaaacaaaaaaaaaaaaaaaccccaaaaccaaaacccccccccccccccccccccccaccccccccccccccccccaaaaaa +abccccaaaaaaaaccccccccccccccccaaccccaacaaaaaaaaaaaaaaccaaaaccccaaacccccccccccccccccccccccccccccccccccccccccaaaaaa