array_sum($numbers)) {
$GLOBALS['calsTotal']++;
return $GLOBALS['resultsOutput'];
}
//--------------------------------------------------
// Run
$usedNumbers = array();
numberAdditionsSub($numbers, $goal, $usedNumbers);
//--------------------------------------------------
// Return
return $GLOBALS['resultsOutput'];
}
function numberAdditionsSub($numbers, $goal, $usedNumbers) {
foreach ($numbers as $cNumber) { // A local copy of $numbers is made, so not effected by the array_shift()
//--------------------------------------------------
// Stats
$GLOBALS['calsTotal']++;
//--------------------------------------------------
// New usedNumbers array, and calculate its "sum"
$newUsedNumbers = $usedNumbers;
array_push($newUsedNumbers, $cNumber); // Faster than array_merge
$sum = array_sum($newUsedNumbers);
//--------------------------------------------------
// Remove this number from the array of newNumbers.
//
// So firstly, when we descend into the next set
// of numbers, we don't want this number to be
// used again... and secondly, during the first
// loop (at this level), we will go though every
// combination of (remaining) children, but on
// the second loop we do not need to include the
// first number again, as it has already been used
// in every combination before hand.
//
// e.g.
// 1) A
// 2) A + B
// 3) A + B + C
// 4) A + C
// 5) A + C + B -- Dupe of 3
// 6) B
// 7) B + A -- Dupe of 2
// 8) B + A + C -- Dupe of 3
// 9) B + C
// 10) B + C + A -- Dupe of 3
// 11) C
// 12) C + A -- Dupe of 2
// 13) C + A + B -- Dupe of 3
// 14) C + B -- Dupe of 9
// 15) C + B + A -- Dupe of 3
array_shift($numbers);
//--------------------------------------------------
// Sum matches
if ($goal !== NULL && $sum == $goal) {
//--------------------------------------------------
// Match
$GLOBALS['resultsOutput'][] = implode(' + ', $newUsedNumbers) . ' = ' . $sum; // two spaces before equals to help sorting
} else if ($goal === NULL || $sum < $goal) {
//--------------------------------------------------
// Add to output, if there is no goal to match
if ($goal === NULL) {
$GLOBALS['resultsOutput'][] = implode(' + ', $newUsedNumbers) . ' = ' . $sum; // two spaces before equals to help sorting
}
//--------------------------------------------------
// Process remaining numbers as children
numberAdditionsSub($numbers, $goal, $newUsedNumbers);
}
}
}
//--------------------------------------------------
// Process
$timeStart = explode(' ', microtime());
$timeStart = ((float)$timeStart[0] + (float)$timeStart[1]);
if ($goal != 0) {
$output = numberAdditions($cleanNumbers, $goal);
} else {
$output = numberAdditions($cleanNumbers);
}
$timeEnd = explode(' ', microtime());
$timeEnd = ((float)$timeEnd[0] + (float)$timeEnd[1]);
$timeTotal = round(($timeEnd - $timeStart), 3);
//--------------------------------------------------
// Output
$htmlOutput = '';
foreach ($output as $cNumber) {
$htmlOutput .= preg_replace('/ += ([^ ]+)$/', ' = $1', html($cNumber)) . "
\n";
}
if ($GLOBALS['calsTotal'] > 0) {
if ($htmlOutput != '') {
$htmlOutput .= "
\n";
}
$htmlOutput .= 'Results: ' . count($output) . "
\n";
$htmlOutput .= 'Calculations: ' . number_format($GLOBALS['calsTotal']) . "
\n";
$htmlOutput .= 'Time: ' . $timeTotal;
}
?>