红宝石阵列的金字塔修饰

时间:2016-04-24 17:48:01

标签: arrays ruby logic

我正在编写一个脚本,它带有两个参数,一个二维数组(全0和1' s)和一个最大垂直距离n,并返回一个修改过的数组。这样,如果n = 3,则以下数组

[[0,0,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,0,0]]

返回

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

(数组输入可以有任何矩形尺寸;任何元素都可以是10)。

我的想法是克隆原始数组,扫描1年,然后将更改映射到克隆中。我试图将更改首先映射到右侧,然后映射到原始1的左侧。

我得到了以下工作,它改变了数组的中心列:

a = [[0,0,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,0,0]]

cloned = a.map(&:clone)

n = 3

a.each.with_index do |whole_row, row|
    whole_row.each.with_index do |cell, column|
        if cell == 1

            #center column
            row_path = row - n
            (n*2+1).times do
                unless (cloned[row_path][column]).nil?
                    cloned[row_path][column] = 1
                end
                row_path += 1
            end

        end
    end
end

cloned

然而,当我尝试向右移动此过程时,我得到了undefined method '[]' for nil:NilClass。我在哪里弄乱这里的逻辑?

a = [[0,0,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,0,0]]

cloned = a.map(&:clone)

n = 3

a.each.with_index do |whole_row, row|
    whole_row.each.with_index do |cell, column|
        if cell == 1

            #central column & right side
            row_path = row - n
            column_path = column
            repetition = 2 * n + 1
            (n+1).times do 
                (repetition).times do
                    unless cloned[row_path][column_path].nil?
                        cloned[row_path][column_path] = 1
                    end
                    row_path += 1
                end
                repetition -= 2
                column_path += 1
                row_path += 1
            end
        end
    end
end

cloned

(我的想法是在原始数组的右边和左边两次实现这个过程。)

3 个答案:

答案 0 :(得分:1)

发生错误是因为您尝试访问不存在的数组索引的子数组中的项。

此行 - cloned[row_path][column_path].nil?此处row_path在某些迭代中不包含任何值,这是因为您将它递增两次。

(repetition).times删除增量应修复它。

希望这有帮助

答案 1 :(得分:1)

从您的示例中我假设[i,j][k,l]之间的元素之间的“垂直距离”由方法给出:

def dist((i,j),(k,l))
  (i-k).abs + (j-l).abs
end

在这种情况下,“矩形距离”将是更好的描述符。如果这个假设不正确,你不需要再读了。

对于你的例子:

a = [[0,0,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,0,0]]

n = 3

在定义上面的方法dist之后,您可以按如下方式构造所需的数组:

nrows = a.size
  #=> 7
ncols = a.first.size
  #=> 7

Array.new(nrows) do |i|
  Array.new(ncols) do |j|
    nrows.times.any? do |k|
      ncols.times.any? do |l|
        a[k][l] == 1 && dist([i,j],[k,l]) <= n
      end
    end ? 1 : 0
  end
end
  #=> [[0, 0, 0, 1, 0, 0, 0],
  #    [0, 0, 1, 1, 1, 0, 0],
  #    [0, 1, 1, 1, 1, 1, 0],
  #    [1, 1, 1, 1, 1, 1, 1],
  #    [0, 1, 1, 1, 1, 1, 0],
  #    [0, 0, 1, 1, 1, 0, 0],
  #    [0, 0, 0, 1, 0, 0, 0]]

或者,你可以反过来做(计算nrowsncols)。

b = Array.new(nrows) { Array.new(ncols,0) }
nrows.times.each do |i|
  ncols.times.each do |j|
    next unless a[i][j]==1
    nrows.times.each do |k|
      ncols.times.each do |l|
        b[k][l] = 1 if dist([i,j],[k,l]) <= n
      end
    end
  end
end                 
b

通过限制检查的行(作为目标行和n的函数),以及对于考虑的每一行,通过限制检查的列(作为函数),可以使这两种方法更有效行,目标行和列以及n)。

答案 2 :(得分:0)

考虑到Dwijen的回答,我调整了脚本,以便在测试时索引内部没有任何内容。我收到错误,直到我继续unless (row_path > cloned.length - 1 )这通过了测试:

a.each.with_index do |whole_row, row|
  whole_row.each.with_index do |cell, column|
    if cell == 1

      #central column & right side
      row_path = row - n
      column_path = column
      repetition = 2 * n + 1
      counter = 0
      (n+1).times do 
        (repetition).times do
          unless (row_path > cloned.length - 1 ) || cloned[row_path][column_path].nil? 
            cloned[row_path][column_path] = 1
          end
          row_path += 1
        end
        counter += 1
        repetition -= 2
        column_path += 1
        row_path = row - n + counter
      end

      #central column & left side
      row_path = row - n
      column_path = column
      repetition = 2 * n + 1
      counter = 0
      (n+1).times do 
        (repetition).times do
          unless (row_path > cloned.length - 1 ) || cloned[row_path][column_path].nil? 
            cloned[row_path][column_path] = 1
          end
          row_path += 1
        end
        counter -= 1
        repetition -= 2
        column_path -= 1
        row_path = row - n - counter
      end

    end
  end
end
相关问题