day12 finished
This commit is contained in:
parent
28fb30d493
commit
5c0183ab93
5 changed files with 163 additions and 0 deletions
0
advent/days/day12/__init__.py
Normal file
0
advent/days/day12/__init__.py
Normal file
41
advent/days/day12/data/input.txt
Normal file
41
advent/days/day12/data/input.txt
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
abcccaaaaaaccccccccaaaaaccccccaaaaaaccccccaaaaaaaacccaaaaaaaccaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa
|
||||
abcccaaaaaacccccccaaaaaaccccaaaaaaaacccccccaaaaaaaaaaaaaaaaccaaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa
|
||||
abccccaaaaacaaaccaaaaaaaacccaaaaaaaaacccccccaaaaaaaaaaaaaaaacaaaaaacccccccccaaacccccccccccaaaaaaaaccccccccccaaccccccccccccccccaaaaaa
|
||||
abccccaaaaccaaaaaaaaaaaaacccaaaaaaaaaacccccaaaaaaaaaaaaaaaaaaacaaaacccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccccccccccccccccccaaa
|
||||
abcccccccccaaaaaacccaacccccccccaaacaaaccccccaacccccccaaaaaaaaacaacccccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccacaaccccccccccccaaa
|
||||
abcccccccccaaaaaacccaacccccccccaaacccccccccccccccccccaaaacaaaacccccccaacaaccaaaccccccccccaccaaaaacacccccccccaaaacaaaaccccccccccccaac
|
||||
abccccccccccaaaaacccccccccccccccacccaaaacccccccccccccaaaacccccccccccccaaaacccccccccccaacccccaaaaccccccccjjjjaaaaaaaaaccccccccccccccc
|
||||
abccccccccccaaaacccccccccccccccccccaaaaacccccccccccccaaaccccccccccccccaaaaacccccccccaaaaaacccaaccccccccjjjjjjkkaaaacccccccccaacccccc
|
||||
abcccccaaccccccccccccccccccccccccccaaaaaacccccccccccccaacccccccccccccaaaaaaccccccccccaaaaaccccccccccccjjjjjjjkkkkaacccccaacaaacccccc
|
||||
abccaaaacccccccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccaaaacaccccccccaaaaaaaccccaacccccjjjjoooookkkkkkkklllaaaaaaacccc
|
||||
abccaaaaaacccccccccccccccccccccccccaaaaacccccccccccccccccccccccccccccccaaccccccccccaaaaaaaaccaaaaccccjjjoooooookkkkkkkllllaaaaaacccc
|
||||
abcccaaaaacccccccccccccccccccccccccccaaaccccccccaaaacccccccccccccccccccccccccccccccaaaaaaaaccaaaaccccjjooooooooppkkppplllllaccaacccc
|
||||
abccaaaaaccccccccccccaccccccccccccccccccccccccccaaaacccccccccccccccccccccccccccccccccaaacacccaaaacccijjooouuuuoppppppppplllccccccccc
|
||||
abcccccaacccccccccccaaaaaaaaccccccccccccccccccccaaaaccccaaccccccccaaacccccccccccccaacaaccccccccccccciijoouuuuuuppppppppplllcccaccccc
|
||||
abcccccccccccccccccccaaaaaaccccccccccccccccccccccaaccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiiiootuuuuuupuuuvvpppllccccccccc
|
||||
abcccccccccccccccccccaaaaaaccaaaaacccccccccccccccccccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiinnotuuxxxuuuuvvvpppllccccccccc
|
||||
abccccccccccccccacccaaaaaaaacaaaaaaacccccccccccccccccccaaaacccccccaaacccccaaaaccaaaaaccccaaccccccciiiinnnttxxxxuuyyyvvqqqllccccccccc
|
||||
abcccccccccccaaaaccaaaaaaaaaaaaaaaaaaccaacccccccccccccccccccccccccccccccccaaaacccaaaaaccaaacccccciiinnnnnttxxxxxyyyyvvqqqllccccccccc
|
||||
abaaaacccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaacccaaaaaacaaaccccciiinnnnttttxxxxxyyyyvvqqmmmccccccccc
|
||||
abaaaaccccccccaaaaacccaaaaacaaaaaacaaaaaaccccccccccccccccaaccccccccccccccccaacccccccaaaaaaaaaaciiinnnnttttxxxxxyyyyvvqqqmmmccccccccc
|
||||
SbaaaacccccccaaaaaccccaaaaaccaaaaaaaaaaaccccccccccccccccaaacaacccccccccccccccccccccccaaaaaaaaachhhnnntttxxxEzzzzyyvvvqqqmmmccccccccc
|
||||
abaaaacccccccaacaacccccaaaaaaaacaaaaaaaaaccccccccccccccccaaaaaccccccccccccccccccccccccaaaaaaacchhhnnntttxxxxxyyyyyyvvvqqmmmdddcccccc
|
||||
abaaaacccccccccccccccccccaaaaaacaaaaaaaaaacccccccccccccaaaaaaccccccccaaaccccccccccccccaaaaaaccchhhnnntttxxxxywyyyyyyvvvqqmmmdddccccc
|
||||
abaacccccccccccccccccccaaaaaaacccccaaaaaaacccccccccccccaaaaaaaacccccaaaacccccccccccccaaaaaaacaahhhmmmttttxxwwyyyyyyyvvvqqmmmdddccccc
|
||||
abcccccccccccccccccccccaaaaaaacaaccaaacccccccccccccccccaacaaaaacccccaaaacccccccccccccaaacaaaaaahhhmmmmtsssswwyywwwwvvvvqqqmmdddccccc
|
||||
abcccccccccccccccaaaccccaaaaaaaaaacaaccaaccccccccccccccccaaacaccccccaaaacccccccccccccccccaaaaacahhhmmmmmsssswwywwwwwvvrrqqmmdddccccc
|
||||
abcccccccccccccaaaaaaccccaaaaaaaaaccaaaacccccccccccccccccaacccccccccccccccccccccccaaaccccaaaaaaahhhhhmmmmssswwwwwrrrrrrrrmmmmddccccc
|
||||
abcccccccccccccaaaaaaccccaaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaacccccaaaaachhhhhmmmmsswwwwrrrrrrrrrkkmdddccccc
|
||||
abccccccccccccccaaaaaccccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaaccccaaaaacccchhggmmmssswwrrrrrkkkkkkkkdddacccc
|
||||
abccaaaacccccccaaaaacccccccccaaaaaacaaaaacccccccccccccccccccccccccccccccccccccccaaaaaaccccaacaaaccccggggmmsssssrrlkkkkkkkkkdddaccccc
|
||||
abccaaaacccccccaaaaacccccccccaaaaaaccccaacccccccccccccccccccccccccccccccccccccccaaaaaccccccccaaccccccgggmllssssrllkkkkkkkeeeddaccccc
|
||||
abccaaaacccccccaaacccccccccccaaaaaacccccccccccccccccccaacccccccccccccccccccccccaaaaaacccccccccccccccccggllllssslllkkeeeeeeeeeaaacccc
|
||||
abcccaaccccccccaaacaaaccccccaaaaaaaaaaacccccccccccccaaaaaacccccccccccccccccccccaaacaaacccccaacccccccccggglllllllllfeeeeeeeeaaaaacccc
|
||||
abccccccccccaaaaaaaaaaccccccccccccaccaaaccacccccccccaaaaaaccccaaccaacccaaccccccaaaaaaacccccaaccccccccccggglllllllfffeeecccaaaaaacccc
|
||||
abccccccccccaaaaaaaaacccccccccccccccaaaaaaaccccccccccaaaaaccccaaaaaacccaaaaaaccaaaaaacccaaaaaaaacccccccggggllllfffffccccccaacccccccc
|
||||
abcccccccccccaaaaaaacccccccccccccccccaaaaaaccaacccccaaaaaccccccaaaaacccaaaaaacaaaaaaacccaaaaaaaaccccccccgggffffffffccccccccccccccccc
|
||||
abccccccccccccaaaaaaacccccccccccccaaaaaaaaacaaaaccccaaaaacaaaaaaaaaacaaaaaaacaaaaaaaaaccccaaaacccccccccccggffffffacccccccccccccccaaa
|
||||
abccccccccccccaaaaaaacaaccccccccccaaaaaaaaacaaaacccccaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaacccaaaaacccccccccccaffffaaaaccccccccccccccaaa
|
||||
abccccccccccccaaacaaaaaacccccccccccaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaacccaaacaaaccaaaaaacccccccccccccccccaaaccccccccccccccaaa
|
||||
abccccccccccccaaccaaaaaccccccccccccccaaaaaaaccccaaaaaaaaaaaaccccaacccccaaaaaacccaaaccccccaaccaacccccccccccccccccaaacccccccccccaaaaaa
|
||||
abcccccccccccccccaaaaaaaaccccccccccccaacccacccccccaaaaaaaaaaccccaacccccaaccccccccaccccccccccccccccccccccccccccccccccccccccccccaaaaaa
|
||||
5
advent/days/day12/data/test01.txt
Normal file
5
advent/days/day12/data/test01.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Sabqponm
|
||||
abcryxxl
|
||||
accszExk
|
||||
acctuvwj
|
||||
abdefghi
|
||||
93
advent/days/day12/solution.py
Normal file
93
advent/days/day12/solution.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from queue import Queue
|
||||
|
||||
from typing import Iterator, Self
|
||||
|
||||
day_num = 12
|
||||
|
||||
|
||||
def part1(lines: Iterator[str]) -> int:
|
||||
return Map.create(lines).find_path('S')
|
||||
|
||||
|
||||
def part2(lines: Iterator[str]) -> int:
|
||||
return Map.create(lines).find_path('a')
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True, order=True, eq=True)
|
||||
class Position:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
def neighbors(self, width: int, height: int) -> Iterator[Position]:
|
||||
if self.x < width - 1:
|
||||
yield Position(self.x + 1, self.y)
|
||||
if self.y > 0:
|
||||
yield Position(self.x, self.y - 1)
|
||||
if self.x > 0:
|
||||
yield Position(self.x - 1, self.y)
|
||||
if self.y < height - 1:
|
||||
yield Position(self.x, self.y + 1)
|
||||
|
||||
|
||||
@dataclass(slots=True, frozen=True)
|
||||
class Map:
|
||||
map: list[str]
|
||||
width: int
|
||||
height: int
|
||||
|
||||
@classmethod
|
||||
def create(cls, input: Iterator[str]) -> Self:
|
||||
map = list(input)
|
||||
width = len(map[0])
|
||||
height = len(map)
|
||||
return Map(map, width, height)
|
||||
|
||||
def can_climb(self, *, from_pos: Position, to_pos: Position) -> bool:
|
||||
""" Checks if one gan walk from the elevation at from_pos to the elevation at to_pos """
|
||||
from_elevation = self.get_elevation(from_pos)
|
||||
to_elevation = self.get_elevation(to_pos)
|
||||
if to_elevation == 'E':
|
||||
return from_elevation >= 'y'
|
||||
|
||||
if from_elevation == 'S':
|
||||
return to_elevation <= 'b'
|
||||
|
||||
return ord(to_elevation) <= ord(from_elevation) + 1
|
||||
|
||||
def get_elevation(self, position: Position) -> str:
|
||||
""" returns the elevation at the given position """
|
||||
return self.map[position.y][position.x]
|
||||
|
||||
def find_marker(self, point: str) -> Position:
|
||||
""" Returns the position of the first marker matching the argument """
|
||||
for y, row in enumerate(self.map):
|
||||
for x, char in enumerate(row):
|
||||
if char == point:
|
||||
return Position(x, y)
|
||||
|
||||
raise Exception(f"Did not find point {point}")
|
||||
|
||||
def find_path(self, target: str):
|
||||
""" Finds a path backwards from the Endpoint to an elevation/marker target """
|
||||
endpoint = self.find_marker('E')
|
||||
found: set[Position] = {endpoint}
|
||||
queue: Queue[tuple[int, Position]] = Queue()
|
||||
queue.put((0, endpoint))
|
||||
while not queue.empty():
|
||||
current_len, current_pos = queue.get()
|
||||
for next_position in self.next_step(current_pos):
|
||||
if next_position not in found:
|
||||
elevation = self.get_elevation(next_position)
|
||||
if elevation == target:
|
||||
return current_len + 1
|
||||
found.add(next_position)
|
||||
queue.put((current_len + 1, next_position))
|
||||
raise Exception('No Path found')
|
||||
|
||||
def next_step(self, current_pos: Position) -> Iterator[Position]:
|
||||
""" yields all neighbors, that could have been the previous step to this one"""
|
||||
for neighbor in current_pos.neighbors(self.width, self.height):
|
||||
if self.can_climb(from_pos=neighbor, to_pos=current_pos):
|
||||
yield neighbor
|
||||
24
advent/days/day12/test_solution.py
Normal file
24
advent/days/day12/test_solution.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
from advent.common import input
|
||||
|
||||
from .solution import Map, day_num, part1, part2
|
||||
|
||||
|
||||
def test_part1():
|
||||
lines = input.read_lines(day_num, 'test01.txt')
|
||||
expected = 31
|
||||
result = part1(lines)
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_part2():
|
||||
lines = input.read_lines(day_num, 'test01.txt')
|
||||
expected = 29
|
||||
result = part2(lines)
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_path():
|
||||
lines = input.read_lines(day_num, 'test01.txt')
|
||||
expected = 31
|
||||
result = Map.create(lines).find_path('S')
|
||||
assert result == expected
|
||||
Loading…
Add table
Add a link
Reference in a new issue