【发布时间】:2011-04-06 23:34:35
【问题描述】:
我正在寻找一个示例,说明如何在 Ruby、类似 C 的语言或伪代码中创建可变数量的整数数组的笛卡尔积,每个数组的长度不同,并逐步查看结果一个特定的顺序:
所以给定,[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.
而不是我看到的典型结果(包括我在下面给出的示例):
[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.
此示例的问题在于,在尝试了前两个位置的所有组合之前,根本不会探索第三个位置。在使用它的代码中,这意味着即使正确答案通常是(更大的等值)1、1、2,它也会检查几百万个可能性,而不是在找到它之前只检查几千个。
我正在处理一百万到数亿的结果集,因此在这里生成它们然后排序是不可行的,并且会破坏在第一个示例中对它们进行排序的原因,即更快地找到正确的答案所以更早地突破了笛卡尔积。
以防万一它有助于澄清上述任何内容,这就是我现在如何执行此操作(这具有正确的结果和正确的性能,但不是我想要的顺序,即它创建的结果如上面第二个列表所示):
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
更新: 我没有说得很清楚,我正在寻求一个解决方案,其中在添加 3 之前检查 1,2 的所有组合,然后是所有 3 和 1,然后是所有 3、2 和 1,然后是所有 3,2 .换句话说,在“垂直”之前“水平”探索所有早期的组合。探索这些可能性的确切顺序(即 1,1,2 或 2,1,1)无关紧要,只需在混合 3 之前探索所有 2 和 1,依此类推。
【问题讨论】:
-
我不确定你的算法。如果你“水平”地用尽组合,不是所有 3、2 都在所有 3、2、1 之前吗?
-
如果您的意思是 3,2,2 和 2,3,2 会在 3,2,1 之前出现,那么不,不是我更喜欢它的工作方式。但是您的订单会比 1,1,1 2,1,1, 3,1,1, 1,2,1, 1,3,1 等要好得多。我想要摆脱的是第一列中的每个值都被尝试过,然后第二列中的每个值都被尝试过——这意味着最后一列甚至没有前进一个位置,直到进入序列的很远(因此在我正在使用的几百万次毫无意义的迭代之后。 )
标签: ruby algorithm cartesian-product