diff options
| -rw-r--r-- | .pre-commit-config.yaml | 15 | ||||
| -rw-r--r-- | aoc/__init__.py | 14 | ||||
| -rw-r--r-- | aoc/__main__.py | 32 | ||||
| -rw-r--r-- | aoc/test_init.py | 6 | ||||
| -rw-r--r-- | aoc/utils.py | 3 | ||||
| -rw-r--r-- | conftest.py | 16 | ||||
| -rw-r--r-- | day1/__init__.py | 20 |
7 files changed, 64 insertions, 42 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..1232470 --- /dev/null +++ b/.pre-commit-config.yaml | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | # See https://pre-commit.com for more information | ||
| 2 | # See https://pre-commit.com/hooks.html for more hooks | ||
| 3 | repos: | ||
| 4 | - repo: https://github.com/pre-commit/pre-commit-hooks | ||
| 5 | rev: v4.3.0 | ||
| 6 | hooks: | ||
| 7 | - id: trailing-whitespace | ||
| 8 | - id: end-of-file-fixer | ||
| 9 | - id: check-merge-conflict | ||
| 10 | - id: debug-statements | ||
| 11 | - id: fix-encoding-pragma | ||
| 12 | - repo: https://github.com/psf/black | ||
| 13 | rev: 22.10.0 | ||
| 14 | hooks: | ||
| 15 | - id: black | ||
diff --git a/aoc/__init__.py b/aoc/__init__.py index b13489c..5fce415 100644 --- a/aoc/__init__.py +++ b/aoc/__init__.py | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 1 | import os | 2 | import os |
| 2 | from abc import ABC | 3 | from abc import ABC |
| 3 | from typing import Generator, Any, Iterator | 4 | from typing import Generator, Any, Iterator |
| @@ -5,23 +6,24 @@ from typing import Generator, Any, Iterator | |||
| 5 | 6 | ||
| 6 | class BaseAssignment(ABC): | 7 | class BaseAssignment(ABC): |
| 7 | example_result = NotImplemented | 8 | example_result = NotImplemented |
| 9 | |||
| 8 | def __init__(self, path): | 10 | def __init__(self, path): |
| 9 | self.path = path | 11 | self.path = path |
| 10 | 12 | ||
| 11 | def __str__(self): | 13 | def __str__(self): |
| 12 | return f'{self.__module__}.{self.__class__.__name__}' | 14 | return f"{self.__module__}.{self.__class__.__name__}" |
| 13 | 15 | ||
| 14 | def parse_item(self, item: str) -> Any: | 16 | def parse_item(self, item: str) -> Any: |
| 15 | return item | 17 | return item |
| 16 | 18 | ||
| 17 | def read_input(self, example = False) -> Generator: | 19 | def read_input(self, example=False) -> Generator: |
| 18 | file = f'{self.path}/input.txt' | 20 | file = f"{self.path}/input.txt" |
| 19 | if example or not os.path.isfile(file): | 21 | if example or not os.path.isfile(file): |
| 20 | file = f'{self.path}/example.txt' | 22 | file = f"{self.path}/example.txt" |
| 21 | 23 | ||
| 22 | with open(file, 'r') as input_file: | 24 | with open(file, "r") as input_file: |
| 23 | for line in input_file.readlines(): | 25 | for line in input_file.readlines(): |
| 24 | yield self.parse_item(line.strip()) | 26 | yield self.parse_item(line.strip()) |
| 25 | 27 | ||
| 26 | def run(self, input: Iterator) -> Any: | 28 | def run(self, input: Iterator) -> Any: |
| 27 | raise NotImplementedError('Please implement run') \ No newline at end of file | 29 | raise NotImplementedError("Please implement run") |
diff --git a/aoc/__main__.py b/aoc/__main__.py index 25a7026..337bdfe 100644 --- a/aoc/__main__.py +++ b/aoc/__main__.py | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 1 | import argparse | 2 | import argparse |
| 2 | import importlib | 3 | import importlib |
| 3 | import os | 4 | import os |
| @@ -7,32 +8,37 @@ from typing import List | |||
| 7 | 8 | ||
| 8 | def day(assignment_part: str) -> str: | 9 | def day(assignment_part: str) -> str: |
| 9 | return { | 10 | return { |
| 10 | '1': 'One', | 11 | "1": "One", |
| 11 | '2': 'Two', | 12 | "2": "Two", |
| 12 | }[assignment_part] | 13 | }[assignment_part] |
| 13 | 14 | ||
| 15 | |||
| 14 | def kwargs(kwarg: str) -> List: | 16 | def kwargs(kwarg: str) -> List: |
| 15 | return kwarg.split('=') | 17 | return kwarg.split("=") |
| 18 | |||
| 16 | 19 | ||
| 17 | parser = argparse.ArgumentParser(description='Advent of Code') | 20 | parser = argparse.ArgumentParser(description="Advent of Code") |
| 18 | 21 | ||
| 19 | parser.add_argument('day', type=str, help='Assignment day') | 22 | parser.add_argument("day", type=str, help="Assignment day") |
| 20 | parser.add_argument( | 23 | parser.add_argument( |
| 21 | '-p', '--part', type=day, nargs='?', default='1', | 24 | "-p", |
| 22 | help='Assingment part. Defaults to one.' | 25 | "--part", |
| 26 | type=day, | ||
| 27 | nargs="?", | ||
| 28 | default="1", | ||
| 29 | help="Assingment part. Defaults to one.", | ||
| 23 | ) | 30 | ) |
| 24 | parser.add_argument('--example', default=False, action='store_true') | 31 | parser.add_argument("--example", default=False, action="store_true") |
| 25 | parser.add_argument('kwargs', type=kwargs, nargs='*') | 32 | parser.add_argument("kwargs", type=kwargs, nargs="*") |
| 26 | 33 | ||
| 27 | 34 | ||
| 28 | if __name__ == '__main__': | 35 | if __name__ == "__main__": |
| 29 | args = parser.parse_args() | 36 | args = parser.parse_args() |
| 30 | assignment_day = importlib.import_module(args.day) | 37 | assignment_day = importlib.import_module(args.day) |
| 31 | 38 | ||
| 32 | Assignment = getattr(assignment_day, f'Assignment{args.part}') | 39 | Assignment = getattr(assignment_day, f"Assignment{args.part}") |
| 33 | assignment = Assignment( | 40 | assignment = Assignment( |
| 34 | path=os.path.dirname(assignment_day.__file__), | 41 | path=os.path.dirname(assignment_day.__file__), **dict(args.kwargs) |
| 35 | **dict(args.kwargs) | ||
| 36 | ) | 42 | ) |
| 37 | 43 | ||
| 38 | start = perf_counter() | 44 | start = perf_counter() |
diff --git a/aoc/test_init.py b/aoc/test_init.py index a9155cc..f804c41 100644 --- a/aoc/test_init.py +++ b/aoc/test_init.py | |||
| @@ -1,2 +1,6 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 1 | def test_assignment_examples(assignment): | 2 | def test_assignment_examples(assignment): |
| 2 | assert assignment.run(input=assignment.read_input(example=True)) == assignment.example_result | 3 | assert ( |
| 4 | assignment.run(input=assignment.read_input(example=True)) | ||
| 5 | == assignment.example_result | ||
| 6 | ) | ||
diff --git a/aoc/utils.py b/aoc/utils.py index 6d794f4..a5de050 100644 --- a/aoc/utils.py +++ b/aoc/utils.py | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 1 | from typing import Callable | 2 | from typing import Callable |
| 2 | 3 | ||
| 3 | 4 | ||
| 4 | def bold(item: str, condition: Callable[[], bool]): | 5 | def bold(item: str, condition: Callable[[], bool]): |
| 5 | return f'\033[36m{item}\033[0m' if condition() else item | 6 | return f"\033[36m{item}\033[0m" if condition() else item |
diff --git a/conftest.py b/conftest.py index 24884e2..1c0a8e4 100644 --- a/conftest.py +++ b/conftest.py | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 1 | import importlib | 2 | import importlib |
| 2 | import os | 3 | import os |
| 3 | from pkgutil import walk_packages | 4 | from pkgutil import walk_packages |
| @@ -8,25 +9,28 @@ from aoc.__main__ import day | |||
| 8 | 9 | ||
| 9 | dir_path = os.path.dirname(os.path.realpath(__file__)) | 10 | dir_path = os.path.dirname(os.path.realpath(__file__)) |
| 10 | 11 | ||
| 12 | |||
| 11 | def pytest_generate_tests(metafunc: Metafunc): | 13 | def pytest_generate_tests(metafunc: Metafunc): |
| 12 | if 'assignment' in metafunc.fixturenames: | 14 | if "assignment" in metafunc.fixturenames: |
| 13 | packages = [ | 15 | packages = [ |
| 14 | importlib.import_module(package.name) | 16 | importlib.import_module(package.name) |
| 15 | for package in walk_packages([dir_path]) | 17 | for package in walk_packages([dir_path]) |
| 16 | ] | 18 | ] |
| 17 | 19 | ||
| 18 | assignments = [ | 20 | assignments = [ |
| 19 | (getattr(package, f'Assignment{day(part)}', None), package) | 21 | (getattr(package, f"Assignment{day(part)}", None), package) |
| 20 | for package in packages | 22 | for package in packages |
| 21 | for part in ['1', '2'] | 23 | for part in ["1", "2"] |
| 22 | ] | 24 | ] |
| 23 | 25 | ||
| 24 | metafunc.parametrize( | 26 | metafunc.parametrize( |
| 25 | argnames=f'assignment', | 27 | argnames=f"assignment", |
| 26 | argvalues=[ | 28 | argvalues=[ |
| 27 | Assignment(path=package.__path__[0]) | 29 | Assignment(path=package.__path__[0]) |
| 28 | for (Assignment, package) in assignments | 30 | for (Assignment, package) in assignments |
| 29 | if Assignment is not None and hasattr(package, '__path__') and Assignment.example_result != NotImplemented | 31 | if Assignment is not None |
| 32 | and hasattr(package, "__path__") | ||
| 33 | and Assignment.example_result != NotImplemented | ||
| 30 | ], | 34 | ], |
| 31 | ids=lambda assignment: str(assignment) | 35 | ids=lambda assignment: str(assignment), |
| 32 | ) | 36 | ) |
diff --git a/day1/__init__.py b/day1/__init__.py index d7c995c..e6e4ac9 100644 --- a/day1/__init__.py +++ b/day1/__init__.py | |||
| @@ -1,19 +1,16 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 1 | from abc import ABC | 2 | from abc import ABC |
| 2 | from itertools import groupby | 3 | from itertools import groupby |
| 3 | from typing import Iterator, Any, List | 4 | from typing import Iterator, Any, List |
| 4 | 5 | ||
| 5 | from aoc import BaseAssignment | 6 | from aoc import BaseAssignment |
| 6 | 7 | ||
| 8 | |||
| 7 | class Assignment(BaseAssignment, ABC): | 9 | class Assignment(BaseAssignment, ABC): |
| 8 | def calculate_elf_calories(self, input: Iterator) -> List[int]: | 10 | def calculate_elf_calories(self, input: Iterator) -> List[int]: |
| 9 | return [ | 11 | return [ |
| 10 | sum([ | 12 | sum([int(i) for i in group]) |
| 11 | int(i) | 13 | for in_group, group in groupby(input, key=bool) |
| 12 | for i | ||
| 13 | in group | ||
| 14 | ]) | ||
| 15 | for in_group, group | ||
| 16 | in groupby(input, key=bool) | ||
| 17 | if in_group | 14 | if in_group |
| 18 | ] | 15 | ] |
| 19 | 16 | ||
| @@ -29,11 +26,4 @@ class AssignmentTwo(Assignment): | |||
| 29 | example_result = 45000 | 26 | example_result = 45000 |
| 30 | 27 | ||
| 31 | def run(self, input: Iterator) -> int: | 28 | def run(self, input: Iterator) -> int: |
| 32 | return sum( | 29 | return sum(sorted(self.calculate_elf_calories(input), reverse=True)[:3]) |
