diff --git a/2019/ruby/day_12.rb b/2019/ruby/day_12.rb
index d2b48b1..76ef919 100644
--- a/2019/ruby/day_12.rb
+++ b/2019/ruby/day_12.rb
@@ -1,4 +1,5 @@
require "matrix"
+require "prime"
require "set"
V = Vector
@@ -39,6 +40,10 @@ class Moons < SimpleDelegator
def energy
map {|m| m.potential_energy * m.kinetic_energy }.sum
end
+
+ def fingerprint(axis)
+ map {|m| [m.pos[axis], m.vel[axis]] }
+ end
end
require "minitest"
@@ -81,13 +86,39 @@ class TestMoons < Minitest::Test
end
end
+def gcd(*n)
+ n.map {|c| Prime.prime_division(c).to_h }
+ .inject {|h,p| h.merge(p) {|_, a, b| [a, b].max }}
+ .map {|n,e| n**e }
+ .inject(&:*)
+end
+
if ARGF.to_io.tty?
require "minitest/autorun"
else
moons = Moons.from(ARGF.read)
- 1000.times do
+ # 1000.times do
+ # moons = moons.step
+ # end
+ # puts moons.energy
+
+ seen = [{}, {}, {}]
+ cycles = [nil, nil, nil]
+ (0..).each do |step|
+ if cycles.none?(&:nil?)
+ puts gcd(*cycles.map(&:size))
+ exit
+ end
+
+ (0..2).each do |i|
+ seen[i][moons.fingerprint(i)] ||= step
+ end
+
moons = moons.step
+
+ (0..2).each do |i|
+ cycles[i] ||= (seen[i][moons.fingerprint(i)]..step) if seen[i].include?(moons.fingerprint(i))
+ end
end
- puts moons.energy
end