Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
44142eb2e1
@ -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
|
|
||||||
10
day19.py
10
day19.py
@ -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]):
|
||||||
|
|||||||
71
day22.py
71
day22.py
@ -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)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user