aoc_omni/ruby/2025/4/lib/printing_department.rb
2025-12-04 05:37:12 -05:00

65 lines
1.4 KiB
Ruby

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