| @@ -0,0 +1,51 @@ | |||
| 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) | |||