Merge remote-tracking branch 'origin/master'

This commit is contained in:
Stefan Harmuth 2022-11-29 19:35:32 +01:00
commit 44142eb2e1
4 changed files with 13 additions and 76 deletions

View File

@ -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

View File

@ -1,4 +1,4 @@
from collections import defaultdict from collections import Counter
from itertools import combinations from itertools import combinations
from tools.aoc import AOCDay from tools.aoc import AOCDay
from tools.coordinate import Coordinate, DistanceAlgorithm from tools.coordinate import Coordinate, DistanceAlgorithm
@ -17,7 +17,7 @@ ROTATION_PATH = [
def overlap(beacon1: Grid, beacon2: Grid) -> Union[Coordinate, None]: def overlap(beacon1: Grid, beacon2: Grid) -> Union[Coordinate, None]:
diffs = defaultdict(int) diffs = Counter()
for c1 in beacon1.getActiveCells(): for c1 in beacon1.getActiveCells():
for c2 in beacon2.getActiveCells(): for c2 in beacon2.getActiveCells():
# Interestingly adding an if statement here to break out early when already 12 matches are found # Interestingly adding an if statement here to break out early when already 12 matches are found
@ -25,9 +25,9 @@ def overlap(beacon1: Grid, beacon2: Grid) -> Union[Coordinate, None]:
# and checking the results afterwards. # and checking the results afterwards.
diffs[c1 - c2] += 1 diffs[c1 - c2] += 1
for d in diffs: d = diffs.most_common(1)[0]
if diffs[d] >= 12: if d[1] >= 12:
return d return d[0]
def converge(scanner_grids: List[Grid]) -> (Grid, List[Coordinate]): def converge(scanner_grids: List[Grid]) -> (Grid, List[Coordinate]):

View File

@ -1,66 +1,8 @@
from collections import defaultdict from collections import defaultdict
from tools.aoc import AOCDay from tools.aoc import AOCDay
from tools.coordinate import Coordinate from tools.coordinate import Coordinate, Cube
from typing import Any, Generator, List, Union from typing import Any
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__()
class Day(AOCDay): class Day(AOCDay):
@ -88,22 +30,23 @@ class Day(AOCDay):
minZ, maxZ = map(int, zco.split("..")) minZ, maxZ = map(int, zco.split(".."))
new_cube = Cube(Coordinate(minX, minY, minZ), Coordinate(maxX, maxY, maxZ)) 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 yield state == "on", new_cube
def getOnSum(self, part1: bool = False) -> int: def getOnSum(self, part1: bool = False) -> int:
cubes = defaultdict(int) cubes = defaultdict(int)
for switch_state, this_cube in self.getCubeList(part1=part1): for switch_state, this_cube in self.getCubeList(part1=part1):
for prior_cube in cubes.copy(): for prior_cube in cubes.copy():
intersect_cube = this_cube.intersect(prior_cube) intersect_cube = this_cube.intersection(prior_cube)
if intersect_cube: if intersect_cube:
cubes[intersect_cube] -= cubes[prior_cube] cubes[intersect_cube] -= cubes[prior_cube]
if switch_state: if switch_state:
cubes[this_cube] = 1 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: def part1(self) -> Any:
return self.getOnSum(part1=True) return self.getOnSum(part1=True)

View File

@ -8,7 +8,7 @@ def getTheNumberFast(pushpull, adders, subbers, part2=False):
inc = 1 inc = 1
else: else:
number_init = [9] * 14 number_init = [9] * 14
inc = - 1 inc = -1
z = int(1e9) z = int(1e9)
number = number_init.copy() number = number_init.copy()