from dataclasses import dataclass from typing import Any, Iterator, Literal, cast import parse # type: ignore from ..base import BaseSolver @dataclass(frozen=True) class Reindeer: name: str speed: int fly_time: int rest_time: int class Solver(BaseSolver): def solve(self, input: str) -> Iterator[Any]: lines = input.splitlines() reindeers: list[Reindeer] = [] for line in lines: reindeer, speed, speed_time, rest_time = cast( tuple[str, int, int, int], parse.parse( # type: ignore "{} can fly {:d} km/s for {:d} seconds, " "but then must rest for {:d} seconds.", line, ), ) reindeers.append( Reindeer( name=reindeer, speed=speed, fly_time=speed_time, rest_time=rest_time ) ) target = 1000 if len(reindeers) <= 2 else 2503 states: dict[Reindeer, tuple[Literal["resting", "flying"], int]] = { reindeer: ("resting", 0) for reindeer in reindeers } distances: dict[Reindeer, int] = {reindeer: 0 for reindeer in reindeers} points: dict[Reindeer, int] = {reindeer: 0 for reindeer in reindeers} for time in self.progress.wrap(range(target)): for reindeer in reindeers: if states[reindeer][0] == "flying": distances[reindeer] += reindeer.speed top_distance = max(distances.values()) for reindeer in reindeers: if distances[reindeer] == top_distance: points[reindeer] += 1 for reindeer in reindeers: if states[reindeer][1] == time: if states[reindeer][0] == "resting": states[reindeer] = ("flying", time + reindeer.fly_time) else: states[reindeer] = ("resting", time + reindeer.rest_time) yield max(distances.values()) yield max(points.values()) - 1