生成所有可能的组合

法比奥

我有一个应用程序,用户可以通过从菜单中选择选项来定制要购买的产品。该菜单有很多部分,每个部分可能都有一个用于多选的复选框或单选按钮(如果只能选择一个选项)的列表。用户必须在每个部分中至少选择一个选项。菜单结构如下所示:

$sections = array();

$sections[1] = array(
    'multichoice' => true,
    'options' => array('A','B','C')
);

$sections[2] = array(
    'multichoice' => false,
    'options' => array('A','B','C','D')
);

$sections[3] = array(
    'multichoice' => false,
    'options' => array('A','B')
);

$sections[4] = array(
    'multichoice' => true,
    'options' => array('A','B','C','D','E')
);

示例:三明治是产品。面包类型是一种选择。您可能需要浅面包,黑面包,牛奶面包或纯素食面包。在此部分下只能选择一个选项。现在,在“沙拉”部分中,您可以选择多种沙拉来添加到面包中。

现在,我的老板要求我创建一个页面,列出所有可能的组合,以防用户懒得自己构建产品。所以我必须能够生成这样的结构:

$combinations = array(
    array(
        1 => array('A','B'),
        2 => 'A',
        3 => 'A',
        4 => array('B','D','E')
    ),
    array(
        1 => array('A'),
        2 => 'B',
        3 => 'A',
        4 => array('A','B')
    )
// etc...
);

我设法使用随机方法找到了所有可能的组合,生成了与已生成内容进行比较的散列。这实际上有效,但运行速度非常慢(基本上是蛮力):

...

function generate(){
    $result = array();
    $ids = array();
    foreach($this->getSections() as $sect){
        $items = $this->getSectionOptions($sect['id']);
        if($sect['multi']=='N'){
            $item = $items[rand(0, count($items)-1)];
            $result[$sect['id']] = $item['id'];
            $ids[] = $item['id'];
        } else {
            $how_many = rand(1,count($items));
            shuffle($items);
            for($i=1;$i<=$how_many;$i++){
                $item = array_shift($items);
                $result[$sect['id']][] = $item['id'];
                $ids[] = $item['id'];
            }
        }
    }
    sort($ids);
    return array(
        'hash' => implode(',',$ids),
        'items' => $result
    );
}

function generateMany($attempts=1000){
    $result = array();
    $hashes = array();
    for($i=1;$i<=$attempts;$i++){
        $combine = $this->generate();
        if(!in_array($combine['hash'],$hashes)){
            $result[] = $combine['items'];
            $hashes[] = $combine['hash'];
        }
    }
    return $result;
}


...

我希望您能帮助您创建更精确,更快捷的工具。请记住,每个组合的每个部分必须至少有一个选项。还请记住,多选部分中的选项顺序是无关紧要的(即E,B,A与B,E,A相同)

谢谢

米洛雷罗

谢谢,这是一个非常有趣的难题!

那么我怎么解决,递归递归递归:D

我从多种选择开始,因为这是最困难的选择!(实际上它将解决混合问题)

说明

为了说明我是如何工作的,让我们以选择A,B,C的示例为例。然后,我们将获得以下组合:

A B
A B C
A C
B
B C
C

如果我们仔细观察,我们可以看到一些模式。让结果列表作为第一个元素(A)

B
B C
C
---
B
B C
C

嗯,很有趣...现在让我们再次获取第一个元素(B)

C
---
C

这是一个简单的情况,但是在任何大小的情况下都会发生。

因此,我将递归脚本制作到了最后,然后向后添加了迭代组合,并将其与先前的值复制在一起。

瞧!就是这个!

对于需要所有元素的最终混合,我做了一个非常相似的方法,但是每个元素必须包含1个元素

而且速度非常快!

使用126种组合进行100000次迭代的总时间:14.410287857056秒

如果您发现任何错误ping me:D

https://gist.github.com/MLoureiro/a0ecd1ef477e08b6b83a

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章