-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.rb
107 lines (88 loc) · 2.08 KB
/
main.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
MOONS = File.read('data.txt').each_line.map{ |l| l.scan(/-?\d+/).map(&:to_i) }
def sum_arr a, b
a.zip(b).map{ |s| s.reduce(:+) }
end
class MoonSim
def initialize moons
@moons = moons.map do |m|
{
position: m,
velocity: [0, 0, 0],
}
end
end
def one_step
apply_gravity
apply_velocity
end
def get_moons
@moons
end
def gravity_single moon
@moons.map do |m|
moon[:position].zip(m[:position]).map{ |a, b| b <=> a }
end.inject do |t, c|
sum_arr t, c
end
end
def apply_gravity
@moons = @moons.map do |m|
v = sum_arr m[:velocity], gravity_single(m)
m.merge({ velocity: v })
end
end
def apply_velocity
@moons = @moons.map do |m|
pos = sum_arr *m.values
m.merge({ position: pos })
end
end
def potential_energy
@moons.map do |m|
m[:position].map{ |x| x.abs }.sum
end.sum
end
def kinetic_energy
@moons.map do |m|
m[:velocity].map{ |x| x.abs }.sum
end.sum
end
def total_energy
@moons.map do |m|
m[:position].map{ |x| x.abs }.sum *
m[:velocity].map{ |x| x.abs }.sum
end.sum
end
end
def sim_n_steps n
ms = MoonSim.new MOONS
n.times do
ms.one_step
end
[ms.potential_energy, ms.kinetic_energy, ms.total_energy]
end
def find_loop_with_getter getter
cache = {}
ms = MoonSim.new MOONS
initial = getter[ms.get_moons]
step = 0
loop do
ms.one_step
step += 1
return step if getter[ms.get_moons] == initial
end
end
def find_loop
gen_getter = lambda do |n|
lambda do |moons|
moons.map{ |m| [m[:position][n], m[:velocity][n]] }.flatten
end
end
3.times.map do |n|
find_loop_with_getter gen_getter[n]
end.inject(&:lcm)
end
PART1 = sim_n_steps(1000).last
PART2 = find_loop
puts 'Part 1: %s' % PART1
puts 'Part 2: %s' % PART2