如何从笛卡尔积中选择特定项目而不计算其他项目

时间:2012-03-30 14:27:41

标签: algorithm perl math cartesian-product cross-product

我最终确信这个问题有一个答案,但是因为我的生活无法弄清楚如何去做。

假设我有三套:

A = [ 'foo', 'bar', 'baz', 'bah' ]
B = [ 'wibble', 'wobble', 'weeble' ]
C = [ 'nip', 'nop' ]

而且我知道如何计算笛卡尔/十字架产品,(蚂蚁它覆盖了整个地方,在这个网站和其他地方)所以我不会在这里讨论它。

我正在寻找的是一种算法,它允许我简单地从笛卡尔积中选择一个特定项目而不用生成整个集合或迭代直到我到达第n个项目。

当然,我可以轻松地迭代一个这样的小例子集,但我正在处理的代码将使用更大的集合。

因此,我正在寻找一个功能,我们称之为'CP',其中:

CP(1) == [ 'foo', 'wibble', 'nip' ]
CP(2) == [ 'foo', 'wibble', 'nop' ]
CP(3) == [ 'foo', 'wobble', 'nip' ]
CP(4) == [ 'foo', 'wobble', 'nop' ]
CP(5) == [ 'foo', 'weeble', 'nip' ]
CP(6) == [ 'foo', 'weeble', 'nop' ]
CP(7) == [ 'bar', 'wibble', 'nip' ]
...
CP(22) == [ 'bah', 'weeble', 'nop' ]
CP(23) == [ 'bah', 'wobble', 'nip' ]
CP(24) == [ 'bah', 'wobble', 'nop' ]

答案是在O(1)时间内产生的,或多或少。

我一直在想着它应该是可能的,(哎呀,甚至简单!)来计算我想要的A,B,C元素的索引,然后简单地从原始数组中返回它们,但到目前为止,我试图使这项工作正确,嗯,没有用。

我在Perl编码,但我可以轻松地从Python,JavaScript或Java(可能还有其他几个)中移植一个解决方案

3 个答案:

答案 0 :(得分:25)

可能的组合数量由

给出
N = size(A) * size(B) * size(C)

您可以通过索引i为所有项目编制索引,范围从0N(不包括)

c(i) = [A[i_a], B[i_b], C[i_c]]

,其中

i_a = i/(size(B)*size(C)) 
i_b = (i/size(C)) mod size(B)
i_c = i mod size(C)

(假设所有集合都是可索引的,从零开始,/是整数除法。)

为了得到你的例子,你可以将索引移动1。

答案 1 :(得分:0)

我制作了霍华德答案的python版本。如果您认为可以改进,请告诉我。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="inputLat">Latitude</label>
<br>
<input type="text" id="inputLat" placeholder="-90° to +90°">
<br>
<button type="button" id="sendButton">Send</button>

答案 2 :(得分:0)

以下是基于 Howard 回答的较短 Python 代码:

import functools
import operator
import itertools

def nth_product(n, *iterables):
    sizes = [len(iterable) for iterable in iterables]
    indices = [
        int((n/functools.reduce(operator.mul, sizes[i+1:], 1)) % sizes[i])
        for i in range(len(sizes))]
    return tuple(iterables[i][idx] for i, idx in enumerate(indices))