I hope I've got your question right and that this answer seems helpful to you...
Initial conditions
In addition to your example, let's introduce a second array with information about which question(s) may have multiple answers:
$multi_questions = array('q4');
This would tell our algorithm described in the following that question 4 may have any number of answers selected, while all over questions may only have a single or no answer at all.
Number of possible combinations of answers
The set of answers selected for a specific question is independent from any other question. For a question with a total number of n
possible answers and maximum of 1 selected answer, the number of possible selections for that question is n+1
. If the question allows the selection of multiple answers, there are 2^n
possible combinations for that question (each answer has two options: chosen or not chosen).
In your example, this leads to a total number of 4 * 5 * 4 * 2^6 * 4 = 20480
possible combinations of selected answers. This number can be computed like follows:
$combinations = 1;
foreach ($questions as $q => $answers)
{
if (in_array($q, $multi_questions))
$combinations *= 1 << count($answers);
else
$combinations *= count($answers) + 1;
}
Iterating over all possible combinations of answers
If you are not only interested in the number of answer combinations, but want to generate them all, you can use an algorithm like the following. For the questions with more than one possible answer, it encodes the set of answers given as binary number. That means, the number 001010
would represent the answer set ['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;
}
}