Ruby universal orbit map
This commit is contained in:
parent
d30e3f9600
commit
7708169e56
9
ruby/2019/6/bin/problem
Normal file
9
ruby/2019/6/bin/problem
Normal file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require "universal_orbit_map"
|
||||
|
||||
map = UniversalOrbitMap.for STDIN.read.chomp
|
||||
|
||||
puts "Part 1: #{map.bodies.values.map(&:orbit_chain).map(&:length).sum}"
|
||||
|
||||
puts "Part 2: #{map.path_between("YOU", "SAN").length}"
|
||||
55
ruby/2019/6/lib/universal_orbit_map.rb
Normal file
55
ruby/2019/6/lib/universal_orbit_map.rb
Normal file
@ -0,0 +1,55 @@
|
||||
class UniversalOrbitMap
|
||||
attr_reader :orbits, :bodies
|
||||
def initialize(orbits)
|
||||
@orbits = orbits
|
||||
body_names = orbits.map(&:orbitee) | orbits.map(&:orbiter)
|
||||
@bodies = body_names.to_h { |name| [name, Body.new(name)] }
|
||||
orbits.each do |orbit|
|
||||
bodies[orbit.orbitee].orbiters << orbit.orbiter
|
||||
bodies[orbit.orbiter].orbiting = bodies[orbit.orbitee]
|
||||
end
|
||||
end
|
||||
|
||||
def self.for(input)
|
||||
new input.split("\n").map { |line| Orbit.for line }
|
||||
end
|
||||
|
||||
def path_between(to, from)
|
||||
to_chain = bodies[to].orbit_chain.map(&:name)
|
||||
from_chain = bodies[from].orbit_chain.map(&:name)
|
||||
common_chain = to_chain & from_chain
|
||||
(from_chain - common_chain) + (to_chain - common_chain).reverse
|
||||
end
|
||||
|
||||
class Body
|
||||
attr_reader :name, :orbiters
|
||||
attr_accessor :orbiting
|
||||
def initialize(name)
|
||||
@name = name
|
||||
@orbiting = nil
|
||||
@orbiters = []
|
||||
end
|
||||
|
||||
def orbit_chain
|
||||
chain = [orbiting]
|
||||
while chain.last
|
||||
chain << chain.last.orbiting
|
||||
end
|
||||
chain[..-2]
|
||||
end
|
||||
end
|
||||
|
||||
class Orbit
|
||||
attr_accessor :orbitee, :orbiter, :orbitee_name, :orbiter_name
|
||||
def initialize(orbitee, orbiter)
|
||||
@orbiter = orbiter
|
||||
@orbiter_name = orbiter
|
||||
@orbitee = orbitee
|
||||
@orbitee_name = orbitee
|
||||
end
|
||||
|
||||
def self.for(line)
|
||||
new *line.split(")")
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user