Version de Perl (de la réponse principale) :
use strict;
sub subset_sum {
my ($numbers, $target, $result, $sum) = @_;
print 'sum('.join(',', @$result).") = $target\n" if $sum == $target;
return if $sum >= $target;
subset_sum([@$numbers[$_ + 1 .. $#$numbers]], $target,
[@{$result||[]}, $numbers->[$_]], $sum + $numbers->[$_])
for (0 .. $#$numbers);
}
subset_sum([3,9,8,4,5,7,10,6], 15);
Résultat :
sum(3,8,4) = 15
sum(3,5,7) = 15
sum(9,6) = 15
sum(8,7) = 15
sum(4,5,6) = 15
sum(5,10) = 15
Version Javascript :
const subsetSum = (numbers, target, partial = [], sum = 0) => {
if (sum < target)
numbers.forEach((num, i) =>
subsetSum(numbers.slice(i + 1), target, partial.concat([num]), sum + num));
else if (sum == target)
console.log('sum(%s) = %s', partial.join(), target);
}
subsetSum([3,9,8,4,5,7,10,6], 15);
Une ligne Javascript qui renvoie réellement les résultats (au lieu de les imprimer) :
const subsetSum=(n,t,p=[],s=0,r=[])=>(s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,[...p,l],s+l,r)):s==t?r.push(p):0,r);
console.log(subsetSum([3,9,8,4,5,7,10,6], 15));
Et ma préférée, une phrase avec un rappel :
const subsetSum=(n,t,cb,p=[],s=0)=>s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,cb,[...p,l],s+l)):s==t?cb(p):0;
subsetSum([3,9,8,4,5,7,10,6], 15, console.log);
9 votes
L'article de wikipedia ( fr.wikipedia.org/wiki/Sous-ensemble_somme_problème ) mentionne même que ce problème est une bonne introduction à la classe des problèmes NP-complets.
6 votes
Peut-on utiliser plus d'une fois le même élément de l'ensemble original ? Par exemple, si l'entrée est {1,2,3,5} et la cible 10, est-ce que 5 + 5 = 10 est une solution acceptable ?
0 votes
Juste une fois. Si un nombre entier doit être répété, il apparaît comme un nouvel élément.
1 votes
stackoverflow.com/a/64380474/585411 montre comment utiliser la programmation dynamique pour éviter tout travail inutile dans la production des réponses.