[2019][ruby][12.1]

master
Alpha Chen 5 years ago
parent 975834ce55
commit 85cdc38184

@ -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)
<x=-1, y=0, z=2>
<x=2, y=-10, z=-7>
<x=4, y=-8, z=8>
<x=3, y=5, z=-1>
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
Loading…
Cancel
Save