查找具有良好顺序的唯一组合


PHP Find unique combinations with the good order

我在后台做一份选择题问卷。对于一个问题,你可以有两种类型的答案:强制性的和可选的。棘手的部分是关于可选答案。

例如:你有4个可选的答案"c||b||a| d"。首先,我需要对它们进行排序以限制解决方案的数量,所以我有:"a||b||c||d"(这部分还可以,只需要排序;))

现在,这是我需要的解决方案:

a
b
c
d
--------
a+b
a+c
a+d
b+c
b+d
c+d
--------
a+b+c
a+b+d
a+c+d
b+c+d
--------
a+b+c+d 

目前,我所尝试的是:

$listIdOptionnal = array('a', 'b', 'c', 'd');
$tmpListMatrice = array();
//lette courante
for($i = 0; $i < sizeof($listIdOptionnal); $i++) 
{
    $tmpListMatrice[] = $listIdOptionnal[$i];
    //position suivante
    for($j = $i+1; $j < sizeof($listIdOptionnal); $j++)
    {
        //$tmpListMatrice[] = $listIdOptionnal[$i].','.$listIdOptionnal[$j];
        //Longueur
        for($k = 1; $k < sizeof($listIdOptionnal); $k++)
        {
            $tmp = array_slice($listIdOptionnal, $j, $k);
            $tmpListMatrice[] = $listIdOptionnal[$i].','.implode(',', $tmp);
        }
    }
}
$tmpListMatrice = array_unique($tmpListMatrice);
var_dump($tmpListMatrice);exit;

我当前的结果:

array(14) {
  [0]=>
  string(1) "a"
  [1]=>
  string(3) "a,b"
  [2]=>
  string(5) "a,b,c"
  [3]=>
  string(7) "a,b,c,d"
  [4]=>
  string(3) "a,c"
  [5]=>
  string(5) "a,c,d"
  [7]=>
  string(3) "a,d"
  [10]=>
  string(1) "b"
  [11]=>
  string(3) "b,c"
  [12]=>
  string(5) "b,c,d"
  [14]=>
  string(3) "b,d"
  [17]=>
  string(1) "c"
  [18]=>
  string(3) "c,d"
  [21]=>
  string(1) "d"
}

正如你所看到的,我的解决方案不是很好,因为这里缺少"a, b, d"

试试这个:

$array = array('a', 'b', 'c', 'd');
$cnt  = count($array);
$return = array();
for($i = 1; $i < (1 << $cnt); $i++) {
    $str = '';
    for($j = 0; $j < $cnt; $j++)
        if($i & (1 << $j))
            $str .= $array[$j] . ',';
    $return[] = $str;
}
foreach ($return as $key=>$elmt)
    $return[$key] = substr($elmt, 0, -1);
var_dump($return);

输出:

array (size=15)
  0 => string 'a' (length=1)
  1 => string 'b' (length=1)
  2 => string 'a,b' (length=3)
  3 => string 'c' (length=1)
  4 => string 'a,c' (length=3)
  5 => string 'b,c' (length=3)
  6 => string 'a,b,c' (length=5)
  7 => string 'd' (length=1)
  8 => string 'a,d' (length=3)
  9 => string 'b,d' (length=3)
  10 => string 'a,b,d' (length=5)
  11 => string 'c,d' (length=3)
  12 => string 'a,c,d' (length=5)
  13 => string 'b,c,d' (length=5)
  14 => string 'a,b,c,d' (length=7)

这是我的长版本,

// create new combination
function createCombo($combo, $key){
    $combo = explode(",", $combo);
    $combo[] = $key;
    sort($combo); 
    return implode(",", $combo);
}
// Recursive function
function getCombos($combos, $keys, $repeat) {
    foreach ($combos as $combo){
        foreach ($keys as $key){
            // key exists in current combination => skip
            if (strpos($combo, $key) !== false) continue;
            // create new combination
            $new = createCombo($combo, $key);
            // combination exists => skip
            if (in_array($new, $combos)) continue;
            // combination not exists => add
            $combos[] = $new; 
        }
    }
    if (!$repeat--) return $combos;
    return getCombos($combos, $keys, $repeat);
}
$keys = array('a','b','c','d');
$combos = getCombos($keys, $keys, count($keys));