diff --git a/!NOTES_FOR_NEXT_YEAR b/!NOTES_FOR_NEXT_YEAR deleted file mode 100644 index adec3ec..0000000 --- a/!NOTES_FOR_NEXT_YEAR +++ /dev/null @@ -1,6 +0,0 @@ -- add run() method to AOCDay, so every day can run on it's own -> enable Alt+Shit+F10 and avoid confusion - -> after wards add a "if __name__ == '__main__': day = Day(); day.run()" to the skeleton -- add download_input() and submit_solution() to AOCDay, this can be automated, so let it ... - -> submit_solution() should not submit None and keep track of past (wrong) attempts to not re-try those -- add some sort of "start_day.py", as the manual copy/create is tedious - -> maybe even download the problem description into that days .py? At least part1; adding part2 afterwards might be tricky diff --git a/day22.py b/day22.py index bb8828d..803d76d 100644 --- a/day22.py +++ b/day22.py @@ -1,66 +1,8 @@ from collections import defaultdict from tools.aoc import AOCDay -from tools.coordinate import Coordinate -from typing import Any, Generator, List, Union - - -class Cube: - coord_ulb: Coordinate # min_coord / up left back - coord_urb: Coordinate - coord_ulf: Coordinate - coord_urf: Coordinate - coord_dlb: Coordinate - coord_drb: Coordinate - coord_dlf: Coordinate - coord_drf: Coordinate # max_coord / down right front - - def __init__(self, min_coord: Coordinate, max_coord: Coordinate): - assert max_coord >= min_coord, "invalid cube spec: %s < %s" % (min_coord, max_coord) - self.coord_ulb = min_coord - self.coord_drf = max_coord - #self.coord_urb = Coordinate(self.coord_ulb.x, self.coord_drf.y, self.coord_ulb.z) - #self.coord_ulf = Coordinate(self.coord_ulb.x, self.coord_ulb.y, self.coord_drf.z) - #self.coord_urf = Coordinate(self.coord_ulb.x, self.coord_drf.y, self.coord_drf.z) - #self.coord_dlb = Coordinate(self.coord_drf.x, self.coord_ulb.y, self.coord_ulb.z) - #self.coord_drb = Coordinate(self.coord_drf.x, self.coord_drf.y, self.coord_ulb.z) - #self.coord_dlf = Coordinate(self.coord_drf.x, self.coord_ulb.y, self.coord_drf.z) - - def getSize(self): - return ( - (self.coord_drf.x - self.coord_ulb.x + 1) - * (self.coord_drf.y - self.coord_ulb.y + 1) - * (self.coord_drf.z - self.coord_ulb.z + 1) - ) - - def intersect(self, other: 'Cube') -> Union['Cube', None]: - intersect_ulr = Coordinate( - #max(self.coord_ulb.x, other.coord_ulb.x), - self.coord_ulb.x if self.coord_ulb.x > other.coord_ulb.x else other.coord_ulb.x, - #max(self.coord_ulb.y, other.coord_ulb.y), - self.coord_ulb.y if self.coord_ulb.y > other.coord_ulb.y else other.coord_ulb.y, - #max(self.coord_ulb.z, other.coord_ulb.z) - self.coord_ulb.z if self.coord_ulb.z > other.coord_ulb.z else other.coord_ulb.z, - ) - intersect_drf = Coordinate( - #min(self.coord_drf.x, other.coord_drf.x), - self.coord_drf.x if self.coord_drf.x < other.coord_drf.x else other.coord_drf.x, - #min(self.coord_drf.y, other.coord_drf.y), - self.coord_drf.y if self.coord_drf.y < other.coord_drf.y else other.coord_drf.y, - #min(self.coord_drf.z, other.coord_drf.z), - self.coord_drf.z if self.coord_drf.z < other.coord_drf.z else other.coord_drf.z, - ) - if intersect_ulr <= intersect_drf: - return Cube(intersect_ulr, intersect_drf) - - def __str__(self): - return "Cube(<%d,%d,%d>;<%d,%d,%d>)" % ( - self.coord_ulb.x, self.coord_ulb.y, self.coord_ulb.z, - self.coord_drf.x, self.coord_drf.y, self.coord_drf.z, - ) - - def __repr__(self): - return self.__str__() +from tools.coordinate import Coordinate, Cube +from typing import Any class Day(AOCDay): @@ -88,22 +30,23 @@ class Day(AOCDay): minZ, maxZ = map(int, zco.split("..")) new_cube = Cube(Coordinate(minX, minY, minZ), Coordinate(maxX, maxY, maxZ)) - if not part1 or (new_cube.coord_ulb >= Coordinate(-50, -50, -50) and new_cube.coord_drf <= Coordinate(50, 50, 50)): + if not part1 \ + or (new_cube.top_left >= Coordinate(-50, -50, -50) + and new_cube.bottom_right <= Coordinate(50, 50, 50)): yield state == "on", new_cube def getOnSum(self, part1: bool = False) -> int: cubes = defaultdict(int) for switch_state, this_cube in self.getCubeList(part1=part1): for prior_cube in cubes.copy(): - intersect_cube = this_cube.intersect(prior_cube) + intersect_cube = this_cube.intersection(prior_cube) if intersect_cube: cubes[intersect_cube] -= cubes[prior_cube] if switch_state: cubes[this_cube] = 1 - #print(cubes) - return sum(cube.getSize() * on_off for cube, on_off in cubes.items()) + return sum(len(cube) * on_off for cube, on_off in cubes.items()) def part1(self) -> Any: return self.getOnSum(part1=True)