From 850d181bdc1d467e356c1b23f66c2a8d309b62fe Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Thu, 12 Dec 2019 16:16:25 -0800 Subject: [PATCH] [2019][ruby][12.2] --- 2019/ruby/day_12.rb | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) 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