diff --git a/2023/d02/ex2/ex2.py b/2023/d02/ex2/ex2.py new file mode 100755 index 0000000..26b5315 --- /dev/null +++ b/2023/d02/ex2/ex2.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python + +import functools +import operator as op +import sys +from enum import StrEnum + + +class Color(StrEnum): + RED = "red" + GREEN = "green" + BLUE = "blue" + + +Round = dict[Color, int] +Game = list[Round] + +# The input is in order without skipping, but just in case... +GameRecord = dict[int, Game] + +BAG_CONTENTS = { + Color.RED: 12, + Color.GREEN: 13, + Color.BLUE: 14, +} + + +def solve(input: list[str]) -> int: + def parse_round(round: str) -> Round: + values = (value.split(" ") for value in round.split(", ")) + return {Color(c): int(n) for n, c in values} + + # This does *not* expect the "Game :" bit + def parse_game(game: str) -> Game: + rounds = game.split("; ") + return [parse_round(r) for r in rounds] + + def parse_line(line: str) -> tuple[int, Game]: + game_id, rounds = line.split(": ") + return int(game_id.removeprefix("Game ")), parse_game(rounds) + + def parse(input: list[str]) -> GameRecord: + parsed = map(parse_line, input) + return {id: game for id, game in parsed} + + def min_cubes(game: Game) -> dict[Color, int]: + res = {c: 0 for c in Color} + + for r in game: + for c, count in r.items(): + res[c] = max(res[c], count) + + return res + + def power(game: Game) -> int: + return functools.reduce(op.mul, min_cubes(game).values()) + + games = parse(input) + return sum(map(power, games.values())) + + +def main() -> None: + input = sys.stdin.read().splitlines() + print(solve(input)) + + +if __name__ == "__main__": + main()