diff --git a/README.md b/README.md index 1ff68fa..f5a959b 100644 --- a/README.md +++ b/README.md @@ -28,20 +28,18 @@ poetry run pytest poetry run aoccas solve -y 2023 -d 1 --submit ``` +To run it using the aocd plugin you can run: + +```sh +poetry run aoc -y 2023 -d 1 +``` + + ## Initialize new challenge file ```shell poetry run aoccas init-challenge -y 2023 -d 1 ``` -To submit the results you can add the `-s` flag - Set the environment variable `AOC_SESSION` to use your personal input. -Instructions: [How to find the session id](https://github.com/wimglenn/advent-of-code-wim/issues/1) - - -To run it using the aocd plugin you can run: - -```sh -poetry run aoc -y 2023 -d 1 -``` +Instructions on [how to find your session id](https://github.com/wimglenn/advent-of-code-wim/issues/1) diff --git a/aoc_cas/aoc2023/day1.py b/aoc_cas/aoc2023/day1.py index 2cd7309..44c01b0 100644 --- a/aoc_cas/aoc2023/day1.py +++ b/aoc_cas/aoc2023/day1.py @@ -1,6 +1,3 @@ -from aoc_cas.util import test_with_examples - - def part_a(data) -> int: result = 0 for line in data.splitlines(): @@ -39,4 +36,6 @@ def part_b(data) -> int: if __name__ == "__main__": - test_with_examples(2023, 1) + from aoc_cas.util import solve_with_examples + + solve_with_examples(2023, 1) diff --git a/aoc_cas/aoc2023/day2.py b/aoc_cas/aoc2023/day2.py new file mode 100644 index 0000000..0f8b7c0 --- /dev/null +++ b/aoc_cas/aoc2023/day2.py @@ -0,0 +1,45 @@ +import dataclasses +from collections import defaultdict +from typing import Self + + +@dataclasses.dataclass(frozen=True) +class Round: + id: int + red: int = 0 + blue: int = 0 + green: int = 0 + + @classmethod + def from_data_line(cls, line: str) -> Self: + game_part, cube_part = line.split(": ") + game_id = int(game_part.split(" ")[1]) + + most_seen: dict[str, int] = defaultdict(int) + for cube_set in cube_part.split("; "): + for draw in cube_set.split(", "): + count, color = draw.split(" ") + most_seen[color] = max(most_seen[color], int(count)) + + return Round(game_id, **most_seen) + + +def part_a(data: str) -> int: + result = 0 + for round in map(Round.from_data_line, data.splitlines()): + if round.red <= 12 and round.green <= 13 and round.blue <= 14: + result += round.id + return result + + +def part_b(data: str) -> int: + result = 0 + for round in map(Round.from_data_line, data.splitlines()): + result += round.blue * round.green * round.red + return result + + +if __name__ == "__main__": + from aoc_cas.util import solve_with_examples + + solve_with_examples(year=2023, day=2) diff --git a/aoc_cas/cli.py b/aoc_cas/cli.py index 2e55313..347e005 100644 --- a/aoc_cas/cli.py +++ b/aoc_cas/cli.py @@ -1,4 +1,3 @@ -import logging from datetime import datetime from pathlib import Path @@ -8,12 +7,10 @@ from . import plugin -log = logging.getLogger() - @click.group() def main(): - logging.basicConfig(format="%(message)s", level=logging.INFO) + ... @main.command() @@ -22,13 +19,13 @@ def main(): @click.option("--submit", "-s", is_flag=True) def solve(year: int, day: int, submit: bool) -> None: puzzle = Puzzle(year, day) - log.info(f"--- {year} Day {day}: {puzzle.title} ---") - part_1_result, part_2_result = plugin(year, day) - log.info(f"PartA: {part_1_result}") - log.info(f"PartB: {part_2_result}") + print(f"--- {year} Day {day}: {puzzle.title} ---") + part_a_result, part_b_result = plugin(year=year, day=day, data=puzzle.input_data) + print(f"PartA: {part_a_result}") + print(f"PartB: {part_b_result}") if submit: - puzzle.answer_a = part_1_result - puzzle.answer_2 = part_2_result + puzzle.answer_a = part_a_result + puzzle.answer_b = part_b_result @main.command() @@ -40,9 +37,11 @@ def init_challenge(year: int, day: int) -> None: if not year_folder.exists(): year_folder.mkdir() year_folder.joinpath("__init__.py").touch() + print(f"Generated a new year folder: {year_folder}") python_file = year_folder / f"day{day}.py" if not python_file.exists(): - python_file.write_text(challenge_template.format(day, year)) + python_file.write_text(challenge_template.format(day=day, year=year)) + print(f"Generated a new solution file at: {python_file}") test_folder = Path.cwd() / f"tests/fixtures/{year}" test_folder.mkdir(exist_ok=True) diff --git a/aoc_cas/util.py b/aoc_cas/util.py index 46afcfa..f98b898 100644 --- a/aoc_cas/util.py +++ b/aoc_cas/util.py @@ -8,7 +8,7 @@ def load_module(year: int, day: int): return importlib.import_module(module_name) -def test_with_examples(year: int, day: int) -> None: +def solve_with_examples(year: int, day: int) -> None: mod = load_module(year, day) puzzle = Puzzle(year, day) print(f"Testing example data") @@ -19,6 +19,6 @@ def test_with_examples(year: int, day: int) -> None: correct = part_a_result == example.answer_a print(f"{'❌✅'[correct]} [Part A] Actual: {part_a_result} - Expected: {example.answer_a}") if example.answer_b is not None: - part_b_result = mod.part_b(example.input_data) - correct = part_b_result == example.answer_a + part_b_result = str(mod.part_b(example.input_data)) + correct = part_b_result == example.answer_b print(f"{'❌✅'[correct]} [Part B] Actual: {part_b_result} - Expected: {example.answer_b}\n") diff --git a/challenge_template.txt b/challenge_template.txt index 06336b2..97d8189 100644 --- a/challenge_template.txt +++ b/challenge_template.txt @@ -1,12 +1,11 @@ -from aoc_cas.util import test_with_examples - - -def part_a(data) -> int: +def part_a(data: str) -> int: pass -def part_b(data) -> int: +def part_b(data: str) -> int: pass if __name__ == "__main__": - test_with_examples({}, {}) + from aoc_cas.util import solve_with_examples + + solve_with_examples(year={year}, day={day}) diff --git a/tests/fixtures/2023/2.txt b/tests/fixtures/2023/2.txt new file mode 100644 index 0000000..feae538 --- /dev/null +++ b/tests/fixtures/2023/2.txt @@ -0,0 +1,7 @@ +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 +8 +2286 \ No newline at end of file