97 lines
2.0 KiB
Ruby
97 lines
2.0 KiB
Ruby
class Playground
|
|
attr_reader :boxes, :circuits, :last_pair
|
|
def initialize(boxes)
|
|
@boxes = boxes
|
|
boxes.each { |box| box.pg = self }
|
|
@circuits = boxes.to_h{ |box| [box.index, Circuit.new(box)] }
|
|
end
|
|
|
|
def self.for(input)
|
|
new input.split("\n").each_with_index.map(&JunctionBox.method(:for))
|
|
end
|
|
|
|
def distances
|
|
boxes.map { |b1| boxes.map { |b2| b1.distance_squared(b2) } }
|
|
end
|
|
|
|
def distance_pairs
|
|
distances.each_with_index.map do |dist_row, x|
|
|
dist_row.each_with_index.map do |dist, y|
|
|
[[x, y].min, [x,y].max, dist]
|
|
end
|
|
end.flatten(1).uniq.sort_by { |dp| dp[2] }
|
|
end
|
|
|
|
def connect_circuits!(connections=1000)
|
|
distance_pairs.first(connections).each do |a, b, _|
|
|
connect_circuit!(a, b)
|
|
end
|
|
end
|
|
|
|
def connect_all_circuits!
|
|
distance_pairs.each do |a, b, _|
|
|
connect_circuit!(a, b)
|
|
break if all_connected?
|
|
end
|
|
end
|
|
|
|
def all_connected?
|
|
circuits.values.uniq.length == 1
|
|
end
|
|
|
|
def connect_circuit!(a, b)
|
|
return if circuits[a].boxes.include?(boxes[b])
|
|
|
|
@last_pair = boxes[a], boxes[b]
|
|
|
|
circuits[a].boxes.push(*Array.new(circuits[b].boxes))
|
|
circuits[b].boxes.each { |box| circuits[box.index] = circuits[a] }
|
|
end
|
|
|
|
class JunctionBox
|
|
attr_reader :index, :x, :y, :z
|
|
attr_accessor :pg
|
|
def initialize(index, x, y, z)
|
|
@index = index
|
|
@x = x
|
|
@y = y
|
|
@z = z
|
|
end
|
|
|
|
def self.for(line, index)
|
|
new index, *line.split(",").map(&:to_i)
|
|
end
|
|
|
|
def distance_squared(other)
|
|
return 9999999999999 if self == other
|
|
|
|
(x - other.x)**2 +
|
|
(y - other.y)**2 +
|
|
(z - other.z)**2
|
|
end
|
|
|
|
def distances
|
|
@distances ||= pg.boxes.map { |box| distance_squared(box) }
|
|
end
|
|
|
|
def to_s
|
|
"#{index} (#{x}, #{y}, #{z})"
|
|
end
|
|
end
|
|
|
|
class Circuit
|
|
attr_reader :boxes
|
|
def initialize(box)
|
|
@boxes = [box]
|
|
end
|
|
|
|
def to_s
|
|
boxes.map(&:index)
|
|
end
|
|
|
|
def length
|
|
boxes.length
|
|
end
|
|
end
|
|
end
|