3

任意の次元数の空間をまたぐ ruby​​ プログラムを書きたいです。

3 次元では、私がやっていることは次のようになります。

x_range = (-1..1)
y_range = (-1..1)
z_range = (-1..1)

step_size = 0.01

x_range.step(step_size) do |x|
  y_range.step(step_size) do |y|
    z_range.step(step_size) do |z|

      # do something with the point x,y,z

    end  
  end
end

n寸法についても同じことをしたい

4

5 に答える 5

2

これは私にとって最初に頭に浮かぶことです:

def enumerate(nDimens, bottom, top, step_size)
  bottom = (bottom / step_size).to_i
  top    = (top    / step_size).to_i

  range = (bottom..top).to_a.map{ |x| x * step_size }
  return range.repeated_permutation(nDimens)
end

stepper = enumerate(4, -1, 1, 0.1)

loop do
  puts "#{stepper.next()}"
end

これにより、次が生成されます。

[-1.0, -1.0, -1.0, -1.0]
[-1.0, -1.0, -1.0, -0.9]
[-1.0, -1.0, -1.0, -0.8]
# Lots more...
[1.0, 1.0, 1.0, 0.8]
[1.0, 1.0, 1.0, 0.9]
[1.0, 1.0, 1.0, 1.0]

これは、すべての次元が同じ範囲を持つことを前提としていますが、何らかの理由でそれが成り立たない場合は簡単に調整できます。

于 2012-08-06T05:02:42.120 に答える
1

再帰は、この種の問題を簡単かつ完全に解決できます。以下のコードは、任意の数の次元に適合し、さまざまな長さの範囲にも適合します。

def traversal(ranges, step_size, conjunction = [], &blk)
  ranges[0].step(step_size) do |x|
    conjunction.push(x)
    if ranges.size > 1
      traversal(ranges[1..-1], step_size, conjunction, &blk)
    else
      blk.call(conjunction) if block_given?
      conjunction.pop
    end
  end
  conjunction.pop
end

実行: (寸法 = 4、長さ = 3、3、4、2)

x = (1..3)
y = (4..6)
z = (7..10)
w = (100..101)
test_data = [x, y, z, w]
step_size = 1

traversal(test_data, step_size) do |x|
  puts "Point: #{x.join('-')}"
end

出力: (合計 72 ポイント、つまり 3 * 3 * 4 * 2)

Point: 1-4-7-100
Point: 1-4-7-101
Point: 1-4-8-100
Point: 1-4-8-101
Point: 1-4-9-100
Point: 1-4-9-101
Point: 1-4-10-100
Point: 1-4-10-101
Point: 1-5-7-100
Point: 1-5-7-101
Point: 1-5-8-100
Point: 1-5-8-101
Point: 1-5-9-100
Point: 1-5-9-101
Point: 1-5-10-100
Point: 1-5-10-101
Point: 1-6-7-100
Point: 1-6-7-101
Point: 1-6-8-100
Point: 1-6-8-101
Point: 1-6-9-100
Point: 1-6-9-101
Point: 1-6-10-100
Point: 1-6-10-101
Point: 2-4-7-100
Point: 2-4-7-101
Point: 2-4-8-100
Point: 2-4-8-101
Point: 2-4-9-100
Point: 2-4-9-101
Point: 2-4-10-100
Point: 2-4-10-101
Point: 2-5-7-100
Point: 2-5-7-101
Point: 2-5-8-100
Point: 2-5-8-101
Point: 2-5-9-100
Point: 2-5-9-101
Point: 2-5-10-100
Point: 2-5-10-101
Point: 2-6-7-100
Point: 2-6-7-101
Point: 2-6-8-100
Point: 2-6-8-101
Point: 2-6-9-100
Point: 2-6-9-101
Point: 2-6-10-100
Point: 2-6-10-101
Point: 3-4-7-100
Point: 3-4-7-101
Point: 3-4-8-100
Point: 3-4-8-101
Point: 3-4-9-100
Point: 3-4-9-101
Point: 3-4-10-100
Point: 3-4-10-101
Point: 3-5-7-100
Point: 3-5-7-101
Point: 3-5-8-100
Point: 3-5-8-101
Point: 3-5-9-100
Point: 3-5-9-101
Point: 3-5-10-100
Point: 3-5-10-101
Point: 3-6-7-100
Point: 3-6-7-101
Point: 3-6-8-100
Point: 3-6-8-101
Point: 3-6-9-100
Point: 3-6-9-101
Point: 3-6-10-100
Point: 3-6-10-101
于 2012-08-07T05:55:06.333 に答える
0

これはあなたができることです...これはイテレータの例です。

#next(l[dim] array of lower ranges ,h[dim] = upper ranges, step[dim], dim = dimensions -1, curr[dim] = current state in dim dimensions )
def nextx(l ,h, step, dim, curr)
    x = dim
    update= false
    while (update==false)
        if curr[x] == h[x]
            if x > 0
                x = x-1
            else
                exit
            end

        else
            curr[x]= curr[x]+step[x]
            while (x < dim)
                x = x+1
                curr[x] = l[x]  
            end
            update = true
        end
    end
    return curr
end


l = [0,0,0]
h = [3,3,3]
step = [1,1,1]
currx = [0,0,2]

i = 0
while i < 70
    currx = nextx(l, h, step, 2, currx)
    puts currx.inspect
    i=i+1
end
于 2012-08-06T09:47:43.893 に答える
0

範囲が大きすぎない場合は、次のようなことができます。

n = 5 # 5 dimentions
x = (-1..1).to_a
x.product(*[x]*(n-1)).each {|i| p i}

結果:

[-1, -1, -1, -1, -1]
[-1, -1, -1, -1, 0]
[-1, -1, -1, -1, 1]
[-1, -1, -1, 0, -1]
[-1, -1, -1, 0, 0]
[-1, -1, -1, 0, 1]
[-1, -1, -1, 1, -1]
[-1, -1, -1, 1, 0]
[-1, -1, -1, 1, 1]
[-1, -1, 0, -1, -1]
[-1, -1, 0, -1, 0]
# skipped
于 2012-08-06T04:26:33.933 に答える