|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- from itertools import combinations, product
-
-
- def manhattan(p1, p2):
- return tuple(abs(a - b) for a, b in zip(p1, p2))
-
-
- def find_shared_transpose(pts):
- new = {manhattan(a, b): a for a, b in combinations(pts, 2)}
- deltas = [
- [(a - b) for a, b in zip(constellations[k], new[k])]
- for k in set(constellations) & set(new)
- ]
- if deltas:
- return [max(t, key=t.count) for t in zip(*deltas)]
-
-
- def overlap(pts):
- for fx, fy, fz in product([1, -1], [1, -1], [1, -1]):
- flipped = {(x * fx, y * fy, z * fz) for x, y, z in pts}
- if deltas := find_shared_transpose(flipped):
- dx, dy, dz = deltas
- transposed = {(x + dx, y + dy, z + dz) for x, y, z in flipped}
- if len(all_beacons & transposed) >= 12:
- update_state((-dx, -dy, -dz), transposed)
- return True
-
-
- def update_state(scanner, beacons):
- all_scanners.add(scanner)
- all_beacons.update(beacons)
- new = {manhattan(a, b): a for a, b in combinations(all_beacons, 2)}
- constellations.update(new)
-
-
- def transform(step, pts):
- if step % 3 == 0:
- pts = [pt[::-1] for pt in pts]
- return [pt[1:] + pt[:1] for pt in pts]
-
-
- text = open(0).read()
- reference, *readings = [
- [tuple(int(n) for n in ln.split(',')) for ln in scnr.splitlines()[1:]]
- for scnr in text.split('\n\n')
- ]
- all_scanners = set()
- all_beacons = set()
- constellations = {}
- update_state((0, 0, 0), reference)
- for step in range(30):
- readings = [transform(step, pts) for pts in readings if not overlap(pts)]
- print(len(all_beacons))
- print(max(sum(manhattan(a, b)) for a, b in combinations(all_scanners, 2)))
|