| import functools | |||||
| import itertools | |||||
| import re | |||||
| import sys | |||||
| from math import gcd | |||||
| def calculate_energy(moons, vels): | |||||
| return sum( | |||||
| sum(abs(p) for p in moon) * sum(abs(v) for v in vel) | |||||
| for moon, vel in zip(moons, vels) | |||||
| ) | |||||
| def simulate(text, axes=slice(0, 3), lim=None): | |||||
| g = (int(n) for n in re.findall(r'-?\d+', text)) | |||||
| moons = [point[axes] for point in zip(*[g] * 3)] | |||||
| vels = [[0, 0, 0] for m in moons] | |||||
| seen = set() | |||||
| for step in itertools.count(): | |||||
| if lim is not None and step >= lim: | |||||
| break | |||||
| for (i, A), (j, B) in itertools.combinations(enumerate(moons), 2): | |||||
| dV = [max(a < b, 0) or -max(b < a, 0) for a, b in zip(A, B)] | |||||
| vels[i] = [v + d for v, d in zip(vels[i], dV)] | |||||
| vels[j] = [v - d for v, d in zip(vels[j], dV)] | |||||
| for i, moon in enumerate(moons): | |||||
| moons[i] = [p + v for p, v in zip(moons[i], vels[i])] | |||||
| key = str(moons) + str(vels) | |||||
| if key in seen: | |||||
| break | |||||
| seen.add(key) | |||||
| return step, calculate_energy(moons, vels) | |||||
| text = sys.stdin.read() | |||||
| _, energy = simulate(text, lim=1000) | |||||
| print(energy) | |||||
| nX, _ = simulate(text, axes=slice(0, 1)) | |||||
| nY, _ = simulate(text, axes=slice(1, 2)) | |||||
| nZ, _ = simulate(text, axes=slice(2, 3)) | |||||
| gcds = {gcd(p, q) for p, q in itertools.combinations([nX, nY, nZ], 2)} | |||||
| lcm = functools.reduce(int.__mul__, gcds) | |||||
| print(nX * nY * nZ // lcm) |