-
Notifications
You must be signed in to change notification settings - Fork 0
/
day12.rb
80 lines (67 loc) · 1.48 KB
/
day12.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
require 'byebug'
class Moon
def self.new_from_string(string)
parts = string.gsub(/<|>| |(x|y|z)=/, '').split(',').map(&:to_i)
Moon.new(*parts)
end
attr_reader :x, :y, :z
def coordinates
[@x, @y, @z]
end
def velocities
[@vx, @vy, @vz]
end
def initialize(x,y,z)
@x, @y, @z = x,y,z
@vx, @vy, @vz = 0,0,0
@delta_vx, @delta_vy, @delta_vz = 0,0,0
end
def apply_gravity(moon)
# if my coordinate is lower, I need +1
@delta_vx += -(@x <=> moon.x)
@delta_vy += -(@y <=> moon.y)
@delta_vz += -(@z <=> moon.z)
end
def step
@vx += @delta_vx
@vy += @delta_vy
@vz += @delta_vz
@delta_vx, @delta_vy, @delta_vz = 0,0,0
@x += @vx
@y += @vy
@z += @vz
end
def total_energy
(@x.abs + @y.abs + @z.abs) * (@vx.abs + @vy.abs + @vz.abs)
end
end
class OrbitalSystem
def initialize(moons)
@moons = moons
end
def step
@moons.each do |moon|
(@moons - [moon]).each do |other_moon|
moon.apply_gravity(other_moon)
end
end
@moons.map(&:step)
end
def system_energy
@moons.map(&:total_energy).sum
end
end
if __FILE__ == $0
moons = []
DATA.read.split("\n").each do |moon_data|
moons << Moon.new_from_string(moon_data)
end
orbital_system = OrbitalSystem.new(moons)
1000.times { orbital_system.step }
print "System Energy after 1000 steps: #{orbital_system.system_energy}\n\n"
end
__END__
<x=12, y=0, z=-15>
<x=-8, y=-5, z=-10>
<x=7, y=-17, z=1>
<x=2, y=-11, z=-6>