Ruby universal orbit map

This commit is contained in:
Bill Rossi 2025-12-06 10:19:18 -05:00
parent d30e3f9600
commit 7708169e56
2 changed files with 64 additions and 0 deletions

9
ruby/2019/6/bin/problem Normal file
View 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}"

View 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