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

如果范围不是太大,您可以执行以下操作:

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 回答
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

这通常在探索搜索空间的算法中遇到。循环从一维do范围创建产品空间。

首先将尽可能多的范围打包到一个数组中,例如

search_space_1Ds = [x_range.step(step_size).to_a, y_range.step(step_size).to_a, z_range.step(step_size).to_a]

那么以下将适用于任意数量的维度。

search_space = search_spaces_1Ds.shift.product(*search_space_1Ds)
search_space.map do |vec|
  # calculate something with vec
end

这个实现不仅简洁,而且非常清楚你的算法在做什么;通过创建为一维搜索空间的乘积空间的搜索空间进行枚举。

于 2018-12-06T23:02:18.567 回答