2016-03-15 102 views
-1

情况:有5个问题有多个可能的答案。四个问题可以有一个或多个答案的答案。任何问题都无法回答。查找数组值的每个可能的排列组合

我想制定出这些答案的每一个可能的组合。

我认为这不是this的重复,因为它涉及单个字符或数字的可能排列。


我相信这个例子会产生像230,400种可能的排列

$questions = array(
    "q1" => array(
     "1a", 
     "1b", 
     "1c" 
    ), 
    "q2" => array(
     "2a", 
     "2b", 
     "2c", 
     "2d" 
    ), 
    "q3" => array(
     "3a", 
     "3b", 
     "3c" 
    ), 
    "q4" => array(// this question can have any number of these answers selected, or none 
     "4a", 
     "4b", 
     "4c", 
     "4d", 
     "4e", 
     "4f" 
    ), 
    "q5" => array(
     "5a", 
     "5b", 
     "5c" 
    ) 
); 
+0

为什么你需要PHP来完成这项任务?如果不是,有什么变数? – Callidior

+0

不需要是PHP,可以是Python或其他。但是,问题和答案的数量是动态的,因此它不是固定的。 –

+0

好的,除了评论之外,你给出的数组表示并不能确定某个特定问题是否只有一个或多个答案。这是计算可能答案组合总数的必要信息。你对这个数字感兴趣吗?还是你自己需要所有可能的组合? – Callidior

回答

0

我希望我有你的问题的权利,而这答案似乎对你有帮助...

初始条件

除了你的例子,我们来介绍第二个数组,其中包含哪些问题可能有多个答案:

$multi_questions = array('q4'); 

这将告诉我们的算法在下面描述的问题4可能有任何数量的答案选择,而所有问题可能只有一个答案或根本没有答案。

的答案

的集合中选择用于特定问题的答案的可能的组合数是独立于任何其他问题。对于总数为n可能的答案和最多1个选定答案的问题,该问题可能的选择数量为n+1。如果问题允许选择多个答案,则有2^n这个问题的可能组合(每个答案有两个选项:选择或不选择)。

在您的示例中,这会导致所选答案的可能组合总数为4 * 5 * 4 * 2^6 * 4 = 20480。这个数字可以计算就像如下:

$combinations = 1; 
foreach ($questions as $q => $answers) 
{ 
    if (in_array($q, $multi_questions)) 
     $combinations *= 1 << count($answers); 
    else 
     $combinations *= count($answers) + 1; 
} 

遍历答案

的所有可能的组合,如果你不仅是在回答的组合的数量感兴趣,但要产生所有这些,你可以使用算法如下。对于具有多个可能答案的问题,它将以二进制数形式给出的一组答案进行编码。这意味着,号码001010将代表答案集['4c','4e']

$q_keys = array_keys($questions); 

// Start with no answer selected for any question 
$answer_set = array(); 
$q_max = array(); 
for ($i = 0; $i < count($q_keys); $i++) 
{ 
    $answer_set[$i] = 0; 
    $q_max[$i] = (in_array($q_keys[$i], $multi_questions)) 
       ? (1 << count($questions[$q_keys[$i]])) - 1 
       : count($questions[$q_keys[$i]]); 
} 

// Iterate over all combinations of answers 
while ($answer_set[0] <= $q_max[0]) 
{ 

    // Decode answer set to array of selected answers for each question 
    $answers = array(); 
    for ($i = 0; $i < count($q_keys); $i++) 
    { 
     if (in_array($q_keys[$i], $multi_questions)) 
     { 
      $answers[$q_keys[$i]] = array(); 
      for ($a = 0; $a < count($questions[$q_keys[$i]]); $a++) 
       if (($answer_set[$i] & (1 << $a)) != 0) // Is the bit corresponding to answer no. $a set? 
        $answers[$q_keys[$i]][] = $questions[$q_keys[$i]][$a]; 
     } 
     else 
      $answers[$q_keys[$i]] = ($answer_set[$i] > 0) 
            ? array($questions[$q_keys[$i]][$answer_set[$i] - 1]) 
            : array(); // Encode no answer as empty array 
    } 

    // Do something with the array of answers for each question ($answers) 
    // ... 

    // Forward the answer set 
    for ($i = count($q_keys) - 1; $i >= 0; $i--) 
    { 
     if (++$answer_set[$i] > $q_max[$i] && $i > 0) 
      $answer_set[$i] = 0; 
     else 
      break; 
    } 

}