diff options
| -rw-r--r-- | aoc/__main__.py | 58 | ||||
| -rw-r--r-- | aoc/template/__init__.py | 16 | ||||
| -rw-r--r-- | aoc/template/example.txt | 0 | ||||
| -rw-r--r-- | aoc/template/input.txt | 0 | ||||
| -rw-r--r-- | day9/__init__.py | 108 | ||||
| -rw-r--r-- | day9/example.txt | 8 | ||||
| -rw-r--r-- | day9/input.txt | 2000 |
7 files changed, 2173 insertions, 17 deletions
diff --git a/aoc/__main__.py b/aoc/__main__.py index 337bdfe..e1b2a85 100644 --- a/aoc/__main__.py +++ b/aoc/__main__.py | |||
| @@ -2,8 +2,10 @@ | |||
| 2 | import argparse | 2 | import argparse |
| 3 | import importlib | 3 | import importlib |
| 4 | import os | 4 | import os |
| 5 | from pathlib import Path | ||
| 6 | from shutil import copytree | ||
| 5 | from time import perf_counter | 7 | from time import perf_counter |
| 6 | from typing import List | 8 | from typing import List, Callable |
| 7 | 9 | ||
| 8 | 10 | ||
| 9 | def day(assignment_part: str) -> str: | 11 | def day(assignment_part: str) -> str: |
| @@ -17,8 +19,41 @@ def kwargs(kwarg: str) -> List: | |||
| 17 | return kwarg.split("=") | 19 | return kwarg.split("=") |
| 18 | 20 | ||
| 19 | 21 | ||
| 22 | def run(args: argparse.Namespace): | ||
| 23 | assignment_day = importlib.import_module(args.day) | ||
| 24 | |||
| 25 | Assignment = getattr(assignment_day, f"Assignment{args.part}") | ||
| 26 | assignment = Assignment( | ||
| 27 | path=os.path.dirname(assignment_day.__file__), **dict(args.kwargs) | ||
| 28 | ) | ||
| 29 | |||
| 30 | start = perf_counter() | ||
| 31 | print( | ||
| 32 | assignment.run( | ||
| 33 | input=assignment.read_input(example=args.example), | ||
| 34 | ) | ||
| 35 | ) | ||
| 36 | end = perf_counter() | ||
| 37 | delta = end - start | ||
| 38 | print() | ||
| 39 | print(f'{(delta if delta > 1 else delta * 1000):.3f}{"s" if delta > 1 else "ms"}') | ||
| 40 | |||
| 41 | |||
| 42 | def new(args: argparse.Namespace): | ||
| 43 | self = importlib.import_module(".", package="aoc") | ||
| 44 | path = Path(self.__file__) | ||
| 45 | template = path.parent.joinpath("template") | ||
| 46 | target = path.parent.parent.joinpath(args.day) | ||
| 47 | |||
| 48 | try: | ||
| 49 | copytree(template, target) | ||
| 50 | except FileExistsError: | ||
| 51 | print(f"{args.day} already exists") | ||
| 52 | |||
| 53 | |||
| 20 | parser = argparse.ArgumentParser(description="Advent of Code") | 54 | parser = argparse.ArgumentParser(description="Advent of Code") |
| 21 | 55 | ||
| 56 | parser.add_argument("command", type=str, choices=["run", "new"]) | ||
| 22 | parser.add_argument("day", type=str, help="Assignment day") | 57 | parser.add_argument("day", type=str, help="Assignment day") |
| 23 | parser.add_argument( | 58 | parser.add_argument( |
| 24 | "-p", | 59 | "-p", |
| @@ -34,20 +69,9 @@ parser.add_argument("kwargs", type=kwargs, nargs="*") | |||
| 34 | 69 | ||
| 35 | if __name__ == "__main__": | 70 | if __name__ == "__main__": |
| 36 | args = parser.parse_args() | 71 | args = parser.parse_args() |
| 37 | assignment_day = importlib.import_module(args.day) | ||
| 38 | |||
| 39 | Assignment = getattr(assignment_day, f"Assignment{args.part}") | ||
| 40 | assignment = Assignment( | ||
| 41 | path=os.path.dirname(assignment_day.__file__), **dict(args.kwargs) | ||
| 42 | ) | ||
| 43 | 72 | ||
| 44 | start = perf_counter() | 73 | match args.command: |
| 45 | print( | 74 | case "run": |
| 46 | assignment.run( | 75 | run(args) |
| 47 | input=assignment.read_input(example=args.example), | 76 | case "new": |
| 48 | ) | 77 | new(args) |
| 49 | ) | ||
| 50 | end = perf_counter() | ||
| 51 | delta = end - start | ||
| 52 | print() | ||
| 53 | print(f'{(delta if delta > 1 else delta * 1000):.3f}{"s" if delta > 1 else "ms"}') | ||
diff --git a/aoc/template/__init__.py b/aoc/template/__init__.py new file mode 100644 index 0000000..05b2b45 --- /dev/null +++ b/aoc/template/__init__.py | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 2 | from abc import ABC | ||
| 3 | |||
| 4 | from aoc import BaseAssignment | ||
| 5 | |||
| 6 | |||
| 7 | class Assignment(BaseAssignment, ABC): | ||
| 8 | pass | ||
| 9 | |||
| 10 | |||
| 11 | class AssignmentOne(Assignment): | ||
| 12 | pass | ||
| 13 | |||
| 14 | |||
| 15 | class AssignmentTwo(Assignment): | ||
| 16 | pass | ||
diff --git a/aoc/template/example.txt b/aoc/template/example.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc/template/example.txt | |||
diff --git a/aoc/template/input.txt b/aoc/template/input.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc/template/input.txt | |||
diff --git a/day9/__init__.py b/day9/__init__.py new file mode 100644 index 0000000..afa44aa --- /dev/null +++ b/day9/__init__.py | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 2 | from abc import ABC | ||
| 3 | from copy import copy | ||
| 4 | from dataclasses import dataclass | ||
| 5 | from typing import Tuple, Iterator, List | ||
| 6 | |||
| 7 | from aoc import BaseAssignment | ||
| 8 | |||
| 9 | |||
| 10 | @dataclass | ||
| 11 | class Coordinate: | ||
| 12 | x: int | ||
| 13 | y: int | ||
| 14 | |||
| 15 | def __hash__(self): | ||
| 16 | return tuple([self.x, self.y]).__hash__() | ||
| 17 | |||
| 18 | def __sub__(self, other: "Coordinate"): | ||
| 19 | return Coordinate(self.x - other.x, self.y - other.y) | ||
| 20 | |||
| 21 | @property | ||
| 22 | def polarity_x(self): | ||
| 23 | try: | ||
| 24 | return abs(self.x) / self.x | ||
| 25 | except ZeroDivisionError: | ||
| 26 | return 0 | ||
| 27 | |||
| 28 | @property | ||
| 29 | def polarity_y(self): | ||
| 30 | try: | ||
| 31 | return abs(self.y) / self.y | ||
| 32 | except ZeroDivisionError: | ||
| 33 | return 0 | ||
| 34 | |||
| 35 | |||
| 36 | class Assignment(BaseAssignment, ABC): | ||
| 37 | def parse_line(self, item: str) -> Tuple[str, int]: | ||
| 38 | direction, amount = item.split(" ") | ||
| 39 | return direction, int(amount) | ||
| 40 | |||
| 41 | def move(self, direction: str, amount: int): | ||
| 42 | pass | ||
| 43 | |||
| 44 | @staticmethod | ||
| 45 | def next_head(head: Coordinate, direction: str): | ||
| 46 | match direction: | ||
| 47 | case "R": | ||
| 48 | head.x += 1 | ||
| 49 | case "L": | ||
| 50 | head.x -= 1 | ||
| 51 | case "U": | ||
| 52 | head.y += 1 | ||
| 53 | case "D": | ||
| 54 | head.y -= 1 | ||
| 55 | |||
| 56 | @staticmethod | ||
| 57 | def next_tail(head: Coordinate, tail: Coordinate): | ||
| 58 | delta = head - tail | ||
| 59 | |||
| 60 | if abs(delta.x) > 1 and delta.y == 0: | ||
| 61 | tail.x += delta.x - delta.polarity_x | ||
| 62 | if abs(delta.x) > 1 and abs(delta.y) == 1: | ||
| 63 | tail.x += delta.x - delta.polarity_x | ||
| 64 | tail.y += delta.y | ||
| 65 | if abs(delta.y > 1) and delta.x == 0: | ||
| 66 | tail.y += delta.y - delta.polarity_y | ||
| 67 | if abs(delta.y) > 1 and abs(delta.x) == 1: | ||
| 68 | tail.y += delta.y - delta.polarity_y | ||
| 69 | tail.x += delta.x | ||
| 70 | |||
| 71 | def tail_positions(self, input: Iterator[str]) -> Iterator[Coordinate]: | ||
| 72 | head = Coordinate(0, 0) | ||
| 73 | tail = Coordinate(0, 0) | ||
| 74 | |||
| 75 | for line in input: | ||
| 76 | direction, amount = self.parse_line(line) | ||
| 77 | |||
| 78 | for _ in range(amount): | ||
| 79 | self.next_head(head, direction) | ||
| 80 | self.next_tail(head, tail) | ||
| 81 | yield tail | ||
| 82 | |||
| 83 | |||
| 84 | class AssignmentOne(Assignment): | ||
| 85 | example_result = 13 | ||
| 86 | |||
| 87 | def run(self, input: Iterator) -> int: | ||
| 88 | unique_tail_positions = set() | ||
| 89 | |||
| 90 | for position in self.tail_positions(input): | ||
| 91 | unique_tail_positions.add(copy(position)) | ||
| 92 | |||
| 93 | print(unique_tail_positions) | ||
| 94 | |||
| 95 | for y in range(5): | ||
| 96 | items = [] | ||
| 97 | for x in range(6): | ||
| 98 | if Coordinate(x, y) in unique_tail_positions: | ||
| 99 | items.append("#") | ||
| 100 | else: | ||
| 101 | items.append(".") | ||
| 102 | print("".join(items)) | ||
| 103 | |||
| 104 | return len(unique_tail_positions) | ||
| 105 | |||
| 106 | |||
| 107 | class AssignmentTwo(Assignment): | ||
| 108 | pass | ||
diff --git a/day9/example.txt b/day9/example.txt new file mode 100644 index 0000000..9874df2 --- /dev/null +++ b/day9/example.txt | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | R 4 | ||
| 2 | U 4 | ||
| 3 | L 3 | ||
| 4 | D 1 | ||
| 5 | R 4 | ||
| 6 | D 1 | ||
| 7 | L 5 | ||
| 8 | R 2 | ||
diff --git a/day9/input.txt b/day9/input.txt new file mode 100644 index 0000000..3da93c3 --- /dev/null +++ b/day9/input.txt | |||
| @@ -0,0 +1,2000 @@ | |||
| 1 | L 2 | ||
| 2 | U 2 | ||
| 3 | L 1 | ||
| 4 | D 1 | ||
| 5 | U 1 | ||
| 6 | L 2 | ||
| 7 | R 2 | ||
| 8 | D 1 | ||
| 9 | U 2 | ||
| 10 | D 1 | ||
| 11 | R 2 | ||
| 12 | U 1 | ||
| 13 | L 2 | ||
| 14 | D 2 | ||
| 15 | L 2 | ||
| 16 | R 2 | ||
