diff --git a/tools/aoc.py b/tools/aoc.py index 2dca347..d8d3ced 100644 --- a/tools/aoc.py +++ b/tools/aoc.py @@ -1,5 +1,7 @@ import os import re +import subprocess + import requests import time import webbrowser @@ -91,9 +93,11 @@ class AOCDay: f.write(response.content) f.flush() + if os.path.exists(".git"): + subprocess.call(["git", "add", filename]) + def _submit(self, part: int, answer: Any): answer_cache = JSONFile("answer_cache.json", create=True) - print(answer_cache) str_day = str(self.day) str_part = str(part) if str_day not in answer_cache: diff --git a/tools/coordinate.py b/tools/coordinate.py index 6057cec..17a457d 100644 --- a/tools/coordinate.py +++ b/tools/coordinate.py @@ -174,7 +174,7 @@ class Coordinate: @staticmethod def generate(from_x: int, to_x: int, from_y: int, to_y: int, from_z: int = None, to_z: int = None) -> List[Coordinate]: - if from_z is None and to_z is None: + if from_z is None or to_z is None: return [Coordinate(x, y) for x in range(from_x, to_x + 1) for y in range(from_y, to_y + 1)] else: return [ @@ -183,3 +183,84 @@ class Coordinate: for y in range(from_y, to_y + 1) for z in range(from_z, to_z + 1) ] + + +class Shape: + top_left: Coordinate + bottom_right: Coordinate + mode_3d: bool + + def __init__(self, top_left: Coordinate, bottom_right: Coordinate): + """ + in 2D mode: top_left is the upper left corner and bottom_right the lower right + (top_left.x <= bottom_right.x and top_left.y <= bottom_right.y) + in 3D mode: same logic applied, just for 3D Coordinates + top_left is the upper left rear corner and bottom_right the lower right front + (top_left.x <= bottom_right.x and top_left.y <= bottom_right.y and top_left.z <= bottom_right.z) + """ + self.top_left = top_left + self.bottom_right = bottom_right + self.mode_3d = top_left.z is not None and bottom_right.z is not None + + def size(self): + if not self.mode_3d: + return (self.bottom_right.x - self.top_left.x + 1) * (self.bottom_right.y - self.top_left.y + 1) + else: + return ( + (self.bottom_right.x - self.top_left.x + 1) + * (self.bottom_right.y - self.top_left.y + 1) + * (self.bottom_right.z - self.top_left.z + 1) + ) + + def intersection(self, other: Shape) -> Union[Shape, None]: + """ + returns a Shape of the intersecting part, or None if the Shapes don't intersect + """ + if self.mode_3d != other.mode_3d: + raise ValueError("Cannot calculate intersection between 2d and 3d shape") + + if not self.mode_3d: + intersect_top_left = Coordinate( + self.top_left.x if self.top_left.x > other.top_left.x else other.top_left.x, + self.top_left.y if self.top_left.y > other.top_left.y else other.top_left.y, + ) + intersect_bottom_right = Coordinate( + self.bottom_right.x if self.bottom_right.x < other.bottom_right.x else other.bottom_right.x, + self.bottom_right.y if self.bottom_right.y < other.bottom_right.y else other.bottom_right.y, + ) + else: + intersect_top_left = Coordinate( + self.top_left.x if self.top_left.x > other.top_left.x else other.top_left.x, + self.top_left.y if self.top_left.y > other.top_left.y else other.top_left.y, + self.top_left.z if self.top_left.z > other.top_left.z else other.top_left.z, + ) + intersect_bottom_right = Coordinate( + self.bottom_right.x if self.bottom_right.x < other.bottom_right.x else other.bottom_right.x, + self.bottom_right.y if self.bottom_right.y < other.bottom_right.y else other.bottom_right.y, + self.bottom_right.z if self.bottom_right.z < other.bottom_right.z else other.bottom_right.z, + ) + + if intersect_top_left <= intersect_bottom_right: + return self.__class__(intersect_top_left, intersect_bottom_right) + + def __and__(self, other): + return self.intersection(other) + + def __rand__(self, other): + return self.intersection(other) + + def __str__(self): + return "%s(%s, %s)" % (self.__class__.__name__, self.top_left, self.bottom_right) + + +class Square(Shape): + def __init__(self, top_left, bottom_right): + super().__init__(top_left, bottom_right) + self.mode_3d = False + + +class Cube(Shape): + def __init__(self, top_left, bottom_right): + if top_left.z is None or bottom_right.z is None: + raise ValueError("Both Coordinates need to be 3D") + super().__init__(top_left, bottom_right)