diff options
| author | 2022-12-12 10:49:04 +0100 | |
|---|---|---|
| committer | 2022-12-12 10:49:04 +0100 | |
| commit | 126a628b171e2a7d2490290185ab21990b0d9698 (patch) | |
| tree | bce90696bbc1ed94f96f162f141e36b61a13b5b5 | |
| parent | 0af1b042a29811bc5c850267681dc45469981845 (diff) | |
| download | 2022-126a628b171e2a7d2490290185ab21990b0d9698.tar.gz 2022-126a628b171e2a7d2490290185ab21990b0d9698.tar.bz2 2022-126a628b171e2a7d2490290185ab21990b0d9698.zip | |
Day12 [Wip]
| -rw-r--r-- | day12/__init__.py | 137 | ||||
| -rw-r--r-- | day12/example.txt | 5 | ||||
| -rw-r--r-- | day12/input.txt | 41 | ||||
| -rw-r--r-- | day12/test_init.py | 27 |
4 files changed, 210 insertions, 0 deletions
diff --git a/day12/__init__.py b/day12/__init__.py new file mode 100644 index 0000000..52fa2e7 --- /dev/null +++ b/day12/__init__.py | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 2 | import sys | ||
| 3 | from abc import ABC | ||
| 4 | from math import inf, sqrt, floor | ||
| 5 | from typing import List, Tuple, Iterator, Callable, Any | ||
| 6 | |||
| 7 | from aoc import BaseAssignment | ||
| 8 | |||
| 9 | |||
| 10 | class Map: | ||
| 11 | def __init__(self, map: List[str]): | ||
| 12 | self.map = map | ||
| 13 | |||
| 14 | self.height = len(map) | ||
| 15 | self.width = len(map[0]) | ||
| 16 | |||
| 17 | self.start = self.find_unique_position("S") | ||
| 18 | self.end = self.find_unique_position("E") | ||
| 19 | |||
| 20 | def find_unique_position(self, value: str) -> Tuple[int, int]: | ||
| 21 | for y in range(self.height): | ||
| 22 | for x in range(self.width): | ||
| 23 | if self.map[y][x] == value: | ||
| 24 | return x, y | ||
| 25 | |||
| 26 | def neighbours(self, x: int, y: int) -> Iterator[Tuple[int, int]]: | ||
| 27 | for dy in range(max(0, y - 1), min(self.height, y + 2)): | ||
| 28 | for dx in range(max(0, x - 1), min(self.width, x + 2)): | ||
| 29 | current_elevation = self.elevation(x, y) | ||
| 30 | neigbour_elevation = self.elevation(dx, dy) | ||
| 31 | |||
| 32 | if ( | ||
| 33 | (dy == y and dx == x) | ||
| 34 | or (dy == y - 1 and dx == x - 1) | ||
| 35 | or (dy == y - 1 and dx == x + 1) | ||
| 36 | or (dy == y + 1 and dx == x - 1) | ||
| 37 | or (dy == y + 1 and dx == x + 1) | ||
| 38 | or (abs(neigbour_elevation - current_elevation) > 1) | ||
| 39 | ): | ||
| 40 | continue | ||
| 41 | yield dx, dy | ||
| 42 | |||
| 43 | def elevation(self, x: int, y: int): | ||
| 44 | character = self.map[y][x] | ||
| 45 | |||
| 46 | match character: | ||
| 47 | case "S": | ||
| 48 | elevation = ord("a") | ||
| 49 | case "E": | ||
| 50 | elevation = ord("z") | ||
| 51 | case _: | ||
| 52 | elevation = ord(character) | ||
| 53 | |||
| 54 | return elevation - 96 | ||
| 55 | |||
| 56 | |||
| 57 | class Assignment(BaseAssignment, ABC): | ||
| 58 | def distance(self, map: Map, a: Tuple[int, int], b: Tuple[int, int]): | ||
| 59 | distance = abs(map.elevation(*a) - map.elevation(*b)) | ||
| 60 | |||
| 61 | if distance > 1: | ||
| 62 | return inf | ||
| 63 | |||
| 64 | return distance | ||
| 65 | |||
| 66 | def heuristic(self, map: Map, a: Tuple[int, int]): | ||
| 67 | dx = abs(map.start[0] - a[0]) | ||
| 68 | dy = abs(map.start[1] - a[1]) | ||
| 69 | return floor(sqrt(dx**2 + dy**2)) | ||
| 70 | |||
| 71 | def a_star( | ||
| 72 | self, | ||
| 73 | map: Map, | ||
| 74 | start: Tuple[int, int], | ||
| 75 | end: Tuple[int, int], | ||
| 76 | distance: Callable[[Tuple[int, int], Tuple[int, int]], int], | ||
| 77 | heuristic: Callable[[Tuple[int, int]], int], | ||
| 78 | ) -> List[Tuple[int, int]]: | ||
| 79 | open = {start} | ||
| 80 | came_from = {} | ||
| 81 | |||
| 82 | g_scores = {start: 0} | ||
| 83 | |||
| 84 | f_scores = {start: heuristic(start)} | ||
| 85 | |||
| 86 | while True: | ||
| 87 | try: | ||
| 88 | current = sorted( | ||
| 89 | [item for item in open], key=lambda item: f_scores.get(item, inf) | ||
| 90 | )[0] | ||
| 91 | except IndexError: | ||
| 92 | raise RuntimeError("No path found") | ||
| 93 | |||
| 94 | if current == end: | ||
| 95 | path = [current] | ||
| 96 | |||
| 97 | while current in came_from: | ||
| 98 | current = came_from[current] | ||
| 99 | path = [current, *path] | ||
| 100 | |||
| 101 | return path | ||
| 102 | |||
| 103 | open.remove(current) | ||
| 104 | |||
| 105 | for neighbour in map.neighbours(*current): | ||
| 106 | g_score = g_scores.get(current, inf) + distance(current, neighbour) | ||
| 107 | |||
| 108 | if g_score < g_scores.get(neighbour, inf): | ||
| 109 | came_from[neighbour] = current | ||
| 110 | g_scores[neighbour] = g_score | ||
| 111 | f_scores[neighbour] = g_score + heuristic(neighbour) | ||
| 112 | |||
| 113 | if neighbour not in open: | ||
| 114 | open.add(neighbour) | ||
| 115 | |||
| 116 | |||
| 117 | class AssignmentOne(Assignment): | ||
| 118 | example_result = 31 | ||
| 119 | |||
| 120 | def run(self, input: Iterator) -> Any: | ||
| 121 | map = Map(map=list(input)) | ||
| 122 | |||
| 123 | print(map.start, map.end) | ||
| 124 | |||
| 125 | path = self.a_star( | ||
| 126 | map, | ||
| 127 | map.start, | ||
| 128 | map.end, | ||
| 129 | distance=lambda a, b: self.distance(map, a, b), | ||
| 130 | heuristic=lambda a: self.heuristic(map, a), | ||
| 131 | ) | ||
| 132 | |||
| 133 | return len(path) - 1 | ||
| 134 | |||
| 135 | |||
| 136 | class AssignmentTwo(Assignment): | ||
| 137 | pass | ||
diff --git a/day12/example.txt b/day12/example.txt new file mode 100644 index 0000000..86e9cac --- /dev/null +++ b/day12/example.txt | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | Sabqponm | ||
| 2 | abcryxxl | ||
| 3 | accszExk | ||
| 4 | acctuvwj | ||
| 5 | abdefghi | ||
diff --git a/day12/input.txt b/day12/input.txt new file mode 100644 index 0000000..7fc8957 --- /dev/null +++ b/day12/input.txt | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | abcccccccccccccccccccccccccccccccccccccccccccccccccccaaaaacccccccccccccaaaaaaaccccccccccccccccaaaaaaccccccccccccccccccccccccccaaaaacccaaaccccccccccccccccccccccccccccccaaaaa | ||
| 2 | abcccccccccaaaccccccccccccaaaccccccccccccccccccccccccaaaaaacccccccccccccaaaaaaaaaaaccaaaaccccaaaaaaacccccccccccccccccccccccccccaaaaaacaaaaccccccccccccccccccccccccccccccaaaa | ||
| 3 | abcccccccccaaaaaacccccccccaaaacccccccccccccccccccccccaaaaaaccccccccccccaaaaaaaaaaaccaaaaacccaaaaaacccccccccaaacccccccccccccccaaaaaaaacaaaaccccccccccccccccacccccccccccccaaaa | ||
| 4 | abcccccccccaaaaaacccccccccaaaaccccaacccccccccccccccccaaaaaaccccccccccaaaaaaaaaaaaaacaaaaaaccaacaaaccaacccaaaaaaccccccccccccccaaaaaaaacaaaccccccccccaccccaaaccccccccccccaaaaa | ||
| 5 | abcccccccaaaaaaaccccccccccaaaacccaaaaccccccccccccaaccccaaacccccccaaacaaaaaaaaaccccccaaaaaacccccaaaccaacccaaaaaacccccccccccccccccaaccccccccccccccccaaacccaaaccccccccccccaaaca | ||
| 6 | abcccccccaaaaaaacccccccaaacccccccaaaacccccccaaccaaaccccccccccccaaaaacaaaaaaaaaccccccaaaaaccccccccaaaaaaaacaaaaaccaacaaccccccccccaaccccccccccccccccaaaaaaaaaccccccccccccccccc | ||
| 7 | abcccccccccaaaaaaccaaccaaacccccccaaaacccccccaaaaaaaccccccccccccaaaaaaccccaaaaaacccccccaaaccccccccaaaaaaaaaaaaacccaaaaacccccccaaaccccccccccccccccccaaaaaaaackcccccccccccccccc | ||
| 8 | abcccccccccaaaaaaccaaaaaaaccccccccccccccccccaaaaaacccccccccccccaaaaaaccccaaaaaaccccccccccccccccccccaaaaccaaaaaccccaaaaaccccccaaaaaccccaaaaaccccccccaaaajjkkkkkccccccaacccccc | ||
| 9 | abcccccccccaaccccccaaaaaaccccccccccccccccccccaaaaaaaaccccccccccaaaaacccaaaacaaccccccccccccccccccccaaaaaccccccccccaaaaaacccccaaaaaaccccaaaaaccciijjjjjjjjjkkkkkkccaaaaaaccccc | ||
| 10 | abcaaaccccccccccccccaaaaaaaaccccccccccccccccaaaaaaaaacccccccccccaaaacccaaaccaaccccccccccccccccccccaacaaacccccccccaaaacccccccaaaaaacccaaaaaaciiiijjjjjjjjjoopkkkkcaaaaacccccc | ||
| 11 | abaaaacccccccccccccaaaaaaaaaccccccccccccccccaaaaaaaacccccccccccccccccccaaaaaaaccccaccaccccccccccccacccaacccccccccccaaccccccccaaaaacccaaaaaaiiiiiijjjjjjoooppppkkcaaaaaaacccc | ||
| 12 | abaaaaaccccccccccccaaaaaaaaccccccccccccccccaaaaaaaccccccccccccccccccccccaaaaaaccccaaaacccccccccccccccccccccccccccccccccccccccaaaaccccaaaaaiiiinnnoooooooooppppkkkaaaaaaacccc | ||
| 13 | abaaaaacccccccccccaaaaaaaccccccccccccccccccccccaaacccccccccccccccccccaaaaaaaacccccaaaaccccccccccccaaccaacccccaccccacccccccccccccccccccaaaciiinnnnoooooooouupppkkkaaaaaaacccc | ||
| 14 | abaaaaccccccccccccccccaaaccccccccccccccccccccccaaacccccccaaccccccccccaaaaaaaaacccaaaaaacccccccccccaaaaaaccccaaaaaaaacccccccccccccaaccccccciiinnnntttooouuuuupppiiacaaacccccc | ||
| 15 | abaaaacccccccccccccccccaaccccccccccccccccccccccccccccccaaaacacccccccccaaaaaaaacccaaaaaacccccccccccaaaaaccccccaaaaaacccccccccccaaaaaacccccciinnnttttuuuuuuuuuuppiiccaaacccccc | ||
| 16 | abcccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaacccccccccccaaaaaaaccccaacccccaaccccccaaaaaacccccaaaaaacccccccccccaaaaaccccccciinnntttttuuuuxyuuuppiiicccccccccc | ||
| 17 | abccccccccccccccccccccccccccccccccccccaaacccccccaaccccccaaaaccccccccccccaaccccccccccccccccaacaaacaaaaaaaacccaaaaaaaaccccccccccaaaaaaaccccchinnnttxxxxuuxyyyuuppiiiiccccccccc | ||
| 18 | abccccccccccccccccccccccccccccccccccccaaaaaaccccaaacccccaaaaccccccccccccaaccccccccccccccccaaaaaccaaaaaaaaccaaaaaaaaaaccccccccaaaaaaaaccccchhhnnttxxxxxxxyyuvppppiiiccccccccc | ||
| 19 | abccccccccccccccccccccccccccccccccccaaaaaaaaaaccaaaaaaacacaacccccccccccccccccaaaccccccccaaaaaaccccccaacccccaaaaaaaaaaccccccccaaaaaaaaccccchhhnntttxxxxxxyyvvvppqqiiicccccccc | ||
| 20 | abccccccccccccccccccccccccccccaacaccaaaaaaaaaaaaaaaaaaacccccccccccccccccccccaaaaaaccccccaaaaaaacccccaacccccaccaaaaacacccccccccacaaaccccccchhhnnnttxxxxxyyyvvvvqqqqiiiccccccc | ||
| 21 | SbccccccccccccccccccccccccccccaaaaccaaaaaaacaaaaaaaaaaccccccccccccccccccccccaaaaaaccccccccaaaaaaccccccccccccccaaaaccccccccccccccaaacccccchhhmmmtttxxxEzzyyyyvvvqqqqiiccccccc | ||
| 22 | abcccccccccccccccccccccccccccaaaaaccccaaaaaccaaaaaaaaacccccccccccccccaaaaaccaaaaaaccccccccaaccaacccccccccccccccaacccccccaaaaccccccccccccchhhmmmtttxxxyyyyyyyyvvvqqqjjjcccccc | ||
| 23 | abcccaaacccccccccccccccccccccaaaaaacccaacaaaaaaaaaaaaacccccccccccccccaaaaacccaaaaaccccccccaacccccccccccccccccccccccccccaaaaacccccccccccchhhmmmttsxxyyyyyyyyvvvvvqqqjjjcccccc | ||
| 24 | abcccaaaaaacccaacaaccccccccccacaaaacccaacccaaaaaaaaaaaacccccccccccccaaaaaacccaacaaccccccccccccccccccccccccccccccccaacccaaaaaaccccccccccchhhmmmssxxwwwwyyywvvvvvqqqjjjjcccccc | ||
| 25 | abccaaaaaaacccaaaaaccccccccccccaaccccccccccaaaaaaaccaaccccccccccccccaaaaaacccccccccccccccccccccccccccccccccccaaccaaacccaaaaaacccccccaaachhhmmssswwwwwwyyywvvqqqqqqjjjccccccc | ||
| 26 | abcaaaaaaacccccaaaaacccccccccccccccccccccccccccaaaccccccccccccccccccaaaaaacccccccccccaaccccaaccccccccccccccccaaacaaacccaaaaaacccccccaaacgggmmsssswwwswwyywwrrqqqjjjjcccccccc | ||
| 27 | abcaaaaaaaccccaaaaaacccccccccccccccccccccccaaccaaaccccccccccccccccccccaaccccccccccccaaccccaaaacccccccccccccccaaaaaaccccccaacccccccaacaaagggmmmssssssswwwwwwrrqjjjjjddccccccc | ||
| 28 | abcccaaaaaacccaaaacccccccccccccccccccccccccaaacaaccccccccccccccccccccccccccccccccaaaaacaacaaaaccccccccccccccccaaaaaaaaccccccccccccaaaaaagggmmmmssssssswwwwrrrkjjjjddddcccccc | ||
| 29 | abcccaaaaaacccccaaccccccccccccccccccccccccccaaaaaccccccccccccccccccccccccccccccccaaaaaaaacaaaacaaccccccaaccaaaaaaaaaaacccccccccccccaaaaaggggmmmmllllsrrwwwrrkkkjdddddaaacccc | ||
| 30 | abcccaaaccccccccccccaacccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccccccccaaaaacccccccaaaaaaccaaaaaaaaaaaaaacccccccccccccccaaaaaggggmmllllllrrrrrrrkkkdddddaaaccccc | ||
| 31 | abccccaaaaaaccccccccaacaaaccccccccacccaaccaaaaaaaaccccccccccaaaccccccaacccccccccccaaaaaccccccccaaaaacccaaaaaaaaaaaaccccccccccccccccaaacaacggggggflllllrrrrrrkkddddaaaaaccccc | ||
| 32 | abccccaaaaacccccccccaaaaacccccccccaaaaaaccaaaaaaaaccccccccccaaacacccaaaaccccccccccaacaaacccccaaaaaaccccaaaaaaaccaaacccccccccccccccccaacccccggggffffllllrrrrkkkdddaaaaaaacccc | ||
| 33 | abccaaaaaaacccccccaaaaaaccccccccccaaaaaccccccaacccccaaccccaacaaaaaccaaaacccccccaaccccaaccccccaaaaaaaccaaaaaaaaccaaaccccccccccccccccccaaaccccccgffffflllkkkkkkeedaaaaaaaacccc | ||
| 34 | abccaaaaaaacccccccaaaaaaacccccccccaaaaaacccccaacccccaaacccaaaaaaaaccaaaacccaaaaacccccccccccccccaaaaaacaaaaaaaacccccccccccccccccccccccaaaacaacccccffffllkkkkkeeedccaaaaaacccc | ||
| 35 | abccccaaaaaaccccccccaaaaaacccccccaaaaaaaacccccaaccccaaaaaaaaaaaaccccccccccaaaaaaaacccccccccccccaaccaaccccaaaccccccaacccccccccccccccccaaaaaaaccccccfffffkkkkeeeecccaacccccccc | ||
| 36 | abccccaaccaaccccccccaaccaacccccccaaaaaaaacccccaaccaaaaaaaaccaaaaacccccccccaaaaaaaaccccccccccaacaaccccccccaaccccaacaaaccccaacccccccccccaaaaaaccccccaafffeeeeeeecccccccccccccc | ||
| 37 | abccccaaccccccccccccaaccccccccccccccaacccccaaaaaaaaaaaaaaacaaacaaaaaaacaccaaaaaaacccccccaaacaacccccccccccccccccaaaaaccccaaaacccccccaaaaaaaaccccccaaaaffeeeeeeeccccccccccccca | ||
| 38 | abacccccccccccccaaacccccccccccccccccaacccccaaaaaaaaaaaaaacccaaccaaaaaaaaaaaaaccaaacccccccaaaaaccccccccccccccccccaaaaaaccaaaacccccccaaaaaaaaaccccccaaacceeeeeccccccccccccccaa | ||
| 39 | abaaccccccccccaaaaaacccccccccccccccccccccccccaaaacccaaaaaaccccccaaaaaaaaaaaaaaaaaaaccccccaaaaaaacccaaaccccccccaaaaaaaaccaaaaccccccccaaaaaaaaccccccccccccaaacccccccccccaaacaa | ||
| 40 | abaaccccccccccaaaaaacccccccccccccccccccccccccaaaaacaaaaaaaccccccaaaaaaaaaaaaaaaaaaccccccaaaaaaaaccccaaaaccccccaaaaacaaccccccccccccccccaaaaaaacccccccccccacacccccccccccaaaaaa | ||
| 41 | abacccccccccccaaaaaaccccccccccccccccccccccccaaaaaacaaaccaaccccccaaaaaaccaaaaaaaaccccccccaaaaaaaaccaaaaaacccccccccaaaccccccccccccccccccaacccccccccccccccccccccccccccccccaaaaa | ||
diff --git a/day12/test_init.py b/day12/test_init.py new file mode 100644 index 0000000..f721d56 --- /dev/null +++ b/day12/test_init.py | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 2 | from day12 import Map | ||
| 3 | |||
| 4 | |||
| 5 | class TestMap: | ||
| 6 | def test_neighbours(self): | ||
| 7 | |||
| 8 | map_input = ["".join([str(i) for i in range(8)]) for _ in range(5)] | ||
| 9 | |||
| 10 | map = Map(map=map_input) | ||
| 11 | |||
| 12 | assert set(map.neighbours(0, 0)) == { | ||
| 13 | (0, 1), | ||
| 14 | (1, 0), | ||
| 15 | } | ||
| 16 | |||
| 17 | assert set(map.neighbours(0, 4)) == { | ||
| 18 | (0, 3), | ||
| 19 | (1, 4), | ||
| 20 | } | ||
| 21 | |||
| 22 | assert set(map.neighbours(1, 1)) == { | ||
| 23 | (0, 1), | ||
| 24 | (1, 0), | ||
