在PHP

时间:2017-06-12 08:42:07

标签: php

我需要从给定的数据集(n个数字)生成唯一的组合,每个组合包含r值。

基本上希望在PHP中实现C(n,r)=n!(r!(n−r)!)公式。

输入数据集{A,B,C,D},需要3个值的唯一组合,如下所示:

C(n,r)=C(4,3) = 4!/(3!(4−3)!)
= 4

ABC ACD BCD BDA

(CDA,CAB,BCA等是重复的,应该从输出中截断)。

但我的代码

<?php
function sampling($chars, $size, $combinations = array()) {

    # if it's the first iteration, the first set 
    # of combinations is the same as the set of characters
    if (empty($combinations)) {
        $combinations = $chars;
    }

    # we're done if we're at size 1
    if ($size == 1) {
        return $combinations;
    }

    # initialise array to put new values in
    $new_combinations = array();

    # loop through existing combinations and character set to create strings
    foreach ($combinations as $combination) {
        foreach ($chars as $char) {
            if($combination != $char)
            $new_combinations[] = $combination . $char;
        }
    }

    # call same function again for the next iteration
    return sampling($chars, $size - 1, $new_combinations);

}
?>

返回64个带有重复项的数组

  

{[0] =&gt; string(3)&#34; aaa&#34; [1] =&GT; string(3)&#34; aab&#34; [2] =&GT;字符串(3)&#34; aac&#34;   [3] =&GT; string(3)&#34; aad&#34; [4] =&GT; string(3)&#34; aba&#34; [5] =&GT; string(3)&#34; abb&#34;   [6] =&GT; string(3)&#34; abc&#34; [7] =&GT; string(3)&#34; abd&#34; [8] =&GT; string(3)&#34; aca&#34;   [9] =&GT; string(3)&#34; acb&#34; [10] =&GT; string(3)&#34; acc&#34; [11] =&GT; string(3)&#34; acd&#34;   [12] =&GT; string(3)&#34; ada&#34; [13] =&GT; string(3)&#34; adb&#34; [14] =&GT; string(3)&#34; adc&#34;   [15] =&GT; string(3)&#34; add&#34; [16] =&GT; string(3)&#34; baa&#34; [17] =&GT; string(3)&#34; bab&#34;   [18] =&GT; string(3)&#34; bac&#34; [19] =&GT; string(3)&#34; bad&#34; [20] =&GT; string(3)&#34; bba&#34;   [21] =&GT; string(3)&#34; bbb&#34; [22] =&GT; string(3)&#34; bbc&#34; [23] =&GT; string(3)&#34; bbd&#34;   [24] =&GT; string(3)&#34; bca&#34; [25] =&GT; string(3)&#34; bcb&#34; [26] =&GT; string(3)&#34; bcc&#34;   [27] =&GT; string(3)&#34; bcd&#34; [28] =&GT; string(3)&#34; bda&#34; [29] =&GT; string(3)&#34; bdb&#34;   [30] =&GT; string(3)&#34; bdc&#34; [31] =&GT; string(3)&#34; bdd&#34; [32] =&GT; string(3)&#34; caa&#34;   [33] =&GT; string(3)&#34; cab&#34; [34] =&GT; string(3)&#34; cac&#34; [35] =&GT; string(3)&#34; cad&#34;   [36] =&GT; string(3)&#34; cba&#34; [37] =&GT; string(3)&#34; cbb&#34; [38] =&GT; string(3)&#34; cbc&#34;   [39] =&GT; string(3)&#34; cbd&#34; [40] =&GT; string(3)&#34; cca&#34; [41] =&GT; string(3)&#34; ccb&#34;   [42] =&GT; string(3)&#34; ccc&#34; [43] =&GT; string(3)&#34; ccd&#34; [44] =&GT; string(3)&#34; cda&#34;   [45] =&GT; string(3)&#34; cdb&#34; [46] =&GT; string(3)&#34; cdc&#34; [47] =&GT; string(3)&#34; cdd&#34;   [48] =&GT; string(3)&#34; daa&#34; [49] =&GT; string(3)&#34; dab&#34; [50] =&GT; string(3)&#34; dac&#34;   [51] =&GT;字符串(3)&#34;爸爸&#34; [52] =&GT; string(3)&#34; dba&#34; [53] =&GT; string(3)&#34; dbb&#34;   [54] =&GT; string(3)&#34; dbc&#34; [55] =&GT; string(3)&#34; dbd&#34; [56] =&GT; string(3)&#34; dca&#34;   [57] =&GT; string(3)&#34; dcb&#34; [58] =&GT; string(3)&#34; dcc&#34; [59] =&GT; string(3)&#34; dcd&#34;   [60] =&GT; string(3)&#34; dda&#34; [61] =&GT; string(3)&#34; ddb&#34; [62] =&GT; string(3)&#34; ddc&#34;   [63] =&GT; string(3)&#34; ddd&#34; }

提前致谢!!!

2 个答案:

答案 0 :(得分:1)

假设您有一组4个项目,并且您想要其中3个项目的随机子集。您可以执行以下操作:

$myset = [ "A","B","C", "D" ];    

function randomSubset($set, $size) {
    $array = array_pad(array_pad([],$size,1),count($set),0); //Get an array like [ 1,1,1,0 ];
    shuffle($array);
    return array_intersect_key($set, array_filter($array));
 }

 print_r(randomSubset($myset,3));

在沙箱中查看:http://sandbox.onlinephpfunctions.com/code/a68f3b2f1abc285424ccadbaab8a12fc4928bb8d

现在,如果你需要大小为N的所有子集,你可以做一些递归魔术:

function allSubsets($set, $size) {     
    $subsets = [];
    if ($size == 1) {
        return array_map(function ($v) { return [$v]; },$set);
    }
    foreach (allSubsets($set,$size-1) as $subset) {
        foreach ($set as $element) {
            if (!in_array($element,$subset)) {
                $newSet = array_merge($subset,[$element]);
                sort($newSet);
                if (!in_array($newSet,$subsets)) {
                    $subsets[] = array_merge($subset,[$element]);
                }
            }
        }
    }
    return $subsets;

}

 $myset = [ "A","B","C", "D", "E" ];   
 print_r(allSubsets($myset,3));

沙盒:http://sandbox.onlinephpfunctions.com/code/01b55f0c1eb55ee82a67175d2551c164ffb2bf87

答案 1 :(得分:0)

这是一个从一组数字生成唯一组合的代码。

如果您有一组数字,例如1,3,4,7,12,则可以生成X个数字集,这些数字都是唯一的,没有重复。

第一个函数在PHP 7.4或更高版本中起作用,第二个函数使用键存储值。两者都基于基准运行良好。

function get_combos74($map, $size, &$generated = [], $loop = 1, $i = 0, $prefix = [])
{
    if ($loop == 1) {
        sort($map);
    }

    for (; $i < count($map); $i++) {
        if ($loop < $size) {
            get_combos74($map, $size, $generated, $loop + 1, $i + 1, [...$prefix, $map[$i]]);
        } else {
            $generated[] = [...$prefix, $map[$i]];
        }
    }

    return $generated;
}

function get_combosSTR($map, $size, &$generated = [], $loop = 1, $i = 0, $prefix = '')
{
    if ($loop == 1) {
        sort($map);
    }

    for (; $i < count($map); $i++) {
        if ($loop < $size) {
            get_combosSTR($map, $size, $generated, $loop + 1, $i + 1, "$prefix{$map[$i]}:");
        } else {
            $generated["$prefix{$map[$i]}"] = 0;
        }
    }

    return $generated;
}