diff --git a/.gitignore b/.gitignore index 94beb0c..134e75f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /build/ __pycache__/ *.egg-info/ +.coverage diff --git a/02/__main__.py b/02/__main__.py deleted file mode 100644 index b842131..0000000 --- a/02/__main__.py +++ /dev/null @@ -1,14 +0,0 @@ -from pathlib import Path - -from puzzle import solve_pt_1, solve_pt_2 - - -def main(): - input = Path(__file__).parent.joinpath("games.txt").read_text().strip().split("\n") - print("Sum of IDs of Valid Games:") - print("Part 1 -", solve_pt_1(input)) - print("Part 2 -", solve_pt_2(input)) - - -if __name__ == "__main__": - main() diff --git a/02/game.py b/02/game.py deleted file mode 100644 index 5866bc7..0000000 --- a/02/game.py +++ /dev/null @@ -1,55 +0,0 @@ -from __future__ import annotations - -import re -from dataclasses import dataclass - -game_id_pattern = re.compile(r"^Game (\d+)$") -draw_yield_description_pattern = re.compile(r"(\d+) (\w+)") - - -@dataclass -class Game: - id: int - draws: list[dict[str, int]] - - @classmethod - def parse(cls, desc: str) -> Game: - try: - id_segment, draws_segment = desc.split(":") - except: - raise ValueError("Game description is invalid.") - - # Parse game ID - id_match = game_id_pattern.match(id_segment) - if not id_match: - raise ValueError("Game description is invalid.") - id = int(id_match.group(1)) - - # Parse draws - draws = [] - for draw_desc in draws_segment.split(";"): - draw = {} - for yield_desc in draw_desc.split(","): - yield_match = draw_yield_description_pattern.match(yield_desc.strip()) - if not yield_match: - raise ValueError("Game description is invalid.") - yield_quantity = int(yield_match.group(1)) - yield_name = yield_match.group(2) - draw[yield_name] = yield_quantity - draws.append(draw) - - return Game(id, draws) - - def meets_configuration(self, bag: dict[str, int]) -> bool: - for draw in self.draws: - for name, quantity in draw.items(): - if quantity > bag.get(name, 0): - return False - return True - - def minimum_configuration(self) -> dict[str, int]: - config: dict[str, int] = {} - for draw in self.draws: - for name, quantity in draw.items(): - config[name] = max(quantity, config.get(name, 0)) - return config diff --git a/02/game_test.py b/02/game_test.py deleted file mode 100644 index 46300b1..0000000 --- a/02/game_test.py +++ /dev/null @@ -1,82 +0,0 @@ -import pytest -from game import Game - - -def test_parse_games(): - assert Game.parse("Game 3: 1 red") == Game(3, [{"red": 1}]) - assert Game.parse( - "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green", - ) == Game( - 1, - [ - { - "blue": 3, - "red": 4, - }, - { - "red": 1, - "green": 2, - "blue": 6, - }, - { - "green": 2, - }, - ], - ) - - with pytest.raises(ValueError): - assert Game.parse("Game 1") - - with pytest.raises(ValueError): - assert Game.parse(":") - - -def test_meets_configuration(): - bag = {"red": 5, "green": 5, "blue": 5} - - assert Game( - 1, - [ - {"red": 3, "blue": 5}, - {"green": 2, "blue": 3}, - {"red": 4}, - ], - ).meets_configuration(bag) - - assert not Game( - 2, - [ - {"green": 3}, - {"red": 6, "blue": 2}, - {"blue": 2}, - ], - ).meets_configuration(bag) - - assert not Game( - 3, - [{"orange": 1}], - ).meets_configuration(bag) - - -def test_minimum_configuration(): - assert Game( - 1, - [ - {"red": 3, "blue": 5}, - {"green": 2, "blue": 3}, - {"red": 4}, - ], - ).minimum_configuration() == {"red": 4, "blue": 5, "green": 2} - - assert Game( - 2, - [ - {"red": 1}, - {"blue": 1}, - {"green": 1}, - ], - ).minimum_configuration() == { - "red": 1, - "blue": 1, - "green": 1, - } diff --git a/02/games.txt b/02/games.txt deleted file mode 100644 index 72084d0..0000000 --- a/02/games.txt +++ /dev/null @@ -1,100 +0,0 @@ -Game 1: 7 blue, 4 red, 11 green; 2 red, 2 blue, 7 green; 2 red, 13 blue, 8 green; 18 blue, 7 green, 5 red -Game 2: 3 green, 4 red, 4 blue; 6 red, 4 green, 4 blue; 2 blue, 4 green, 3 red -Game 3: 1 red, 2 green, 3 blue; 1 red, 2 green; 2 green, 3 red; 1 blue, 2 red -Game 4: 1 red, 15 green; 1 green, 2 blue; 12 green, 1 red, 2 blue; 14 green; 2 green, 1 blue, 2 red -Game 5: 8 red; 7 red; 11 red, 4 green; 1 blue, 8 red; 6 red, 2 green, 1 blue; 8 green, 13 red, 1 blue -Game 6: 3 blue, 2 red, 6 green; 2 red, 8 green, 1 blue; 1 red, 3 blue -Game 7: 5 green, 1 red, 1 blue; 6 blue, 12 red; 6 red, 7 green; 3 green, 1 blue -Game 8: 10 red, 6 green; 4 blue, 6 green, 5 red; 8 green, 5 red, 5 blue; 2 red, 4 blue -Game 9: 11 blue, 13 red, 3 green; 13 red, 1 green, 6 blue; 8 blue, 4 green, 5 red; 16 red, 7 green, 10 blue; 16 red, 5 green, 6 blue; 17 red, 6 blue -Game 10: 16 blue, 8 green; 2 red, 4 green, 1 blue; 15 blue; 4 red, 5 green, 4 blue -Game 11: 3 blue, 8 red, 10 green; 10 red, 6 green; 1 red, 1 green; 13 red, 1 green, 1 blue; 3 green, 7 red; 2 blue, 6 green, 2 red -Game 12: 1 red, 10 green; 4 red, 6 green, 1 blue; 9 green, 1 blue, 7 red; 1 blue, 13 green, 2 red; 2 blue, 5 red, 11 green -Game 13: 1 red, 5 blue; 1 red, 6 green; 2 blue, 1 red; 2 blue, 1 red, 2 green; 5 green, 2 blue -Game 14: 4 green; 8 blue, 1 red, 2 green; 7 red, 2 green, 4 blue; 4 blue, 7 green; 7 blue, 2 green, 1 red; 7 blue, 5 red -Game 15: 10 green, 3 red; 8 blue, 14 green, 3 red; 4 red, 1 green, 12 blue -Game 16: 8 red, 4 blue, 6 green; 14 blue, 9 red, 10 green; 1 red, 5 blue, 8 green; 14 blue, 11 green, 3 red -Game 17: 20 blue, 5 red, 4 green; 3 red, 14 blue; 4 red, 4 blue, 4 green; 12 blue, 5 red, 3 green -Game 18: 7 blue, 8 red; 1 blue, 2 red; 1 green, 2 blue -Game 19: 14 green, 4 blue; 6 green; 12 green, 5 blue; 12 green, 1 red, 1 blue; 4 blue, 10 green -Game 20: 3 green, 4 blue, 4 red; 13 blue, 1 red, 2 green; 13 blue, 9 green, 9 red -Game 21: 4 green, 2 blue, 2 red; 3 green, 2 blue; 1 blue, 5 green; 1 blue, 2 red, 3 green; 1 green, 1 blue, 2 red; 6 blue, 1 green -Game 22: 4 red, 17 green; 15 green, 3 blue, 2 red; 4 blue, 7 red, 11 green; 16 green, 4 red; 3 blue, 2 red -Game 23: 19 green, 2 blue, 3 red; 1 red, 2 blue, 2 green; 2 blue, 10 green, 11 red -Game 24: 1 red, 3 blue; 2 blue; 1 green, 1 red, 3 blue; 1 red, 1 green -Game 25: 12 green, 2 red, 10 blue; 6 green, 3 red; 3 green, 18 blue, 3 red; 17 green, 3 red, 18 blue -Game 26: 4 red, 12 blue, 5 green; 3 green, 5 red, 1 blue; 6 blue, 4 green, 1 red; 6 blue, 7 green; 3 green, 5 red, 2 blue; 1 green, 2 blue, 9 red -Game 27: 1 red, 9 green; 3 green; 9 green, 2 blue, 1 red; 10 green, 1 blue; 1 red, 5 green, 3 blue -Game 28: 10 red, 8 green; 2 blue, 4 green, 7 red; 2 green, 9 red, 1 blue -Game 29: 5 blue, 5 green, 3 red; 1 green, 2 blue, 3 red; 2 green, 3 blue, 5 red; 3 red, 11 blue -Game 30: 11 red, 5 green; 4 blue, 3 green, 5 red; 6 blue, 3 green, 5 red -Game 31: 2 blue, 8 green, 14 red; 9 green; 1 red, 1 blue, 4 green; 2 green, 10 red; 1 red, 10 green, 2 blue; 8 green, 14 red -Game 32: 14 green, 6 red, 6 blue; 1 red, 2 blue, 15 green; 2 red, 18 green, 1 blue -Game 33: 16 green, 4 red; 18 green, 3 red; 5 red, 10 green; 5 red, 19 green; 11 green, 4 red; 11 red, 1 blue, 2 green -Game 34: 1 blue, 11 red; 5 red, 4 green; 4 green, 1 blue, 12 red; 2 blue, 1 green, 7 red; 3 green, 1 blue, 12 red -Game 35: 5 red, 1 blue; 1 blue, 1 red; 2 blue, 2 green, 15 red; 7 red, 2 green; 3 blue, 1 green, 1 red; 16 red, 3 blue, 1 green -Game 36: 10 green, 16 red; 2 blue, 14 green, 6 red; 1 blue, 8 green, 12 red -Game 37: 17 green, 14 blue; 10 green, 12 blue; 10 blue, 1 red, 8 green -Game 38: 9 blue, 2 green; 5 blue, 1 green, 5 red; 6 blue, 2 green, 7 red; 17 red, 1 green, 7 blue; 1 green, 9 blue, 16 red -Game 39: 2 red, 13 blue, 10 green; 5 blue, 15 green, 1 red; 13 blue, 5 green; 3 red, 6 blue, 2 green; 17 green, 1 blue, 4 red; 4 red, 1 blue, 11 green -Game 40: 4 green, 12 blue; 5 red, 13 blue, 1 green; 4 green, 7 red; 7 blue, 2 green -Game 41: 3 red, 1 green; 10 green, 4 blue, 5 red; 8 blue, 5 red -Game 42: 8 blue, 12 red, 5 green; 8 red, 5 green, 4 blue; 3 green, 13 red; 8 blue, 16 red; 12 red, 3 green, 1 blue; 2 blue, 2 green, 6 red -Game 43: 5 blue, 4 red; 10 red, 6 blue; 12 red, 2 blue, 1 green; 7 blue, 12 red, 1 green -Game 44: 11 blue, 5 red; 2 red, 13 green, 5 blue; 7 red, 7 blue, 11 green -Game 45: 7 red, 6 blue; 5 blue, 6 green; 5 green, 5 blue, 7 red; 4 red, 9 green, 12 blue; 9 blue, 12 green, 1 red -Game 46: 2 green, 7 blue, 20 red; 18 green, 2 blue; 8 blue, 1 red, 3 green; 6 green, 1 blue; 2 red, 6 blue, 4 green -Game 47: 6 red, 6 blue; 14 blue, 7 green, 2 red; 8 blue, 3 red -Game 48: 1 red, 5 blue; 3 blue, 15 green, 2 red; 6 blue, 1 red, 13 green; 6 green, 4 blue, 3 red; 11 green, 3 blue -Game 49: 1 green, 15 blue, 3 red; 15 green, 6 blue; 12 green, 2 red, 8 blue; 3 green, 16 blue -Game 50: 8 blue, 7 red, 1 green; 6 blue, 1 green, 2 red; 3 red, 7 blue; 4 blue, 6 red, 1 green -Game 51: 2 red, 5 blue; 2 red, 10 green; 11 green, 1 blue; 9 green, 1 blue, 2 red; 5 blue, 11 green; 1 red, 8 green, 1 blue -Game 52: 1 green, 1 red, 15 blue; 17 blue, 1 red; 5 red, 1 green; 19 blue, 6 red, 3 green; 5 blue, 1 green -Game 53: 1 blue, 12 red, 6 green; 3 red, 7 green, 3 blue; 2 blue, 7 red, 5 green; 4 red, 3 blue, 19 green; 10 red, 12 green, 2 blue; 5 blue, 7 red, 14 green -Game 54: 12 green, 1 red, 4 blue; 3 blue, 5 red, 8 green; 9 green, 6 blue; 3 green, 2 red, 11 blue; 3 green, 10 blue, 7 red; 2 red, 3 green, 4 blue -Game 55: 5 red, 3 blue; 4 blue, 6 green; 10 blue, 1 green; 7 green, 4 red, 14 blue; 2 red, 9 blue, 10 green; 5 red, 10 blue, 10 green -Game 56: 3 green, 11 blue; 4 blue, 10 green, 8 red; 2 blue, 5 green, 2 red; 1 blue, 1 green, 8 red; 5 green, 7 red, 3 blue -Game 57: 2 green, 2 blue, 3 red; 8 red, 5 green, 2 blue; 16 red, 12 blue, 7 green; 13 blue, 6 red, 2 green; 12 red, 1 green -Game 58: 2 green, 3 blue, 8 red; 3 green, 4 blue, 7 red; 2 blue, 11 red, 4 green; 4 green, 1 blue, 2 red; 3 green, 3 red, 2 blue -Game 59: 10 red, 6 blue, 2 green; 2 green, 6 blue, 14 red; 3 green, 11 red, 7 blue; 1 blue, 1 green -Game 60: 5 blue, 10 red; 4 blue, 12 red; 2 green, 3 red, 4 blue -Game 61: 4 blue, 1 green; 10 blue, 2 red; 6 blue, 1 red; 1 green, 7 red; 5 blue, 5 red -Game 62: 6 blue, 7 red, 1 green; 7 blue, 7 green, 15 red; 14 green, 16 red, 2 blue; 2 blue, 17 red; 4 red, 11 green, 6 blue; 13 green, 16 red, 5 blue -Game 63: 4 red, 13 green, 1 blue; 2 green, 5 blue, 10 red; 3 green, 8 red; 1 blue, 3 red, 11 green; 1 red, 7 blue -Game 64: 12 green, 1 blue; 8 red, 1 blue, 10 green; 11 green, 1 blue, 3 red; 10 green, 2 red, 1 blue; 1 blue, 9 green, 8 red -Game 65: 5 green, 2 red; 7 blue, 5 red, 10 green; 9 green, 8 blue; 3 blue, 4 red, 8 green; 11 green, 6 red, 16 blue -Game 66: 8 green, 1 red, 4 blue; 10 green, 5 blue, 7 red; 5 blue, 3 red, 6 green; 4 blue, 12 green, 6 red; 16 green, 3 red; 16 green, 7 red, 4 blue -Game 67: 6 green; 7 red, 1 green, 5 blue; 10 red, 13 green, 3 blue; 8 green, 11 red, 6 blue; 14 red, 5 green, 7 blue -Game 68: 1 red, 8 green, 3 blue; 1 green, 1 red, 1 blue; 1 green, 11 blue, 1 red -Game 69: 2 red, 4 green, 1 blue; 4 blue, 10 green; 4 green, 1 blue, 2 red; 12 green, 5 blue; 6 blue, 3 green -Game 70: 1 blue, 3 green, 2 red; 1 green, 2 blue; 5 green, 1 red; 2 blue, 4 green; 1 red, 5 green -Game 71: 6 blue, 3 red, 12 green; 2 red, 8 green, 3 blue; 8 green, 8 blue; 7 blue, 1 red, 9 green; 2 green, 4 blue, 1 red; 3 red, 7 blue, 8 green -Game 72: 8 red, 7 blue, 6 green; 2 red, 8 blue, 7 green; 2 red, 5 blue, 1 green; 4 green, 6 blue, 1 red; 11 green, 13 red, 3 blue; 8 green, 11 red, 2 blue -Game 73: 7 blue, 17 red, 4 green; 1 red, 4 green, 2 blue; 3 red, 4 blue, 4 green; 5 blue, 5 red; 6 red, 2 blue; 11 red, 1 green, 4 blue -Game 74: 3 red, 2 green; 4 red, 12 blue, 4 green; 7 red, 6 blue, 10 green -Game 75: 6 blue, 7 green; 8 green, 9 blue, 1 red; 6 red, 4 blue, 9 green; 10 red, 9 blue, 4 green; 6 red, 2 blue, 1 green; 7 green -Game 76: 10 red, 8 green; 2 red, 2 blue, 5 green; 1 red, 1 blue, 1 green; 9 red, 11 green, 2 blue; 2 blue, 9 green, 3 red; 6 green, 14 red -Game 77: 9 blue, 1 red, 3 green; 8 blue, 17 green, 4 red; 5 green, 1 blue, 2 red; 6 green, 1 red, 9 blue; 4 green, 10 red; 9 red, 3 blue -Game 78: 5 green, 10 blue; 2 green, 5 blue, 11 red; 1 red, 1 green, 6 blue; 1 red, 8 blue, 4 green -Game 79: 3 green, 1 blue, 2 red; 8 green, 1 blue, 2 red; 2 blue, 1 red, 11 green -Game 80: 12 blue, 3 green; 6 red, 4 green, 13 blue; 4 blue, 8 red; 3 green, 4 blue -Game 81: 1 green, 5 blue; 1 green, 3 blue, 1 red; 1 blue, 1 red, 3 green; 6 blue, 5 green -Game 82: 2 green, 1 blue; 10 blue, 1 red, 6 green; 4 green, 20 blue, 1 red; 20 blue, 2 green, 1 red -Game 83: 2 green, 9 blue, 10 red; 12 red, 11 blue, 4 green; 11 blue, 8 red, 3 green; 17 green, 4 blue; 12 green, 4 red, 6 blue; 1 red, 11 green, 8 blue -Game 84: 7 green, 15 red, 15 blue; 4 blue, 3 green, 18 red; 2 blue, 1 red, 2 green; 8 blue, 19 red, 5 green; 11 blue, 3 red; 9 red, 2 blue -Game 85: 14 green, 3 red, 16 blue; 3 blue, 6 green; 12 green, 6 blue, 2 red -Game 86: 5 red, 6 green; 9 red, 4 green; 7 green, 1 blue, 2 red -Game 87: 10 blue, 7 red, 1 green; 12 blue, 14 red; 7 blue, 7 red -Game 88: 5 red, 10 green, 5 blue; 10 green, 2 red, 8 blue; 2 red, 14 green, 4 blue -Game 89: 1 blue, 6 red, 12 green; 9 red, 13 green, 3 blue; 11 green, 6 red, 3 blue -Game 90: 1 green, 8 blue, 10 red; 10 blue, 7 green; 6 blue, 15 red, 1 green; 1 blue, 16 red, 4 green -Game 91: 8 red, 9 green, 2 blue; 2 red, 15 blue, 2 green; 15 blue, 1 red, 5 green; 1 green, 6 red, 10 blue -Game 92: 10 blue, 4 red; 9 blue, 3 red, 7 green; 8 blue, 16 green, 3 red; 16 green, 16 blue -Game 93: 1 blue, 2 green, 1 red; 4 red, 7 green, 12 blue; 6 green, 3 blue, 4 red; 8 blue, 4 red, 12 green; 5 red, 8 green; 1 red, 18 blue, 10 green -Game 94: 1 blue, 5 red, 6 green; 7 red, 6 green, 1 blue; 8 red, 11 green; 12 green, 7 red, 1 blue; 7 red, 8 green -Game 95: 10 red, 7 green; 2 green, 1 blue, 10 red; 6 green, 5 red, 1 blue -Game 96: 3 blue, 12 red, 3 green; 13 red, 9 blue; 2 green, 5 red, 13 blue; 2 red, 18 blue, 4 green; 6 red, 6 blue, 7 green; 3 green, 15 red, 18 blue -Game 97: 4 red, 3 green; 2 blue, 4 red, 5 green; 3 red, 3 green -Game 98: 2 red, 19 blue; 2 blue; 11 blue, 2 red; 3 green, 5 blue, 1 red; 2 red, 1 blue; 17 blue -Game 99: 2 red, 16 blue, 1 green; 2 green, 12 blue, 6 red; 1 red, 3 green, 3 blue; 8 red, 1 green; 2 red, 9 blue; 1 green, 7 red, 9 blue -Game 100: 8 green, 3 red; 7 green, 4 red; 1 red, 7 green, 2 blue; 1 green, 2 red diff --git a/02/puzzle.py b/02/puzzle.py deleted file mode 100644 index b6651b6..0000000 --- a/02/puzzle.py +++ /dev/null @@ -1,22 +0,0 @@ -from game import Game - - -def solve_pt_1(input: list[str]): - total = 0 - for game_desc in input: - game = Game.parse(game_desc) - if game.meets_configuration({"red": 12, "green": 13, "blue": 14}): - total += game.id - return total - - -def solve_pt_2(input: list[str]): - total = 0 - for game_desc in input: - game = Game.parse(game_desc) - total += _configuration_power(game.minimum_configuration()) - return total - - -def _configuration_power(bag: dict[str, int]) -> int: - return bag.get("blue", 0) * bag.get("green", 0) * bag.get("red", 0) diff --git a/02/puzzle_test.py b/02/puzzle_test.py deleted file mode 100644 index 32eb5cf..0000000 --- a/02/puzzle_test.py +++ /dev/null @@ -1,25 +0,0 @@ -from game import Game -from puzzle import _configuration_power, solve_pt_1, solve_pt_2 - -mock_input = [ - "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", -] - - -def test_solve_pt_1(): - assert solve_pt_1(mock_input) == 8 - - -def test_solve_pt_2(): - assert solve_pt_2(mock_input) == 2286 - - -def test_configuration_power(): - assert [ - _configuration_power(Game.parse(game_desc).minimum_configuration()) - for game_desc in mock_input - ] == [48, 12, 1560, 630, 36] diff --git a/pyproject.toml b/pyproject.toml index 881ca8b..1778c56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ version = "0.1.0" dependencies = ["requests"] [project.optional-dependencies] -test = ["pytest", "types-requests"] +test = ["pytest", "pytest-cov", "types-requests"] [project.scripts] advent-of-code-2023 = "advent_of_code.__main__:main"