56 lines
1.4 KiB
Python
56 lines
1.4 KiB
Python
from __future__ import annotations
|
|
from dataclasses import dataclass
|
|
import regex
|
|
|
|
from aoc import Aoc2, AocParseLinesSameParser
|
|
|
|
|
|
@dataclass
|
|
class Card:
|
|
card_id: int
|
|
wins: int
|
|
win: list[int]
|
|
have: list[int]
|
|
|
|
@staticmethod
|
|
def from_line(line: str) -> Card:
|
|
matches = regex.match(
|
|
r"Card\s*(?P<card_id>\d+):(\s*(?P<win>\d+)\s*)*\|(\s*(?P<have>\d+)\s*)*",
|
|
line,
|
|
)
|
|
if matches is None:
|
|
raise RuntimeError(f'Could not parse "{line}"')
|
|
|
|
win = [int(d) for d in matches.captures("win")]
|
|
have = [int(d) for d in matches.captures("have")]
|
|
|
|
wins = len(set(win).intersection(have))
|
|
return Card(int(matches["card_id"]), wins, win, have)
|
|
|
|
|
|
class Day04(AocParseLinesSameParser[Card], Aoc2[list[Card], list[Card]]):
|
|
def __init__(self) -> None:
|
|
Aoc2.__init__(self, 2023, 4)
|
|
|
|
def parseline(self, inpt: str) -> Card:
|
|
return Card.from_line(inpt)
|
|
|
|
def part1(self, cards: list[Card]) -> int:
|
|
return sum(2 ** (card.wins - 1) for card in cards if card.wins)
|
|
|
|
def part2(self, cards: list[Card]) -> int:
|
|
d = [0] * len(cards)
|
|
for card in reversed(cards):
|
|
d[card.card_id - 1] = 1 + sum(
|
|
d[card.card_id + i] for i in range(card.wins)
|
|
)
|
|
return sum(d)
|
|
|
|
|
|
def main() -> None:
|
|
day4 = Day04()
|
|
day4.run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|