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