Reputation: 584
I've been searching for a while to try and arrive at some sort of solution for a problem that is currently roadblocking a task I'm trying to complete. I've come across a few solutions in other programming languages that I really can't understand despite my attempts at doing so. I've also seen a lot of terminology surrounding this problem such as permutations, refactoring, subset sums, coins in a dollar, etc.
If I'm going about this the wrong way, please do feel free to let me know.
Here's the problem in a nutshell:
Given a set (array) of numbers,
ex: 2, 3, 7, 14
,
how could I find what combinations of those numbers add up to (or equal) a specific sum, ex: 14
.
An example of some of the potential combinations for the above example numbers:
3 + 3 + 3 + 3 + 2
7 + 3 + 2 + 2
7 + 7
14
Since the problem I'm trying to solve is in PHP, I'd love if there were a solution that could be offered in that language. If not, even if someone could better explain what the problem is that I'm trying to solve, and potential methods of doing so, I'd be greatly appreciative.
Or again if I might be going about this the wrong way, I'm all ears.
Upvotes: 2
Views: 2532
Reputation: 584
Here's what I have managed to come up with thus far, based on amit's feedback and example, and some other examples. So far it appears to be working - but I'm not 100% certain.
$totals = array();
$x=0;
function getAllCombinations($ind, $denom, $n, $vals=array()){
global $totals, $x;
if ($n == 0){
foreach ($vals as $key => $qty){
for(; $qty>0; $qty--){
$totals[$x][] = $denom[$key];
}
}
$x++;
return;
}
if ($ind == count($denom)) return;
$currdenom = $denom[$ind];
for ($i=0;$i<=($n/$currdenom);$i++){
$vals[$ind] = $i;
getAllCombinations($ind+1,$denom,$n-($i*$currdenom),$vals);
}
}
$array = array(3, 5, 7, 14);
$sum = 30;
getAllCombinations(0, $array, $sum);
var_dump($totals);
Upvotes: 2
Reputation: 178471
To generate ALL solutions you are going to need to use some kind of backtracking, "guess" if the first number is in the solution or not, and recurse for each of the possibilities (it is needed to sum the result, or it is not).
Something like the following pseudo-code:
genResults(array, sum, currentResult):
if (sum == 0): //stop clause, found a series summing to to correct number
print currentResult
else if (sum < 0): //failing stop clause, passed the required number
return
else if (array.length == 0): //failing stop clause, exhausted the array
return
else:
//find all solutions reachable while using the first number (can use it multiple times)
currentResult.addLast(array[0])
genResults(array, sum - array[0], currentResult)
//clean up
currentResult.removeLast()
//find all solutions reachable while NOT using first number
genResults(array+1, sum, currentResult)
//in the above array+1 means the subarray starting from the 2nd element
Upvotes: 2