71 lines
1.5 KiB
Python
71 lines
1.5 KiB
Python
from enum import Enum
|
|
from typing import Tuple, Iterable
|
|
|
|
import aoc
|
|
|
|
HexPos = Tuple[int, int, int]
|
|
|
|
|
|
class Direction(Enum):
|
|
N = 0
|
|
NE = 1
|
|
SE = 2
|
|
S = 3
|
|
SW = 4
|
|
NW = 5
|
|
|
|
@classmethod
|
|
def parse(cls, s: str):
|
|
match s:
|
|
case 'n': return Direction.N
|
|
case 's': return Direction.S
|
|
case 'ne': return Direction.NE
|
|
case 'nw': return Direction.NW
|
|
case 'se': return Direction.SE
|
|
case 'sw': return Direction.SW
|
|
case _: raise ValueError(f"unknown direction: {s}")
|
|
|
|
|
|
def part1():
|
|
steps = map(Direction.parse, aoc.puzzle_input(11).split(","))
|
|
return distance(walk(steps))
|
|
|
|
|
|
def part2():
|
|
steps = map(Direction.parse, aoc.puzzle_input(11).split(","))
|
|
pos = (0, 0, 0)
|
|
far = pos
|
|
for step in steps:
|
|
pos = move(pos, step)
|
|
if distance(pos) > distance(far):
|
|
far = pos
|
|
return distance(far)
|
|
|
|
|
|
def walk(steps: Iterable[Direction]) -> HexPos:
|
|
pos = (0, 0, 0)
|
|
for step in steps:
|
|
pos = move(pos, step)
|
|
return pos
|
|
|
|
|
|
def distance(pos: HexPos) -> int:
|
|
assert sum(pos) == 0, pos
|
|
return sum(map(abs, pos)) // 2
|
|
|
|
|
|
def move(pos: HexPos, dir: Direction) -> HexPos:
|
|
(q, r, s) = pos
|
|
match dir:
|
|
case Direction.N: return (q, r-1, s+1)
|
|
case Direction.S: return (q, r+1, s-1)
|
|
|
|
case Direction.NE: return (q+1, r-1, s)
|
|
case Direction.SW: return (q-1, r+1, s)
|
|
|
|
case Direction.NW: return (q-1, r, s+1)
|
|
case Direction.SE: return (q+1, r, s-1)
|
|
|
|
|
|
print(part1())
|
|
print(part2())
|