私は2次元配列を持っています
0 0 0 0 0
0 2 3 4 0
0 9 1 5 0
0 8 7 6 0
0 0 0 0 0
そして、1に隣接するすべての数値を取得する必要があります(2、3、4、5、6、7、8、9)。
以下よりも醜い解決策はありますか?
topLeft = array[x-1][y-1]
top = array[x][y-1]
topRight = array[x+1][y-1]
# etc
ありがとう!
順序について心配していない場合は、おそらくいくつかのループを使用するのが最もクリーンです。
result = new List<int>(8);
for (dx = -1; dx <= 1; ++dx) {
for (dy = -1; dy <= 1; ++dy) {
if (dx != 0 || dy != 0) {
result.Add(array[x + dx][y + dy]);
}
}
}
順序が重要な場合は、すべての(dx、dy)のリストを必要な順序で作成し、代わりにそれを繰り返すことができます。
コメントで指摘されているように、おそらく境界チェックを追加する必要があります。これは次のように行うことができます(順序は重要ではないと想定)。
List<int> result = new List<int>(8);
for (int dx = (x > 0 ? -1 : 0); dx <= (x < max_x ? 1 : 0); ++dx)
{
for (int dy = (y > 0 ? -1 : 0); dy <= (y < max_y ? 1 : 0); ++dy)
{
if (dx != 0 || dy != 0)
{
result.Add(array[x + dx][y + dy]);
}
}
}
私はおそらく次のように、dx、各方向のdyの定数リストを求めます。
_struct {
int dx;
int dy;
} directions[] = {{-1,-1,},{-1,0,},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
_
次に、単純なループを使用して方向を繰り返します。
_for (int i = 0; i < 8; i++) {
// use x + directions[i].dx;
// use y + directions[i].dy;
}
_
もちろん、上記の_8
_の代わりにsizeof(directions) / sizeof(directions[1])
を使用することもできます。
個人的には、ループはオリジナルよりも醜いです。
topLeft = array[ x - 1 ][ y - 1 ]
top = array[ x ][ y - 1 ]
topRight = array[ x + 1 ][ y - 1 ]
midLeft = array[ x - 1 ][ y ]
midRight = array[ x + 1 ][ y ]
botLeft = array[ x - 1 ][ y + 1 ]
bot = array[ x ][ y + 1 ]
botRight = array[ x + 1 ][ y + 1 ]
ただし、値を何に使用するかを指定しないと、さまざまな方向で何をするかによって、値を別々の変数に含めるかどうかが決まります。
ゲームオブライフスタイルの処理では、通常、個別の値の配列ではなくビットパターンで作業する必要があり、アキュムレータと一時変数を使用して一度に8つのセルのうち3つだけを水平方向に検査してスキャンできます。グラフィック畳み込みの場合は、3x3カーネルを備えた既存のライブラリを使用します。
境界を処理するもう1つの方法は、配列を各方向に1セルずつ拡張することです。これにより、畳み込みコードの高価な分岐が回避されます。
C++
これは次のようになります。
vector<int> adj;
for (int i = 0; i < 9; i++)
if (i != 4) adj.Push_back(array[x + i/3 - 1][y + i%3 - 1]);
これは非常に明確な解決策ではありませんが、非常に短いものです。
指定されたマトリックス内の隣接ノードを取得するPythonジェネレーター
def gen_adjacent_node(matrix_2d, node=(0,0)):
rows = len(matrix_2d)
columns = len(matrix_2d[0])
for r in [-1, 0, 1]:
for c in [-1, 0, 1]:
if r == c == 0:
continue
# check valid index
if 0 <= node[0]+r < rows and 0 <= node[1]+c < columns:
# print((node[0]+i, node[1]+j))
yield (node[0]+r, node[1]+c)
ここにRubyソリューションがあります。Rubyに精通していない読者でもアルゴリズムは明白です。反復される行と列を計算した方法に注意してください(これは次のように記述されます)ほとんどの言語)。これは、たとえば、反復する行のインデックスの「max(r-1, 0)
からmin(r+1, arr.size-1)
へ」よりもはるかにクリーンに思えます。
def adjacent(arr, r, c)
rows_ndx = arr.each_index.select { |i| (i-r).abs < 2 }
cols_ndx = arr.first.size.times.select { |j| (j-c).abs < 2 }
rows_ndx.each_with_object([]) do |i,a|
cols_ndx.each { |j| a << arr[i][j] unless [i,j] == [r,c] }
end
end
arr = [
[-1, 2, 3, 4],
[-2, 9, 1, 5],
[-3, 8, 7, 6],
[-4, -5, -6, -7]
]
(0..2).each do |i|
(0..3).each do |j|
puts "adjacent to #{arr[i][j]} at r=#{i}, c=#{j} = #{adjacent(arr, i, j)}"
end
end
プリント
adjacent to -1 at r=0, c=0 = [2, -2, 9]
adjacent to 2 at r=0, c=1 = [-1, 3, -2, 9, 1]
adjacent to 3 at r=0, c=2 = [2, 4, 9, 1, 5]
adjacent to 4 at r=0, c=3 = [3, 1, 5]
adjacent to -2 at r=1, c=0 = [-1, 2, 9, -3, 8]
adjacent to 9 at r=1, c=1 = [-1, 2, 3, -2, 1, -3, 8, 7]
adjacent to 1 at r=1, c=2 = [2, 3, 4, 9, 5, 8, 7, 6]
adjacent to 5 at r=1, c=3 = [3, 4, 1, 7, 6]
adjacent to -3 at r=2, c=0 = [-2, 9, 8, -4, -5]
adjacent to 8 at r=2, c=1 = [-2, 9, 1, -3, 7, -4, -5, -6]
adjacent to 7 at r=2, c=2 = [9, 1, 5, 8, 6, -5, -6, -7]
adjacent to 6 at r=2, c=3 = [1, 5, 7, -6, -7]