From 85cdc38184441a21d4e6aa06618b60e2f5cac311 Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Thu, 12 Dec 2019 08:42:00 -0800 Subject: [PATCH] [2019][ruby][12.1] --- 2019/ruby/day_12.rb | 93 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 2019/ruby/day_12.rb diff --git a/2019/ruby/day_12.rb b/2019/ruby/day_12.rb new file mode 100644 index 0000000..d2b48b1 --- /dev/null +++ b/2019/ruby/day_12.rb @@ -0,0 +1,93 @@ +require "matrix" +require "set" + +V = Vector +Moon = Struct.new(:id, :pos, :vel) do + def potential_energy + pos.map(&:abs).sum + end + + def kinetic_energy + vel.map(&:abs).sum + end +end + +class Moons < SimpleDelegator + def self.from(input) + moons = input + .scan(/x=(-?\d+), y=(-?\d+), z=(-?\d+)/) + .map.with_index {|x,i| Moon.new(i, V[*x.map(&:to_i)], V.zero(3)) } + new(moons) + end + + def step + # apply gravity + deltas = Hash.new {|h,k| h[k] = V.zero(3) } + combination(2).each do |a, b| + delta = V[*a.pos.zip(b.pos).map {|a,b| a <=> b }] + deltas[a] -= delta + deltas[b] += delta + end + + # apply velocity + Moons.new(map {|m| + v = m.vel + deltas.fetch(m) + Moon.new(m.id, m.pos + v, v) + }) + end + + def energy + map {|m| m.potential_energy * m.kinetic_energy }.sum + end +end + +require "minitest" + +class TestMoons < Minitest::Test + def setup + @moons = Moons.from(<<~MOONS) + + + + + MOONS + end + + def test_from + assert_equal Moon.new(0, V[-1, 0, 2], V[0, 0, 0]), @moons.fetch(0) + assert_equal Moon.new(3, V[3, 5, -1], V[0, 0, 0]), @moons.fetch(3) + end + + def test_step + moons = @moons.step + + assert_equal Moon.new(0, V[2, -1, 1], V[3, -1, -1]), moons.fetch(0) + assert_equal Moon.new(3, V[2, 2, 0], V[-1, -3, 1]), moons.fetch(3) + + 9.times do + moons = moons.step + end + + assert_equal Moon.new(0, V[2, 1, -3], V[-3, -2, 1]), moons.fetch(0) + assert_equal Moon.new(3, V[2, 0, 4], V[1, -1, -1]), moons.fetch(3) + end + + def test_energy + 10.times do + @moons = @moons.step + end + + assert_equal 179, @moons.energy + end +end + +if ARGF.to_io.tty? + require "minitest/autorun" +else + moons = Moons.from(ARGF.read) + + 1000.times do + moons = moons.step + end + puts moons.energy +end