/** * Calculates a subset sum: finds out which combinations of numbers * from the numbers array can be added together to come to the target * number. * * Returns an indexed array with arrays of number combinations. * * Example: * *
 * $matches = subset_sum(array(5,10,7,3,20), 25);
 * 
* * Returns: * *
 * Array
 * (
 *   [0] => Array
 *   (
 *       [0] => 3
 *       [1] => 5
 *       [2] => 7
 *       [3] => 10
 *   )
 *   [1] => Array
 *   (
 *       [0] => 5
 *       [1] => 20
 *   )
 * )
 * 
* * @param number[] $numbers * @param number $target * @param array $part * @return array[number[]] */ function subset_sum($numbers, $target, $part=null) { // we assume that an empty $part variable means this // is the top level call. $toplevel = false; if($part === null) { $toplevel = true; $part = array(); } $s = 0; foreach($part as $x) { $s = $s + $x; } // we have found a match! if($s == $target) { sort($part); // ensure the numbers are always sorted return array(implode('|', $part)); } // gone too far, break off if($s >= $target) { return null; } $matches = array(); $totalNumbers = count($numbers); for($i=0; $i < $totalNumbers; $i++) { $remaining = array(); $n = $numbers[$i]; for($j = $i+1; $j < $totalNumbers; $j++) { $remaining[] = $numbers[$j]; } $part_rec = $part; $part_rec[] = $n; $result = subset_sum($remaining, $target, $part_rec); if($result) { $matches = array_merge($matches, $result); } } if(!$toplevel) { return $matches; } // this is the top level function call: we have to // prepare the final result value by stripping any // duplicate results. $matches = array_unique($matches); $result = array(); foreach($matches as $entry) { $result[] = explode('|', $entry); } return $result; }