问题描述
我在找的怎么样,在Ruby中,如语言,或伪code A C,创建不同数量的整数数组,每个不同长度的笛卡尔乘积为例,步结果以特定的顺序:
I'm looking for an example of how, in Ruby, a C like language, or pseudo code, to create the Cartesian product of a variable number of arrays of integers, each of differing length, and step through the results in a particular order:
于是给定,[1,2,3],[1,2,3],[1,2,3]:
So given, [1,2,3],[1,2,3],[1,2,3]:
[1, 1, 1]
[2, 1, 1]
[1, 2, 1]
[1, 1, 2]
[2, 2, 1]
[1, 2, 2]
[2, 1, 2]
[2, 2, 2]
[3, 1, 1]
[1, 3, 1]
etc.
而不是典型的结果,我已经看到了(包括例子,我在下面提供):
Instead of the typical result I've seen (including the example I give below):
[1, 1, 1]
[2, 1, 1]
[3, 1, 1]
[1, 2, 1]
[2, 2, 1]
[3, 2, 1]
[1, 3, 1]
[2, 3, 1]
etc.
与本例中的问题是,所述第三位置是没有探讨在所有直到前两个的所有组合都试过。在使用这个code,这意味着即使正确答案一般是(大得多当量)1,1,2-发现它之前,只有几千会检查数百万的可能性,而不是。
The problem with this example is that the third position isn't explored at all until all combinations of of the first two are tried. In the code that uses this, that means even though the right answer is generally (the much larger equivalent of) 1,1,2 it will examine a few million possibilities instead of just a few thousand before finding it.
我处理一百万到数以百万计的结果集,因此产生他们,然后排序是不可行这里会破坏原因,命令他们在第一个例子,这是找到正确的答案越快所以打出来的笛卡尔积代早期。
I'm dealing with result sets of one million to hundreds of millions, so generating them and then sorting isn't doable here and would defeat the reason for ordering them in the first example, which is to find the correct answer sooner and so break out of the cartesian product generation earlier.
以防万一它有助于澄清上述任何一项,这里就是我这样做了(这有正确的结果和正确的业绩,但不是我想要的顺序,也就是说,它作为第二上市上面创建的结果):
Just in case it helps clarify any of the above, here's how I do this now (this has correct results and right performance, but not the order I want, i.e., it creates results as in the second listing above):
def cartesian(a_of_a)
a_of_a_len = a_of_a.size
result = Array.new(a_of_a_len)
j, k, a2, a2_len = nil, nil, nil, nil
i = 0
while 1 do
j, k = i, 0
while k < a_of_a_len
a2 = a_of_a[k]
a2_len = a2.size
result[k] = a2[j % a2_len]
j /= a2_len
k += 1
end
return if j > 0
yield result
i += 1
end
end
更新:我没有说得很清楚,我是一个解决方案,其中的1,2所有组合3之前被检查的加入,则所有3个和1个,然后所有3个,2个和1个后,那么所有3,2 。换句话说,在探索所有早期组合水平,垂直。在precise顺序的可能性进行了探讨,即1,1,2或2,1,1,无所谓,只是所有的2和1/3的混合等之前进行了探讨。
UPDATE:I didn't make it very clear that I'm after a solution where all the combinations of 1,2 are examined before 3 is added in, then all 3 and 1, then all 3, 2 and 1, then all 3,2. In other words, explore all earlier combinations "horizontally" before "vertically." The precise order in which those possibilities are explored, i.e., 1,1,2 or 2,1,1, doesn't matter, just that all 2 and 1 are explored before mixing in 3 and so on.
推荐答案
之后,precision的问题,这里有一个修订版。我保持了previous的答案,因为它可能是有用的太多,并且使用一个不太复杂的订单。
After the precision in the question, here's a revised version. I'm keeping the previous answer since it can be useful too and uses a less complex order.
# yields the possible cartesian products of [first, *rest], where the total
# of the indices that are "distributed" is exactly +nb+ and each index doesn't
# go beyong +depth+, but at least one of them is exactly +depth+
def distribute(nb, depth, reached, first, *rest)
from = [nb - rest.size * depth, 0].max
to = [first.size-1, depth, nb].min
from.upto(to) do |i|
obj = first[i]
reached ||= i == depth
if rest.empty?
yield [obj] if reached
else
distribute(nb - i, depth, reached, *rest) do |comb|
yield [obj, *comb]
end
end
end
end
def depth_first_cartesian(*arrays)
return to_enum __method__, *arrays unless block_given?
lengths = arrays.map(&:length)
total = lengths.inject(:+)
lengths.max.times do |depth|
depth.upto(arrays.size * depth) do |nb|
distribute(nb, depth, false, *arrays) {|c| yield c}
end
end
end
p depth_first_cartesian([1, 2, 3], [1, 2, 3, 4], [1, 2, 3]).to_a
# => [[1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [1, 2, 2], [2, 1, 2], [2, 2, 1], [2, 2, 2],
# [1, 1, 3], [1, 3, 1], [3, 1, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2],
# [3, 2, 1], [1, 3, 3], [2, 2, 3], [2, 3, 2], [3, 1, 3], [3, 2, 2], [3, 3, 1], [2, 3, 3],
# [3, 2, 3], [3, 3, 2], [3, 3, 3], [1, 4, 1], [1, 4, 2], [2, 4, 1], [1, 4, 3], [2, 4, 2],
# [3, 4, 1], [2, 4, 3], [3, 4, 2], [3, 4, 3]]
这篇关于算法产生阵列的笛卡儿积在深度优先顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!