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\d+):(\s*(?P\d+)\s*)*\|(\s*(?P\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()