From 3ace918ff2580f06d16209871724ebe7b40e1b8f Mon Sep 17 00:00:00 2001 From: Bill Rossi Date: Thu, 4 Dec 2025 05:37:12 -0500 Subject: [PATCH] 2025 ruby day 4 --- ruby/2025/4/bin/problem | 7 +++ ruby/2025/4/lib/printing_department.rb | 64 ++++++++++++++++++++ ruby/2025/4/test/test_printing_department.rb | 40 ++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 ruby/2025/4/bin/problem create mode 100644 ruby/2025/4/lib/printing_department.rb create mode 100644 ruby/2025/4/test/test_printing_department.rb diff --git a/ruby/2025/4/bin/problem b/ruby/2025/4/bin/problem new file mode 100644 index 0000000..d6cddda --- /dev/null +++ b/ruby/2025/4/bin/problem @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby +require "printing_department" + +printing_department = PrintingDepartment.for STDIN.read.chomp +puts "Part 1: #{printing_department.accessible_rolls.count}" +printing_department.remove_all_accessible_rolls! +puts "Part 2: #{printing_department.removed_rolls.count}" \ No newline at end of file diff --git a/ruby/2025/4/lib/printing_department.rb b/ruby/2025/4/lib/printing_department.rb new file mode 100644 index 0000000..56875cd --- /dev/null +++ b/ruby/2025/4/lib/printing_department.rb @@ -0,0 +1,64 @@ +class PrintingDepartment + attr_reader :rows, :removed_rolls + def initialize(rows) + @rows = rows + @removed_rolls = [] + end + + def self.for(string) + new string.split("\n").map{ |row| row.split("") } + end + + def rolls + rows.each_with_index.map do |row, row_index| + row.each_with_index.map do |char, column_index| + [row_index, column_index] if char == "@" + end.compact + end.flatten(1) + end + + def char_at(row, column) + rows[row][column] + end + + def width + rows[0].length + end + + def height + rows.length + end + + def neighbor_indices(row, column) + [0, row - 1].max.upto([width - 1, row + 1].min).map do |r| + [0, column - 1].max.upto([height - 1, column + 1].min).map do |c| + [r, c] + end + end.flatten(1).reject{ |r, c| r == row && c == column } + end + + def neighbors(row, column) + neighbor_indices(row, column).map { |nr, nc| char_at nr, nc } + end + + def adjacent_roll_count(row, column) + neighbors(row, column).select { |char| char == "@" }.count + end + + def accessible_rolls + rolls.select{ |r, c| adjacent_roll_count(r, c) < 4 } + end + + def remove_roll!(row, col) + removed_rolls << [row, col] + rows[row][col] = "." + end + + def remove_accessible_rolls! + accessible_rolls.each { |r, c| remove_roll! r, c } + end + + def remove_all_accessible_rolls! + remove_accessible_rolls! until accessible_rolls.empty? + end +end diff --git a/ruby/2025/4/test/test_printing_department.rb b/ruby/2025/4/test/test_printing_department.rb new file mode 100644 index 0000000..8f7a672 --- /dev/null +++ b/ruby/2025/4/test/test_printing_department.rb @@ -0,0 +1,40 @@ +require "minitest/autorun" +require "printing_department" + +class TestPrintingDepartment < Minitest::Test + def test_accessible_rolls + map = <