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