Ok, curse me, this is my knock-up, improvements welcome :)
I believe this is a Bin Packing Problem or knapsack problem
Javascript
General Power Set
function
function powerSet(array) {
var lastElement,
sets;
if (!array.length) {
sets = [[]];
} else {
lastElement = array.pop();
sets = powerSet(array).reduce(function (previous, element) {
previous.push(element);
element = element.slice();
element.push(lastElement);
previous.push(element);
return previous;
}, []);
}
return sets;
}
Reduces copies in the power set, ie we dont want [6, 8] and [8, 6] they are the same
function reducer1(set) {
set.sort(function (a, b) {
return a - b;
});
return this[set] ? false : (this[set] = true);
}
The main function, gets a match for the bin, remove the used items, rinse and repeat
function calc(bins, items) {
var result = {
unfilled: bins.slice(),
unused: items.slice()
},
match,
bin,
index;
function reducer2(prev, set) {
if (!prev) {
set.length && set.reduce(function (acc, cur) {
acc += cur;
return acc;
}, 0) === bin && (prev = set);
}
return prev;
}
function remove(item) {
result.unused.splice(result.unused.indexOf(item), 1);
}
for (index = result.unfilled.length - 1; index >= 0; index -= 1) {
bin = result.unfilled[index];
match = powerSet(result.unused.slice()).filter(reducer1, {}).reduce(reducer2, '');
if (match) {
result[bin] = match;
match.forEach(remove);
result.unfilled.splice(result.unfilled.lastIndexOf(bin), 1);
}
}
return result;
}
These are our items and the bins they need to be packed into
var array = [6, 5, 7, 8, 6, 12, 16],
sums = [14, 24, 22];
console.log(JSON.stringify(calc(sums, array)));
Output
{"14":[6,8],"22":[6,16],"24":[5,7,12],"unfilled":[],"unused":[]}
On jsfiddle