2016-04-17 12 views
1

私はいくつかの演習を行っている初心者です。配列要素の周囲の要素を変更する

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

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

Iを返す必要があります。私は、要素が1である場合、次いで、周囲の非対角要素が1に変更されなければならないような2次元アレイを操作しようとしています入れ子になったeach_with_indexを使って問題に遭遇しています:周囲の左右の初期の変更を調整した後、メソッドが反復するにつれて、それは以前の調整によってピックアップされ、望ましくない変更を行います。また、「底」の要素を変更する必要があります行がエラーを投げている:

a = [[0,0,0,0], 
    [0,0,1,0], 
    [0,0,0,0], 
    [0,0,0,0] 
    ] 

a.each_with_index do |m, n| # n == index of main array 
    m.each_with_index do |x, y| # y == index of subarray 
     if x == 1 
      a[n][y+1] = 1 unless (a[n][y+1]).nil? #right 
      a[n][y-1] = 1 unless (a[n][y-1]).nil? #left 
      a[n-1][y] = 1 unless (a[n-1][y]).nil? #top 
      a[n+1][y] = 1 unless (a[n+1][y]).nil? #bottom--currently giving an error 
     end 
    end 
end 

任意の提案を、私はうまく受信されるこれら二つの側面を解決して行くことができる方法のよう。

+0

何が望ましくない変更ですか?それを詳しく説明してください。何のエラー? – sawa

答えて

1

Matrixクラスを使用することをお勧めします。

require 'matrix' 

m = Matrix[*a] 
    #=> Matrix[[0, 0, 0, 0], 
    #   [0, 0, 1, 0], 
    #   [0, 0, 0, 0], 
    #   [0, 0, 0, 0]] 
row, col = m.index(1) 
    #=> [1, 2] 
Matrix.build(m.row_size, m.column_size) { |r,c| 
    (c-col).abs + (r-row).abs <= 1 ? 1 : 0 }.to_a 
    #=> [[0, 0, 1, 0], 
    # [0, 1, 1, 1], 
    # [0, 0, 1, 0], 
    # [0, 0, 0, 0]] 

以下の通りである(Array#indexは、Fixnum#divmodArray::newEnumerable#each_slice、およびいくつかの他の方法を使用して)この非マトリックスバージョン。

nrows, ncols = a.size, a.first.size 
    #=> [4, 4] 
row, col = a.flatten.index(1).divmod(ncols) 
    #=> [1, 2] 
Array.new(nrows*ncols) do |i| 
    r, c = i.divmod(ncols) 
    (c-col).abs + (r-row).abs <= 1 ? 1 : 0 
end.each_slice(ncols).to_a 
    #=> [[0, 0, 1, 0], 
    # [0, 1, 1, 1], 
    # [0, 0, 1, 0], 
    # [0, 0, 0, 0]] 

は、私はそれはのように効率的ではないかもしれないが、理解しやすいようにMatrixクラスを使用する方法を見つけます。

3

前のステップの干渉を避けるためには、配列を複製して参照配列を変更するか、関連するすべてのインデックスを抽出してから配列を変更することができます。後者はより良いです。また、フラットな配列を使用する方がネストされた配列を扱うよりはるかに簡単なので、aをフラット化された配列bとの間で変換し、bの範囲内で処理します。

b = a.flatten 

b 
.each_index.select{|i| b[i] == 1} 
.each do 
    |i| 
    b[i - 1] = 1 if b[i - 1] and i - 1 >= 0 
    b[i + 1] = 1 if b[i + 1] 
    b[i - 4] = 1 if b[i - 4] and i - 4 >= 0 
    b[i + 4] = 1 if b[i + 4] 
end 

a = b.each_slice(4).to_a 
# => [[0, 0, 1, 0], [0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]] 
+1

b [i-1]とb [i-4]のチェックは、あなたが望むとは思っていない配列の最後から1/4を返します。 –

+0

@FrederickCheungそれは私の間違いでした。指摘してくれてありがとう。 – sawa

関連する問題