57 lines
1.5 KiB
Python
57 lines
1.5 KiB
Python
from __future__ import annotations
|
|
from dataclasses import dataclass
|
|
from collections import deque
|
|
|
|
from aoc import Aoc
|
|
|
|
@dataclass
|
|
class Card:
|
|
card_id: int
|
|
wins: int
|
|
winning: list[int]
|
|
have: list[int]
|
|
|
|
@staticmethod
|
|
def from_line(line: str) -> Card:
|
|
id_section, number_section = line.split(": ")
|
|
_, card_id = [s for s in id_section.split(" ") if s.strip()]
|
|
winning_str, have_str = number_section.split(" | ")
|
|
|
|
winning = [int(nr.strip()) for nr in winning_str.split(" ") if nr.strip()]
|
|
have = [int(nr.strip()) for nr in have_str.split(" ") if nr.strip()]
|
|
|
|
wins = len(set(winning).intersection(have))
|
|
return Card(int(card_id),wins, winning, have)
|
|
|
|
class Day04(Aoc[list[Card]]):
|
|
def __init__(self) -> None:
|
|
super().__init__(2023, 4)
|
|
|
|
def parseinput(self, inpt: str) -> list[Card]:
|
|
lines = inpt.splitlines()
|
|
return [Card.from_line(line) for line in lines]
|
|
|
|
|
|
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:
|
|
stack = deque(range(len(cards)))
|
|
complete = len(cards)
|
|
while stack:
|
|
card_id = stack.popleft()
|
|
for win in range(cards[card_id].wins):
|
|
stack.appendleft(win + card_id + 1)
|
|
complete += 1
|
|
return complete
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> None:
|
|
day4 = Day04()
|
|
day4.run()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|