Here's a fun solution.
First, we build a "sum map" from the array, using a procedure like the classic dynamic programming solution for subset sum.
This map contains, for each possible sum you can create, the list of indexes of possible last numbers in that sum.
We can then use the same map to directly generate all of the possible ways to get all of your possible sums, without any more searching/backtracking.
Note that the output can be very large, but the sum map is not that big for the kinds of inputs you seem to be interested in.
I don't know what you need those big lists for, but maybe you just want to store the sum map instead and generate the lists as you need them. This can save you a lot of memory.
// numbersToSum total = 11319
var numbersToSum = [276, 1872, 1345, 1355, 1400, 1300, 1200, 51, 1020, 500, 400, 300, 100, 100, 100];
// targetSums total = 11319
var targetSums = [1627, 4775, 4917];
// Keep track of the total sum for convenience
var totalSum = 11319;
// Build a "sum map" from a list of positive integers
// For each sum <= maxtarget, the returned map will provide
// the list of indexes that could be the last number in that sum
// From this map, the complete set of possible sums for any value
// can be easily determined.
function buildSumMap(nums, maxtarget)
{
//all accessible sums <= maxtarget
let sumList=[0];
//for each accessible sum, the indexes of possible final numbers, in order
let sumMap={
0:[]
}
for (let i=0; i<nums.length; ++i) {
for (let previ=sumList.length-1; previ>=0; --previ) {
let newsum = sumList[previ]+nums[i];
if (newsum <= maxtarget) {
let list = sumMap[newsum];
if (!list) {
//previously inaccessible sum
sumList.push(newsum);
list = [];
sumMap[newsum] = list;
}
list.push(i);
}
}
}
return sumMap;
}
// Get all the derivations of a given target sum, using a sum map
// only indexes < indexLimit will be considered
function getSetsThatSum(nums, sumMap, target, indexLimit)
{
if (target==0) {
return [[]];
}
let list = sumMap[target];
if (!(list && list.length)) {
return [];
}
let ret=[];
for (let i=0; i<list.length; i++) {
let lastindex = list[i];
if (lastindex >= indexLimit) {
break;
}
let val = nums[lastindex];
getSetsThatSum(nums, sumMap, target-val, lastindex).forEach(prevsum => {
ret.push([...prevsum, val]);
});
}
return ret;
}
let sumMap = buildSumMap(numbersToSum, 5000);
// Store the solutions
var targetSumsSolutions = {
1627: getSetsThatSum(numbersToSum, sumMap, 1627, numbersToSum.length),
4775: getSetsThatSum(numbersToSum, sumMap, 4775, numbersToSum.length),
4917: getSetsThatSum(numbersToSum, sumMap, 4917, numbersToSum.length),
};
console.log(targetSumsSolutions);
Output:
{ '1627':
[ [ 276, 1300, 51 ],
[ 276, 1200, 51, 100 ],
[ 276, 51, 500, 400, 300, 100 ],
[ 276, 1200, 51, 100 ],
[ 276, 51, 500, 400, 300, 100 ],
[ 276, 1200, 51, 100 ],
[ 276, 51, 500, 400, 300, 100 ] ],
'4775':
[ [ 1355, 1200, 1020, 500, 400, 300 ],
[ 1355, 1400, 1020, 500, 400, 100 ],
[ 1355, 1400, 1020, 500, 400, 100 ],
[ 1355, 1300, 1020, 500, 400, 100, 100 ],
[ 1355, 1400, 1020, 500, 300, 100, 100 ],
[ 1355, 1400, 1020, 500, 400, 100 ],
[ 1355, 1300, 1020, 500, 400, 100, 100 ],
[ 1355, 1400, 1020, 500, 300, 100, 100 ],
[ 1355, 1300, 1020, 500, 400, 100, 100 ],
[ 1355, 1400, 1020, 500, 300, 100, 100 ],
[ 1355, 1200, 1020, 500, 400, 100, 100, 100 ],
[ 1355, 1300, 1020, 500, 300, 100, 100, 100 ],
[ 1355, 1400, 1020, 400, 300, 100, 100, 100 ] ],
'4917':
[ [ 1872, 1345, 1200, 500 ],
[ 1872, 1345, 1300, 400 ],
[ 1872, 1345, 1400, 300 ],
[ 1872, 1345, 1200, 400, 100 ],
[ 1872, 1345, 1300, 300, 100 ],
[ 1872, 1345, 1200, 400, 100 ],
[ 1872, 1345, 1300, 300, 100 ],
[ 1872, 1345, 1200, 300, 100, 100 ],
[ 1872, 1345, 1200, 400, 100 ],
[ 1872, 1345, 1300, 300, 100 ],
[ 1872, 1345, 1200, 300, 100, 100 ],
[ 1872, 1345, 1200, 300, 100, 100 ],
[ 1872, 1345, 1400, 100, 100, 100 ] ] }