# -*- coding: utf-8 -*- from abc import ABC from typing import Iterator from aoc import BaseAssignment I = tuple[list[int], list[int]] T = int class Assignment(BaseAssignment, ABC): def winning_numbers(self, winning: list[int], owned: list[int]) -> set[int]: return set(winning) & set(owned) def parse_numbers(self, numbers: str) -> list[int]: return [int(num) for num in numbers.split(" ") if num != ""] def parse_item(self, item: str) -> I: _, numbers = item.split(": ") winning, owned = numbers.split(" | ") return self.parse_numbers(winning), self.parse_numbers(owned) class AssignmentOne(Assignment): example_result = 13 def points(self, winning: list[int], owned: list[int]) -> int: overlap = len(self.winning_numbers(winning, owned)) return overlap if overlap < 2 else 2 ** (overlap - 1) def run(self, input: Iterator[I]) -> T: return sum(self.points(winning, owned) for winning, owned in input) class AssignmentTwo(Assignment): example_result = 30 def run(self, input: Iterator[I]) -> T: cards = list(input) count = {index: 1 for index, _ in enumerate(cards)} for index, (winning, owned) in enumerate(cards): for i in range(len(self.winning_numbers(winning, owned))): winning_index = index + i + 1 if winning_index in count: count[winning_index] += count[index] return sum(count.values())