PHP彩票复式排列组合算法

如下需求
需要将用户选择的01,02,03,04这4个号码按照两个数为一组的组合下注,并且按照顺序,每个组合不会因为大小顺序,重复出现多次
通过手工计算我们可以得到
["01", "02"],["01", "03"],["01", "04"],["02", "03"],["02", "04"],["03", "04"]
共计6个组合

像这种计算我们可以使用简单的for循环来实现组合

$checkedData = ["01","02","03","04"];
$boxData = [];
for ($i = 0; $i < count($checkedData); $i++) {
    $tempData = [$checkedData[$i]];
    foreach ($checkedData as $v) {
        if ($checkedData[$i] == $v) continue;
        $boxData[] = array_merge($tempData, [$v]);
    }
}
#输出结果
[
        ["01","02"],
        ["01","03"],
        ["01","04"],
        ["02","01"],
        ["02","03"],
        ["02","04"],
        ["03","01"],
        ["03","02"],
        ["03","04"],
        ["04","01"],
        ["04","02"],
        ["04","03"]
    ]

实际使用两个for循环会输出12种组合,这不是我们所需要的,因为每个数都出现了先后顺序重复

改良后的代码

$checkedData = ["01","02","03","04"];
$boxData = [];
for ($i = 0; $i < count($checkedData); $i++) {
    $tempData = [$checkedData[$i]];
    #每循环一次,就减去一个数组
    $bData = array_slice($checkedData, $i + 1);
    foreach ($bData as $v) {
        $boxData[] = array_merge($tempData, [$v]);
    }
}

#输出结果
[
    ["01","02"],
    ["01","03"],
    ["01","04"],
    ["02","03"],
    ["02","04"],
    ["03","04"]
]

嗯,没毛病,这就是我们想要的结果,想法是美好的,但现实却是扯淡的。
现在两个数为一组这个算法是写好了,但是呢,人类的脑袋壳子不知道是怎么搞得,总有各种想法和需求,强大到你无法想象
如什么连、什么串、什么全中不中的。。。

然后就出现了,需要3个、4个、5个、6个。。。n个数为一组的排列组合,这可怎么搞?按照上面的代码,两个数为一组需要嵌套两个循环,N个就要N个循环,那代码得写成啥样?

$checkedData = ["01","02","03","04"];
$boxData = [];
for ($i = 0; $i < count($checkedData); $i++) {
    $tempData = [$checkedData[$i]];
    #每循环一次,就减去一个数组
    $bData = array_slice($checkedData, $i + 1);
    foreach ($bData as $bk => $v) {
        $cData = array_slice($bData, $bk + 1);
        foreach ($cData ) {
           foreach ($dData ) {
               ...
           }
        }
    }
}

没错,如果按照组合个数不断增加这样的需要,就是多少个组合就要多少个循环,这些写肯定是不行的,这里我们就需要介绍下语言的递归操作了,就是调用方法本身,让其自成一个无限循环,直到处理结果返回

改良后的代码

function combination($data, $len){
        $boxData = [];
        $n = count($data);
        if ($len <= 0 || $len > $n) {
            return $boxData;
        }

        for ($i = 0; $i < $n; $i++) {
            $tempData = [$data[$i]];
            if ($len == 1) {
                $boxData[] = $tempData;
            } else {
                $b = array_slice($data, $i + 1);
                $c = combination($b, $len - 1);
                foreach ($c as $v) {
                    $boxData[] = array_merge($tempData, $v);
                }
            }
        }
        return $boxData;
}

$checkedData = ["01","02","03","04","05","06","07","08"];
$data = combination($checkedData,2);//两组
$data = combination($checkedData,3);//三组
以此类推......

还有一种需求

需要将[0,1,2],[2,3,4],[5,6,7],[7,8,9],[1,2,3,4,5]这样复杂的数组,拆分成3个、4个、5个数为每一组的不重复数据,像什么星啦、什么同不同号啦、什么胆啦,需要用到。
嗯,废话不多说了,主要是我感觉你应该懂了,直接上代码

#len为需要多少个数组合
function GetCombinationData($lists,$len = 5){

    //二维数组列表必须等于设定的len,否则不能组合
    if (count($lists) < $len) return false;

    $resLists = [];
    foreach ($lists as $k => $v) {
        $resLists = SetCombinationData($v);
    }

    return $resLists;
}

function SetCombinationData($val){

    //静态变量,保存上一个的值
    static $resLists = [];

    if (empty($resLists)) {
        $resLists = $val;
    }else{
        // 临时数组保存结合的结果
        $tempLists = [];

        //循环
        foreach ($resLists as $k => $v) {
            foreach ($val as $key => $value) {
                $tempLists[$k . '_' . $key] = $v . ',' . $value;
            }
        }
        $resLists = $tempLists;
    }
    return $resLists;
}

$checkedData = [[0,1,2],[2,3,4],[5,6,7],[7,8,9],[1,2,3,4,5]];
$result = GetCombinationData($checkedData,5);
var_dump($result);

你可能感兴趣的:(PHP彩票复式排列组合算法)