用于获取y个不同容器中x个不同项目的组合的PHP资源?

时间:2018-07-10 03:27:39

标签: php math combinations

有人知道某种资源(手册或书籍),或者有PHP解决方案来获取y个不同的箱中x个不同的项的所有组合吗? 例如,如果我有2个物品[1、2]和2个垃圾箱,则4种可能性将是:

[ 1,2 ] [ ] [ 1 ] [ 2 ] [ 2 ] [ 1 ] [ ] [ 1,2 ]

我需要组合而不是排列,因为项的顺序是irelevent。箱中没有物品的最小/最大。如果由于不清楚您要降级我的问题,请指出您的困惑。我整天都在努力寻找解决方案,即使是使用另一种编程语言也是如此。显然,提出来不是很容易。

更新:您好,Karol,感谢您的评论和链接。我仍然在解决这个问题,并确实在搜索中找到了该页面并将其转换为PHP:

function combinationsOf($k, $xs){
if ($k === 0)
    return array(array());
if (count($xs) === 0)
    return array();
$x = $xs[0];
$xs1 = array_slice($xs,1,count($xs)-1);
$res1 = combinationsOf($k-1,$xs1);
for ($i = 0; $i < count($res1); $i++) {
    array_splice($res1[$i], 0, 0, $x);
}
$res2 = combinationsOf($k,$xs1);
return array_merge($res1, $res2); }

我要用的方式与我最初希望的方式不同,所以仍然希望能听到某人的声音……谢谢!

更新:因此,我在利用上面的递归函数以及我发现的另一个链接方面取得了进步:Permutation Of Multidimensional Array in PHP 虽然,如果我错了(这是一个漫长的日子),请纠正我,但这不是排列,而是组合,这是在这里生成的。

1 个答案:

答案 0 :(得分:2)

您可以使用利用递归的backtracking方法。基本上,这就像一种“智能强力”方法,它采用了一条路径并试图获得有效的组合。

该解决方案可能看起来有点大,但其中的大多数功能仅用于支持combo功能。该算法的主要大脑位于combo函数的后面,该函数创建组合。其余的功能在那里都支持combo功能并打印出美观的输出。

<?php
function toPlainArray($arr2) {
    $output = "[";
    foreach($arr2 as $arr) {
        $output .= "[";
        foreach($arr as $val) {
            $output .= $val . ", ";
        }
        if($arr != []) {
            $output = substr($output, 0, -2) . "], ";
        } else {
            $output .= "], ";
        }   
    }
    return substr($output, 0, -2) . "]";
}

function difference($arr2d, $arr1d) {
    foreach((array)$arr2d as $arr) {
        foreach($arr as $item) {
            if(in_array($item, $arr1d)) {
                $index = array_search($item, $arr1d);
                unset($arr1d[$index]);
            }
        }
    }

    return $arr1d;
}

function getNextPossibleSol($pSol, $item) { // returns an array (1d)
    $allItems = range(1, $item);
    return difference($pSol, $allItems); 
}

function createEmpty2dArray($arr, $amount) {
    for($i = 0; $i < $amount; $i++) {
        $arr[] = [];
    }
    return $arr;
}


function isSmallerThenPartialItems($item, $pSol) {
    foreach($pSol as $arr) {
        foreach($arr as $val) {
            if($val > $item) return false;
        }
    }

    return true;
}

function combo($items, $buckets, $partialSol=[]) {
     if($partialSol == []) { // Starting empty array, populate empty array with other arrays (ie create empty buckets to fill)
         $partialSol = createEmpty2dArray($partialSol, $buckets);
     }

    $nextPossibleSol = getNextPossibleSol($partialSol, $items);

    if($nextPossibleSol == []) { // base case: solution found
        echo toPlainArray($partialSol); // 2d array
        echo "<br /><br />";
    } else {
        foreach($nextPossibleSol as $item) {
            for($i = 0; $i < count($partialSol); $i++) {
                if(isSmallerThenPartialItems($item, $partialSol)) { // as order doesn't matter, we can use this if-statement to remove duplicates
                    $partialSol[$i][] = $item;
                    combo($items, $buckets, $partialSol);
                    array_pop($partialSol[$i]);
                }
            }  
        }
    }
}

combo(2, 2); // call the combinations functions with 2 items and 2 buckets

?>

输出:

[[1, 2], []]

[[1], [2]]

[[2], [1]]

[[], [1, 2]]