From d3952a8ed215f96aca449e71eaf9a2f47aa21e78 Mon Sep 17 00:00:00 2001 From: Bill Rossi Date: Fri, 5 Dec 2025 07:17:50 -0500 Subject: [PATCH] Hoo boy 2025 ruby day 5 --- ruby/2025/5/bin/problem | 6 ++ ruby/2025/5/lib/ingredient_management.rb | 56 +++++++++++++++++++ .../2025/5/test/test_ingredient_management.rb | 43 ++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 ruby/2025/5/bin/problem create mode 100644 ruby/2025/5/lib/ingredient_management.rb create mode 100644 ruby/2025/5/test/test_ingredient_management.rb diff --git a/ruby/2025/5/bin/problem b/ruby/2025/5/bin/problem new file mode 100644 index 0000000..3463d21 --- /dev/null +++ b/ruby/2025/5/bin/problem @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby + +require "ingredient_management" +im = IngredientManagement.for(STDIN.read.chomp) +puts "Part 1: #{im.fresh_ingredient_ids.count}" +puts "Part 2: #{im.all_fresh_ids_count}" \ No newline at end of file diff --git a/ruby/2025/5/lib/ingredient_management.rb b/ruby/2025/5/lib/ingredient_management.rb new file mode 100644 index 0000000..37323c8 --- /dev/null +++ b/ruby/2025/5/lib/ingredient_management.rb @@ -0,0 +1,56 @@ +class IngredientManagement + attr_reader :ranges, :ids + def initialize(ranges, ids) + @ranges = ranges + @ids = ids + end + + def self.for(input) + ranges, ids = input.split("\n\n") + new( + ranges.split("\n").map{ |r| s, e = r.split("-").map(&:to_i); s..e }, + ids.split("\n").map(&:to_i) + ) + end + + def fresh?(id) + ranges.any? { |range| range.include? id } + end + + def fresh_ingredient_ids + ids.select { |id| fresh? id } + end + + def all_fresh_ids + # this makes it OOM! + # return ranges.map(&:to_a).flatten.uniq + [] + end + + def all_fresh_ids_count + combine_ranges.map(&:size).sum + end + + def combine_two_ranges(r1, r2) + return [r1, r2] if r2.begin > r1.end || r1.begin > r2.end + + [([r1.begin, r2.begin].min)..([r1.end, r2.end].max)] + end + + def combine_ranges(rs = ranges) + rs.sort_by!(&:begin) + index = 0 + while index < rs.length - 1 + c2r = combine_two_ranges(rs[index], rs[index + 1]) + if c2r.length == 2 # did not combine + index += 1 + else # combined + rs.delete_at(index) + rs.delete_at(index) + rs.insert(index, c2r[0]) + end + end + + rs + end +end diff --git a/ruby/2025/5/test/test_ingredient_management.rb b/ruby/2025/5/test/test_ingredient_management.rb new file mode 100644 index 0000000..3a4517c --- /dev/null +++ b/ruby/2025/5/test/test_ingredient_management.rb @@ -0,0 +1,43 @@ +require "minitest/autorun" +require "ingredient_management" + +class TestIngredientManagement < Minitest::Test + def database + <<-END +3-5 +10-14 +16-20 +12-18 + +1 +5 +8 +11 +17 +32 +END + end + def test_fresh_ingredient_ids + im = IngredientManagement.for(database) + assert_equal([1,5,8,11,17,32], im.ids) + assert_equal([3..5, 10..14, 16..20, 12..18], im.ranges) + assert_equal([5, 11, 17], im.fresh_ingredient_ids) + end + + def test_all_fresh_ids_count + im = IngredientManagement.for(database) + assert_equal(14, im.all_fresh_ids_count) + end + + def test_combine_two_ranges + im = IngredientManagement.new([], []) + assert_equal([1..6, 9..12], im.combine_two_ranges(1..6, 9..12)) + assert_equal([1..12], im.combine_two_ranges(1..9, 6..12)) + assert_equal([1..12], im.combine_two_ranges(1..9, 1..12)) + end + + def test_combine_ranges + im = IngredientManagement.new([1..2, 3..4, 2..6, 9..12], []) + assert_equal([1..6, 9..12], im.combine_ranges) + end +end