diff --git a/2023/python/Day02.py b/2023/python/Day02.py new file mode 100644 index 0000000000000000000000000000000000000000..c1a7ba83dab9c25dafa5eb18b3106daebe2312df --- /dev/null +++ b/2023/python/Day02.py @@ -0,0 +1,83 @@ +from enum import Enum +from typing import List, Dict + +from ImportData import import_data + +day: int = 2 + + +class Color(Enum): + RED = 1 + GREEN = 2 + BLUE = 3 + + +sample_data: List[str] = ''' +Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green +'''.split('\n')[1:-1] + +data_structure: type = List[List[Dict[Color, int]]] + + +def parse_data(data: List[str]) -> data_structure: + games: List[List[Dict[Color, int]]] = [] + expected_game_number: int = 0 + for game in data: + revelations: List[Dict[Color, int]] = [] + game_identification, game_data = game.split(': ') + # validate my assumption that I can use a list without explicitly tracking the game number + expected_game_number += 1 + actual_game_number = int(game_identification.split(' ')[1]) + assert expected_game_number == actual_game_number + # and now on with the show + for reveal_data in game_data.split('; '): + revelation: Dict[Color, int] = {Color.RED: 0, Color.GREEN: 0, Color.BLUE: 0} + for reveal_datum in reveal_data.split(', '): + number_of_cubes = int(reveal_datum.split(' ')[0]) + color = getattr(Color, reveal_datum.split(' ')[1].upper()) + revelation[color] = number_of_cubes + revelations.append(revelation) + games.append(revelations) + return games + + +def is_possible(game: List[Dict[Color, int]], cubes: Dict[Color, int]) -> bool: + game_is_possible: bool = True + for revelations in game: + for color in revelations: + if revelations[color] > cubes[color]: + game_is_possible = False + return game_is_possible + + +def part1(data: data_structure) -> int: + score: int = 0 + cubes: Dict[Color, int] = {Color.RED: 12, Color.GREEN: 13, Color.BLUE: 14} + for index, game in enumerate(data): + if is_possible(game, cubes): + score += index + 1 + return score + + +def fewest_cubes(game: List[Dict[Color, int]]) -> Dict[Color, int]: + reds: List[int] = [revelations[Color.RED] for revelations in game] + greens: List[int] = [revelations[Color.GREEN] for revelations in game] + blues: List[int] = [revelations[Color.BLUE] for revelations in game] + return {Color.RED: max(reds), Color.GREEN: max(greens), Color.BLUE: max(blues)} + + +def part2(data: data_structure) -> int: + powers = [cubes[Color.RED] * cubes[Color.GREEN] * cubes[Color.BLUE] for cubes in + [fewest_cubes(game) for game in data]] + return sum(powers) + + +if __name__ == '__main__': + production_ready = True + raw_data = import_data(day) if production_ready else sample_data + print(part1(parse_data(raw_data))) + print(part2(parse_data(raw_data)))