mirror of
https://github.com/cupcakearmy/advent-of-code.git
synced 2024-12-22 08:06:25 +00:00
90 lines
2.0 KiB
Python
90 lines
2.0 KiB
Python
|
from typing import List, Union, Tuple, Set, Self
|
||
|
from dataclasses import dataclass
|
||
|
|
||
|
type Point = Tuple[int, int]
|
||
|
|
||
|
TURN = {
|
||
|
# (-1,0) > (0, 1) -> (1, 0) -> (0, -1)
|
||
|
(-1, 0): (0, 1),
|
||
|
(0, 1): (1, 0),
|
||
|
(1, 0): (0, -1),
|
||
|
(0, -1): (-1, 0),
|
||
|
}
|
||
|
|
||
|
|
||
|
@dataclass
|
||
|
class Map:
|
||
|
fields: List[List[bool]]
|
||
|
position: Point
|
||
|
direction: Point
|
||
|
max_y: int = 0
|
||
|
max_x: int = 0
|
||
|
|
||
|
def __post_init__(self):
|
||
|
self.max_y = len(self.fields)
|
||
|
self.max_x = len(self.fields[0])
|
||
|
|
||
|
def next_step(self):
|
||
|
return (
|
||
|
self.position[0] + self.direction[0],
|
||
|
self.position[1] + self.direction[1],
|
||
|
)
|
||
|
|
||
|
def get(self, point: Point) -> Union[bool, None]:
|
||
|
y, x = point
|
||
|
try:
|
||
|
return self.fields[y][x]
|
||
|
except IndexError:
|
||
|
return None
|
||
|
|
||
|
def walk(self):
|
||
|
visited: Set[Point] = set()
|
||
|
while True:
|
||
|
visited.add(self.position)
|
||
|
next_step = self.next_step()
|
||
|
content = self.get(next_step)
|
||
|
if content is None:
|
||
|
# Exited map
|
||
|
break
|
||
|
if content:
|
||
|
# Turn
|
||
|
self.direction = TURN[self.direction]
|
||
|
next_step = self.next_step()
|
||
|
self.position = next_step
|
||
|
|
||
|
return len(visited)
|
||
|
|
||
|
@staticmethod
|
||
|
def parse(raw: str) -> Self:
|
||
|
fields = [[f == "#" for f in line] for line in raw.splitlines()]
|
||
|
# Find init
|
||
|
position = (0, 0)
|
||
|
direction = (-1, 0) # Up
|
||
|
for y, line in enumerate(raw.splitlines()):
|
||
|
for x, f in enumerate(line):
|
||
|
if f == "^":
|
||
|
position = (y, x)
|
||
|
return Map(fields, position, direction)
|
||
|
|
||
|
|
||
|
def solve(raw: str) -> int:
|
||
|
# Part 1
|
||
|
part1 = 0
|
||
|
part2 = 0
|
||
|
|
||
|
m = Map.parse(raw)
|
||
|
part1 = m.walk()
|
||
|
|
||
|
return (part1, part2)
|
||
|
|
||
|
|
||
|
# Test
|
||
|
with open("./2024/06/test.txt", "r") as f:
|
||
|
result = solve(f.read().strip())
|
||
|
print(result)
|
||
|
|
||
|
# Input
|
||
|
with open("./2024/06/input.txt", "r") as f:
|
||
|
result = solve(f.read().strip())
|
||
|
print(result)
|