2016-04-24 15 views
0

2次元の配列(すべて0と1)と最大垂直距離nの2つのパラメタをとり、修正された配列を返すスクリプトを書いています。その結果、その次の配列の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 

(私の考えは、この手順を元の配列の右と左に2回実装することです)。

+0

"最大垂直距離"を単語で定義する必要があります(質問を編集してください)。この例では十分ではありません。また、どの要素が10になることができますか? –

答えて

1

私は[i,j][k,l]の要素間の「垂直距離」の方法で与えられることを想定しています:

私はこれはテストに合格 unless (row_path > cloned.length - 1)を続行するために追加されるまで、私はエラーを取得しました。
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]] 

、あなたはそれを周り(と他の方法を行うことができますnrowsおよびncolsを計算した)。

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)。

1

エラーは、存在しない配列インデックスのサブ配列内の項目にアクセスしようとしているために発生します。

この行 - cloned[row_path][column_path].nil?ここではrow_pathは一部の反復では値を保持しません。これは、2回インクリメントしているためです。

(repetition).timesから増分を削除すると修正されます。テストインデックス内部にはゼロがありませんように

希望これはDwijenの答えを考える

0

を助け、私は、スクリプトを微調整しました。あなたの例から

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