Danny Sullivan
Danny Sullivan

Reputation: 277

Two Dimensional Array With Ruby

I am trying to take in a 2D array, search for any space that is greater than 0, then increment the surrounding spaces by 1.

array = [[0,0,0], [0,1,0], [0,0,0]]

The final output should look like this

new_array = [[0,1,0], [1,1,1], [0,1,0]]

The way I have it set up currently is returning

[1,1,1,1]

It is incrementing the correct spaces, I think, I just am not sure how to put them back into the original arrays and then return the 2D array. Clearly some steps are missing, any help would be greatly appreciated. I understand why it is returning the way it is, just not clear on the next step.

def dilate(array)
  new_array = []
  array.each_with_index do |row, rowIndex|
    row.each_with_index do |col, colIndex|
      if (array[rowIndex][colIndex] > 0)
        new_array << (array[rowIndex][colIndex -1] +1)
        new_array << (array[rowIndex -1][colIndex] +1)
        new_array << (array[rowIndex][colIndex +1] +1)
        new_array << (array[rowIndex +1][colIndex] +1)
      end
    end
  end
  return new_array
end

enter image description here

Upvotes: 2

Views: 977

Answers (2)

KSFT
KSFT

Reputation: 1774

What you're doing is initializing an empty array, new_array, and appending elements to it. You're appending the incremented values to a new array instead of changing the values in the array. Something like this should work:

def dilate(array)
  new_array=[]
  array.each{|i|new_array<<i.dup}
  array.each_with_index do |row, rowIndex|
    row.each_with_index do |col, colIndex|
      if (array[rowIndex][colIndex] > 0)
        new_array[rowIndex][colIndex -1] += 1 if colIndex > 0
        new_array[rowIndex -1][colIndex] += 1 if rowIndex > 0
        new_array[rowIndex][colIndex +1] += 1 if colIndex < array.first.size-1
        new_array[rowIndex +1][colIndex] += 1 if rowIndex < array.size-1
      end
    end
  end
  return new_array
end

I'm creating a new array, new_array, that's a copy of array, then incrementing its elements.

By the way, you say in your question that you want to "search for any space that contains a 1", but what this is doing is searching for spaces containing values greater than zero. I'm not sure if that's what you wanted.

Upvotes: 2

Cary Swoveland
Cary Swoveland

Reputation: 110665

I suggest you use the class Matrix for this. It makes it easy to do and easy to read.

Code

require 'matrix'

def dilate(arr)
  nrows, ncols = arr.size, arr[0].size
  m = Matrix[*arr]
  m.each_with_index.reduce(m.dup) { |mout, (e, row, col)|
    mout + Matrix.build(nrows, ncols) { |i,j|
      adjacent?(i,j,row,col) ? e : 0 } }.to_a
end

def adjacent?(r0,c0,r1,c1)
  ((r0-r1).abs == 1 && (c0==c1)) || ((c0-c1).abs == 1 && (r0==r1))
end

I have assumed that, when the value of an element, x, is non-zero, you want to increase the values of adjacent elements by x. If you want to increase the values of adjacent elements by 1, change:

Matrix.build(nrows, ncols) { |i,j| adjacent?(i,j,row,col) ? e : 0 }

to:

Matrix.build(nrows, ncols) { |i,j| adjacent?(i,j,row,col) ? 1 : 0 }

Examples

arr = [[0, 0, 0],
       [0, 1, 0],
       [0, 0, 0]]           
dilate(arr)
  #=> [[0, 1, 0],
  #    [1, 1, 1],
  #    [0, 1, 0]] 

arr = [[0, 0, 0, 0],
       [0, 1, 0, 0],
       [0, 0, 0, 0]]           
dilate(arr)
  #=> [[0, 1, 0, 0],
  #    [1, 1, 1, 0],
  #    [0, 1, 0, 0]]

arr = [[1, 0, 0],
       [0, 0, 0],
       [0, 0, 0]]
dilate(arr)
  #=> [[1, 1, 0],
  #    [1, 0, 0],
  #    [0, 0, 0]] 

arr = [[0, 0, 0],
       [1, 0, 0],
       [0, 0, 0]]
dilate(arr)
  #=> [[1, 0, 0],
  #    [1, 1, 0],
  #    [1, 0, 0]] 

arr = [[0, 0, 1],
       [0, 0, 0],
       [0, 0, 0]]
dilate(arr)
  #=> [[0, 1, 1],
  #    [0, 0, 1],
  #    [0, 0, 0]]

arr = [[0, 0, 0, 3],
       [0, 1, 1, 0],
       [0, 4, 1, 0],
       [2, 0, 0, 0]]    
dilate(arr)
  #=> [[0, 1, 4, 3],
  #    [1, 6, 3, 4],
  #    [6, 6, 6, 1],
  #    [2, 6, 1, 0]] 

Upvotes: 1

Related Questions