# -*- coding: utf-8 -*- from abc import ABC from enum import Enum from functools import reduce from typing import Iterator from aoc import BaseAssignment, I, T class Color(Enum): red = "red" green = "green" blue = "blue" ColorCount = tuple[int, Color] class Assignment(BaseAssignment, ABC): def parse_item(self, item: str) -> list[tuple[ColorCount, ...]]: _, items = item.split(": ") return [ tuple( ColorCount((int(_.split(" ")[0]), Color(_.split(" ")[1]))) for _ in pair.split(", ") ) for pair in items.split("; ") ] class AssignmentOne(Assignment): example_result = 8 inventory = { Color.red: 12, Color.green: 13, Color.blue: 14, } def is_possible(self, game: list[tuple[ColorCount, ...]]): for item in game: for count, color in item: if count > self.inventory[color]: return False return True def run(self, input: Iterator[list[tuple[ColorCount, ...]]]) -> int: possible_games = [] for index, game in enumerate(input): if self.is_possible(game): possible_games.append(index + 1) return sum(possible_games) class AssignmentTwo(Assignment): example_result = 2286 def get_least_numbers(self, game: list[tuple[ColorCount, ...]]): counts = {} for item in game: for count, color in item: if color not in counts or count > counts[color]: counts[color] = count return counts def run(self, input: Iterator[list[tuple[ColorCount, ...]]]) -> int: powers = [] for game in input: counts = self.get_least_numbers(game) powers.append(reduce(lambda total, item: total * item, counts.values(), 1)) return sum(powers)