[2019][ruby][12.2]
change skvtmqznoyuvwttknvmrwtpnsltxorwo
commit 00fdd9d0e00943e99d9705340374a3250d06dd02
author Alpha Chen <alpha@kejadlen.dev>
date
parent rrnwuwpk
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