Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iterate with a method within ruby class

Class Image initializes with an array of 0's and 1's. I have method transform, such that

[[0,0,0],
 [0,1,0],
 [0,0,0]]

returns

[[0,1,0],
 [1,1,1],
 [0,1,0]]

I want to implement method blur(n), which iterates n times with transform, such calling blur(2) with

[[0,0,0,0,0,0,0,0,0],
 [0,0,0,0,0,0,0,0,0],
 [0,0,0,0,1,0,0,0,0],
 [0,0,0,0,0,0,0,0,0],
 [0,0,0,0,0,0,0,0,0]]

returns

[[0,0,0,0,1,0,0,0,0],
 [0,0,0,1,1,1,0,0,0],
 [0,0,1,1,1,1,1,0,0],
 [0,0,0,1,1,1,0,0,0],
 [0,0,0,0,1,0,0,0,0]]

I'm trying to use transform iteratively to achieve this, but I'm getting undefined method 'map' for #<Context::Image:0x000000012eb020> when calling blur with an instance of Image. How can I iterate over each successive transformation, such that blur returns the latest version with the maximum n transformations?

class Image
  attr_accessor :array

  def initialize(array)
    self.array = array
  end

  def output_image
    self.array.each do |item|
      puts item.join
    end
  end

  def transform #changes adjacent a 1's adjacent 0's into 1
    cloned = self.array.map(&:clone)

    #scan original array for 1; map crosses into clone if found
    self.array.each.with_index do |row, row_index|
      row.each.with_index do |cell, col|
        if cell == 1
          cloned[row_index][col+1] = 1 unless col+1 >= row.length #copy right
          cloned[row_index+1][col] = 1 unless row_index+1 >= cloned.length # copy down
          cloned[row_index][col-1] = 1 unless col.zero? # copy left
          cloned[row_index-1][col] = 1 unless row_index.zero? #copy up
        end
      end
    end
    cloned
  end

  def blur(n) #should call transform iteratively n times
    blurred = Image.new(self)
    n.times do
      blurred = blurred.transform
    end
    blurred
  end

end
like image 595
gonzalo2000 Avatar asked Mar 27 '26 08:03

gonzalo2000


1 Answers

You could use the Matrix class.

require 'matrix'    

class Matrix
  def el(r,c)
    if r < 0 || r >= row_count || c < 0 || c >= column_count
      0
    else
      self[r,c]
    end
  end

  def transform
    Matrix.build(row_count, column_count) { |r,c|
      [el(r,c), el(r-1,c), el(r+1,c), el(r,c-1), el(r,c+1)].max }
  end
end

Given a row-column pair, r, c, the helper method el returns 0 if the row or column is outside the bounds of the matrix and the value at [r,c] otherwise.

nrows = 5
ncols = 5

m = Matrix.build(nrows, ncols) { |r,c| (r==nrows/2 && c==ncols/2) ? 1 : 0 }
  #=> Matrix[[0, 0, 0, 0, 0],
  #          [0, 0, 0, 0, 0],
  #          [0, 0, 1, 0, 0],
  #          [0, 0, 0, 0, 0],
  #          [0, 0, 0, 0, 0]] 
m = m.transform
  #=> Matrix[[0, 0, 0, 0, 0],
  #          [0, 0, 1, 0, 0],
  #          [0, 1, 1, 1, 0],
  #          [0, 0, 1, 0, 0],
  #          [0, 0, 0, 0, 0]] 
m = m.transform
  #   Matrix[[0, 0, 1, 0, 0],
  #          [0, 1, 1, 1, 0],
  #          [1, 1, 1, 1, 1],
  #          [0, 1, 1, 1, 0],
  #          [0, 0, 1, 0, 0]]
m.to_a
  #=>       [[0, 0, 1, 0, 0],
  #          [0, 1, 1, 1, 0],
  #          [1, 1, 1, 1, 1],
  #          [0, 1, 1, 1, 0],
  #          [0, 0, 1, 0, 0]] 
like image 134
Cary Swoveland Avatar answered Mar 29 '26 22:03

Cary Swoveland



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!