···11+import fileinput
22+from copy import deepcopy
33+from itertools import count
44+55+from utils import parse_nums
66+77+88+def gcd(a,b):
99+ """Compute the greatest common divisor of a and b"""
1010+ while b > 0:
1111+ a, b = b, a % b
1212+ return a
1313+1414+def lcm(a, b):
1515+ """Compute the lowest common multiple of a and b"""
1616+ return a * b / gcd(a, b)
1717+1818+1919+positions = []
2020+for i, line in enumerate(fileinput.input()):
2121+ line = line.strip()
2222+ nums = parse_nums(line)
2323+ positions.append(list(nums))
2424+2525+2626+velocities = [[0] * 3 for _ in range(4)]
2727+2828+INIT_POS = deepcopy(positions)
2929+INIT_VEL = deepcopy(velocities)
3030+CYCLES = [None, None, None]
3131+3232+for i in count(start=1):
3333+ # Update velocities
3434+ for x in range(4):
3535+ for y in range(x + 1, 4):
3636+ for d in range(3):
3737+ if positions[x][d] < positions[y][d]:
3838+ velocities[x][d] += 1
3939+ velocities[y][d] -= 1
4040+ elif positions[x][d] > positions[y][d]:
4141+ velocities[x][d] -= 1
4242+ velocities[y][d] += 1
4343+4444+ # Update positions
4545+ for x in range(4):
4646+ for d in range(3):
4747+ positions[x][d] += velocities[x][d]
4848+4949+ energy = 0
5050+5151+ for pos, vel in zip(positions, velocities):
5252+ pot = sum(abs(p) for p in pos)
5353+ kin = sum(abs(p) for p in vel)
5454+ energy += pot * kin
5555+5656+ if i == 1000:
5757+ print "Total energy after 1000 steps:", energy
5858+5959+ for d in range(3):
6060+ if CYCLES[d] is not None:
6161+ continue
6262+6363+ for m in range(4):
6464+ if positions[m][d] != INIT_POS[m][d]:
6565+ break
6666+ if velocities[m][d] != INIT_VEL[m][d]:
6767+ break
6868+ else:
6969+ CYCLES[d] = i
7070+7171+ if all(CYCLES):
7272+ print "Steps for full cycle:", lcm(lcm(CYCLES[0], CYCLES[1]), CYCLES[2])
7373+ break