From 7b70b2fca5413049c325f2a432571ae60a64df2d Mon Sep 17 00:00:00 2001 From: Bill Rossi Date: Mon, 8 Dec 2025 04:48:46 -0500 Subject: [PATCH] 2025 ruby day 8 --- ruby/2025/8/bin/problem | 10 ++++ ruby/2025/8/lib/playground.rb | 96 +++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 ruby/2025/8/bin/problem create mode 100644 ruby/2025/8/lib/playground.rb diff --git a/ruby/2025/8/bin/problem b/ruby/2025/8/bin/problem new file mode 100644 index 0000000..a423098 --- /dev/null +++ b/ruby/2025/8/bin/problem @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby + +require "playground" + +pg = Playground.for STDIN.read.chomp +pg.connect_circuits! +puts "Part 1: #{pg.circuits.values.uniq.sort_by(&:length).last(3).map(&:length).reduce(&:*)}" + +pg.connect_all_circuits! +puts "Part 2: #{pg.last_pair.map(&:x).reduce(&:*)}" \ No newline at end of file diff --git a/ruby/2025/8/lib/playground.rb b/ruby/2025/8/lib/playground.rb new file mode 100644 index 0000000..c87c490 --- /dev/null +++ b/ruby/2025/8/lib/playground.rb @@ -0,0 +1,96 @@ +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