Subset sum problem: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
|||
Line 95: | Line 95: | ||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="11l">V words = [ |
||
‘alliance’ = -624, ‘archbishop’ = -925, ‘balm’ = 397, |
‘alliance’ = -624, ‘archbishop’ = -925, ‘balm’ = 397, |
||
‘bonnet’ = 452, ‘brute’ = 870, ‘centipede’ = -658, |
‘bonnet’ = 452, ‘brute’ = 870, ‘centipede’ = -658, |
||
Line 133: | Line 133: | ||
L(x) s[-neg] |
L(x) s[-neg] |
||
print(x‘ ’words[x]) |
print(x‘ ’words[x]) |
||
L.break</ |
L.break</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 148: | Line 148: | ||
=={{header|Action!}}== |
=={{header|Action!}}== |
||
< |
<syntaxhighlight lang="action!">DEFINE PTR="CARD" |
||
DEFINE PAIR_SIZE="4" |
DEFINE PAIR_SIZE="4" |
||
Line 260: | Line 260: | ||
Test(10) |
Test(10) |
||
Test(27) |
Test(27) |
||
RETURN</ |
RETURN</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Subset_sum_problem.png Screenshot from Atari 8-bit computer] |
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Subset_sum_problem.png Screenshot from Atari 8-bit computer] |
||
Line 278: | Line 278: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO; |
||
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; |
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; |
||
procedure SubsetSum is |
procedure SubsetSum is |
||
Line 333: | Line 333: | ||
end loop; |
end loop; |
||
end loop; |
end loop; |
||
end SubsetSum;</ |
end SubsetSum;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>2: archbishop gestapo |
<pre>2: archbishop gestapo |
||
Line 363: | Line 363: | ||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Line 427: | Line 427: | ||
subsum(0, 0); |
subsum(0, 0); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{output}}<pre>alliance archbishop balm bonnet brute centipede cobol covariate departure deploy diophantine efferent elysee eradicate escritoire exorcism fiat filmy flatworm mincemeat plugging speakeasy |
{{output}}<pre>alliance archbishop balm bonnet brute centipede cobol covariate departure deploy diophantine efferent elysee eradicate escritoire exorcism fiat filmy flatworm mincemeat plugging speakeasy |
||
Line 434: | Line 434: | ||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
Line 515: | Line 515: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The weights of the following 5 subsets add up to zero: |
<pre>The weights of the following 5 subsets add up to zero: |
||
Line 531: | Line 531: | ||
=={{header|C++}}== |
=={{header|C++}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
#include <vector> |
#include <vector> |
||
Line 598: | Line 598: | ||
subsum(0, 0); |
subsum(0, 0); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>alliance archbishop balm bonnet brute centipede cobol covariate departure deploy diophantine efferent elysee eradicate escritoire exorcism fiat filmy flatworm mincemeat plugging speakeasy |
<pre>alliance archbishop balm bonnet brute centipede cobol covariate departure deploy diophantine efferent elysee eradicate escritoire exorcism fiat filmy flatworm mincemeat plugging speakeasy |
||
Line 609: | Line 609: | ||
A simple brute-force solution. This used the module of the third D solution of the Combinations Task. |
A simple brute-force solution. This used the module of the third D solution of the Combinations Task. |
||
{{trans|Ruby}} |
{{trans|Ruby}} |
||
< |
<syntaxhighlight lang="d">void main() { |
||
import std.stdio, std.algorithm, std.typecons, combinations3; |
import std.stdio, std.algorithm, std.typecons, combinations3; |
||
Line 632: | Line 632: | ||
comb.map!q{ a[0] }); |
comb.map!q{ a[0] }); |
||
"No solution found.".writeln; |
"No solution found.".writeln; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>A subset of length 2: archbishop, gestapo</pre> |
<pre>A subset of length 2: archbishop, gestapo</pre> |
||
Line 639: | Line 639: | ||
This version prints all the 349_167 solutions in about 1.8 seconds and counts them in about 0.05 seconds. |
This version prints all the 349_167 solutions in about 1.8 seconds and counts them in about 0.05 seconds. |
||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.algorithm; |
||
enum showAllSolutions = true; |
enum showAllSolutions = true; |
||
Line 735: | Line 735: | ||
writeln("Zero sums: ", sols); |
writeln("Zero sums: ", sols); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Zero sums: 349167</pre> |
<pre>Zero sums: 349167</pre> |
||
Line 743: | Line 743: | ||
We use the Pseudo-polynomial time dynamic programming solution, found in the [[wp:Subset sum problem|Subset sum problem]] Wikipedia article. If A and B are the min and max possible sums, the time and memory needed are '''O((B-A)*N)'''. '''Q''' is an array such as Q(i,s) = true if there is a nonempty subset of x0, ..., xi which sums to s. |
We use the Pseudo-polynomial time dynamic programming solution, found in the [[wp:Subset sum problem|Subset sum problem]] Wikipedia article. If A and B are the min and max possible sums, the time and memory needed are '''O((B-A)*N)'''. '''Q''' is an array such as Q(i,s) = true if there is a nonempty subset of x0, ..., xi which sums to s. |
||
< |
<syntaxhighlight lang="scheme"> |
||
;; 0 <= i < N , A <= s < B , -A = abs(A) |
;; 0 <= i < N , A <= s < B , -A = abs(A) |
||
;; mapping two dims Q(i,s) to one-dim Q(qidx(i,s)) : |
;; mapping two dims Q(i,s) to one-dim Q(qidx(i,s)) : |
||
Line 790: | Line 790: | ||
(map (lambda(i) (first (list-ref input i))) (fillQ (map rest input)))) |
(map (lambda(i) (first (list-ref input i))) (fillQ (map rest input)))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 845: | Line 845: | ||
===Brute force=== |
===Brute force=== |
||
We use the '''powerset''' procrastinator which gives in sequence all subsets of the input list. |
We use the '''powerset''' procrastinator which gives in sequence all subsets of the input list. |
||
< |
<syntaxhighlight lang="scheme"> |
||
(lib 'sequences) ;; for powerset |
(lib 'sequences) ;; for powerset |
||
Line 872: | Line 872: | ||
("deploy" . 44) ("diophantine" . 645) ("efferent" . 54) |
("deploy" . 44) ("diophantine" . 645) ("efferent" . 54) |
||
("elysee" . -326) ("eradicate" . 376)) |
("elysee" . -326) ("eradicate" . 376)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|FunL}}== |
=={{header|FunL}}== |
||
< |
<syntaxhighlight lang="funl">def subsetSum( s, w, v ) = |
||
def sumset( a ) = foldl1( (+), map(w, a) ) |
def sumset( a ) = foldl1( (+), map(w, a) ) |
||
Line 919: | Line 919: | ||
for i <- 0..5 |
for i <- 0..5 |
||
println( i, subsetSum(s, snd, i).get() )</ |
println( i, subsetSum(s, snd, i).get() )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 933: | Line 933: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 999: | Line 999: | ||
} |
} |
||
fmt.Println("no subset sums to 0") |
fmt.Println("no subset sums to 0") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,015: | Line 1,015: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang="haskell">combinations :: Int -> [a] -> [[a]] |
||
combinations 0 _ = [[]] |
combinations 0 _ = [[]] |
||
combinations _ [] = [] |
combinations _ [] = [] |
||
Line 1,046: | Line 1,046: | ||
W "vein" 813] |
W "vein" 813] |
||
main = print $ map word $ head $ solver items</ |
main = print $ map word $ head $ solver items</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>["archbishop","gestapo"]</pre> |
<pre>["archbishop","gestapo"]</pre> |
||
Non brute-force: the list of numbers used here are different, and difficult for a bruteforce method. |
Non brute-force: the list of numbers used here are different, and difficult for a bruteforce method. |
||
< |
<syntaxhighlight lang="haskell">subsum :: Int -> [Int] -> [Int] |
||
subsum w = |
subsum w = |
||
snd . head . filter ((== w) . fst) . (++ [(w, [])]) . foldl s [(0, [])] |
snd . head . filter ((== w) . fst) . (++ [(w, [])]) . foldl s [(0, [])] |
||
Line 1,073: | Line 1,073: | ||
main :: IO () |
main :: IO () |
||
main = print $ subsum 0 items</ |
main = print $ subsum 0 items</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>[-61,32,373,311,249,311,32,-92,-185,-433,-402,-247,156,125,249,32,-464,-278,218,32,-123,-216,373,-185,-402,156,-402,-61,902]</pre> |
<pre>[-61,32,373,311,249,311,32,-92,-185,-433,-402,-247,156,125,249,32,-464,-278,218,32,-123,-216,373,-185,-402,156,-402,-61,902]</pre> |
||
Line 1,079: | Line 1,079: | ||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |
||
{{trans|Ruby}} |
{{trans|Ruby}} |
||
< |
<syntaxhighlight lang="icon">link printf,lists |
||
procedure main() |
procedure main() |
||
Line 1,124: | Line 1,124: | ||
return T |
return T |
||
end</ |
end</syntaxhighlight> |
||
{{libheader|Icon Programming Library}} |
{{libheader|Icon Programming Library}} |
||
Line 1,166: | Line 1,166: | ||
Task data: |
Task data: |
||
< |
<syntaxhighlight lang="j">text=:0 :0 |
||
alliance -624 |
alliance -624 |
||
archbishop -915 |
archbishop -915 |
||
Line 1,201: | Line 1,201: | ||
words=:{.@;:;._2 text |
words=:{.@;:;._2 text |
||
numbs=:+/|:0&".;._2 text</ |
numbs=:+/|:0&".;._2 text</syntaxhighlight> |
||
Implementation: |
Implementation: |
||
< |
<syntaxhighlight lang="j">wsum0=:4 :0 |
||
p=:(#~ 0&<)y |
p=:(#~ 0&<)y |
||
n=:(#~ 0&>)y |
n=:(#~ 0&>)y |
||
Line 1,214: | Line 1,214: | ||
keep=: [ #~ #&2@#@[ #: choose i.~ ] |
keep=: [ #~ #&2@#@[ #: choose i.~ ] |
||
;:inv words #~y e. (p keep P),n keep N |
;:inv words #~y e. (p keep P),n keep N |
||
)</ |
)</syntaxhighlight> |
||
Task example: |
Task example: |
||
< |
<syntaxhighlight lang="j"> words wsum0 numbs |
||
centipede markham mycenae</ |
centipede markham mycenae</syntaxhighlight> |
||
Note also that there are over 300,000 valid solutions here. More than can be comfortably displayed: |
Note also that there are over 300,000 valid solutions here. More than can be comfortably displayed: |
||
< |
<syntaxhighlight lang="j"> Ps=: </.~ /:~ (I.P e. N){P |
||
Ns=: </.~ /:~ (I.N e. P){N |
Ns=: </.~ /:~ (I.N e. P){N |
||
+/#@,@{"1 Ps,.Ns |
+/#@,@{"1 Ps,.Ns |
||
349168</ |
349168</syntaxhighlight> |
||
(One of those is the empty solution, but the rest of them are valid.) |
(One of those is the empty solution, but the rest of them are valid.) |
||
Line 1,232: | Line 1,232: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="java">public class SubsetSum { |
||
private static class Item { |
private static class Item { |
||
private String word; |
private String word; |
||
Line 1,309: | Line 1,309: | ||
zeroSum(0, 0); |
zeroSum(0, 0); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The weights of the following 5 subsets add up to zero: |
<pre>The weights of the following 5 subsets add up to zero: |
||
Line 1,326: | Line 1,326: | ||
{{works with|jq}} |
{{works with|jq}} |
||
'''Works with gojq, the Go implementation of jq''' (provided `keys_unsorted` is replaced by `keys`) |
'''Works with gojq, the Go implementation of jq''' (provided `keys_unsorted` is replaced by `keys`) |
||
<syntaxhighlight lang="jq"> |
|||
<lang jq> |
|||
# Input: an array of n elements, each of which is either in or out |
# Input: an array of n elements, each of which is either in or out |
||
# Output: a stream of the 2^n possible selections |
# Output: a stream of the 2^n possible selections |
||
Line 1,344: | Line 1,344: | ||
. as $dict |
. as $dict |
||
| keys_unsorted | selections | select( sum($dict; 0)); |
| keys_unsorted | selections | select( sum($dict; 0)); |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''An Example''' |
'''An Example''' |
||
< |
<syntaxhighlight lang="jq">def weights: |
||
{ |
{ |
||
"alliance": -624, |
"alliance": -624, |
||
Line 1,381: | Line 1,381: | ||
}; |
}; |
||
weights | first(zero_sums)</ |
weights | first(zero_sums)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,398: | Line 1,398: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">using Combinatorics |
||
const pairs = [ |
const pairs = [ |
||
Line 1,428: | Line 1,428: | ||
zerosums() |
zerosums() |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
For length 1: None |
For length 1: None |
||
Line 1,467: | Line 1,467: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="scala">// version 1.1.2 |
||
class Item(val word: String, val weight: Int) { |
class Item(val word: String, val weight: Int) { |
||
Line 1,530: | Line 1,530: | ||
println("The weights of the following $LIMIT subsets add up to zero:\n") |
println("The weights of the following $LIMIT subsets add up to zero:\n") |
||
zeroSum(0, 0) |
zeroSum(0, 0) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,548: | Line 1,548: | ||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">a = {{"alliance", -624}, {"archbishop", -915}, {"balm", 397}, {"bonnet", 452}, |
||
{"brute", 870}, {"centipede", -658}, {"cobol", 362}, {"covariate", 590},{"departure", 952}, |
{"brute", 870}, {"centipede", -658}, {"cobol", 362}, {"covariate", 590},{"departure", 952}, |
||
{"deploy", 44}, {"diophantine", 645}, {"efferent", 54}, {"elysee", -326}, {"eradicate", 376}, |
{"deploy", 44}, {"diophantine", 645}, {"efferent", 54}, {"elysee", -326}, {"eradicate", 376}, |
||
Line 1,557: | Line 1,557: | ||
result = Rest@Select[ Subsets[a, 7], (Total[#[[;; , 2]]] == 0) &]; |
result = Rest@Select[ Subsets[a, 7], (Total[#[[;; , 2]]] == 0) &]; |
||
Map[ (Print["A zero-sum subset of length ", Length[#], " : ", #[[;; , 1]]])& , result ]</ |
Map[ (Print["A zero-sum subset of length ", Length[#], " : ", #[[;; , 1]]])& , result ]</syntaxhighlight> |
||
<pre>A zero-sum subset of length 2 : {archbishop,gestapo} |
<pre>A zero-sum subset of length 2 : {archbishop,gestapo} |
||
Line 1,570: | Line 1,570: | ||
The above code uses a brute-force approach, but Mathematica includes several solution schemes that can be used to solve this problem. We can cast it as an integer linear programming problem, and thus find the largest or smallest subset sum, or even sums with specific constraints, such as a sum using three negative values and nine positive values. |
The above code uses a brute-force approach, but Mathematica includes several solution schemes that can be used to solve this problem. We can cast it as an integer linear programming problem, and thus find the largest or smallest subset sum, or even sums with specific constraints, such as a sum using three negative values and nine positive values. |
||
< |
<syntaxhighlight lang="mathematica">a = {{"alliance", -624}, {"archbishop", -915}, {"balm", 397}, {"bonnet", 452}, |
||
{"brute", 870}, {"centipede", -658}, {"cobol", 362}, {"covariate", 590},{"departure", 952}, |
{"brute", 870}, {"centipede", -658}, {"cobol", 362}, {"covariate", 590},{"departure", 952}, |
||
{"deploy", 44}, {"diophantine", 645}, {"efferent", 54}, {"elysee", -326}, {"eradicate", 376}, |
{"deploy", 44}, {"diophantine", 645}, {"efferent", 54}, {"elysee", -326}, {"eradicate", 376}, |
||
Line 1,604: | Line 1,604: | ||
Print["3 -ves, 9 +ves: ", Select[Transpose[{threeNineSoln*aValues, aNames}], #[[1]] != 0 &]]; |
Print["3 -ves, 9 +ves: ", Select[Transpose[{threeNineSoln*aValues, aNames}], #[[1]] != 0 &]]; |
||
</syntaxhighlight> |
|||
</lang> |
|||
<pre>Maximal solution: {{-624, alliance}, {-915, archbishop}, {397, balm}, |
<pre>Maximal solution: {{-624, alliance}, {-915, archbishop}, {397, balm}, |
||
Line 1,622: | Line 1,622: | ||
=={{header|MiniZinc}}== |
=={{header|MiniZinc}}== |
||
<syntaxhighlight lang="minizinc"> |
|||
<lang MiniZinc> |
|||
%Subset sum. Nigel Galloway: January 6th., 2021. |
%Subset sum. Nigel Galloway: January 6th., 2021. |
||
enum Items={alliance,archbishop,balm,bonnet,brute,centipede,cobol,covariate,departure,deploy,diophantine,efferent,elysee,eradicate,escritoire,exorcism,fiat,filmy,flatworm,gestapo,infra,isis,lindholm,markham,mincemeat,moresby,mycenae,plugging,smokescreen,speakeasy,vein}; |
enum Items={alliance,archbishop,balm,bonnet,brute,centipede,cobol,covariate,departure,deploy,diophantine,efferent,elysee,eradicate,escritoire,exorcism,fiat,filmy,flatworm,gestapo,infra,isis,lindholm,markham,mincemeat,moresby,mycenae,plugging,smokescreen,speakeasy,vein}; |
||
Line 1,629: | Line 1,629: | ||
var int: wSelected=sum(n in selected)(weight[n]); |
var int: wSelected=sum(n in selected)(weight[n]); |
||
constraint wSelected=0; |
constraint wSelected=0; |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,637: | Line 1,637: | ||
</pre> |
</pre> |
||
=={{header|Modula-2}}== |
=={{header|Modula-2}}== |
||
< |
<syntaxhighlight lang="modula2">MODULE SubsetSum; |
||
FROM FormatString IMPORT FormatString; |
FROM FormatString IMPORT FormatString; |
||
FROM Terminal IMPORT WriteString,WriteLn,ReadChar; |
FROM Terminal IMPORT WriteString,WriteLn,ReadChar; |
||
Line 1,738: | Line 1,738: | ||
ReadChar; |
ReadChar; |
||
END SubsetSum.</ |
END SubsetSum.</syntaxhighlight> |
||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
{{libheader|itertools}} |
{{libheader|itertools}} |
||
We need the third party module "itertools" to compute the combinations. |
We need the third party module "itertools" to compute the combinations. |
||
< |
<syntaxhighlight lang="nim">import sequtils, strformat, strutils |
||
import itertools |
import itertools |
||
Line 1,792: | Line 1,792: | ||
echo &"For length {lg}, found for example: ", comb.mapIt(words[it]).join(" ") |
echo &"For length {lg}, found for example: ", comb.mapIt(words[it]).join(" ") |
||
break checkCombs |
break checkCombs |
||
echo &"For length {lg}, no set found."</ |
echo &"For length {lg}, no set found."</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,831: | Line 1,831: | ||
Just search randomly until a result is found: |
Just search randomly until a result is found: |
||
< |
<syntaxhighlight lang="ocaml">let d = |
||
[ "alliance", -624; "archbishop", -915; "balm", 397; "bonnet", 452; |
[ "alliance", -624; "archbishop", -915; "balm", 397; "bonnet", 452; |
||
"brute", 870; "centipede", -658; "cobol", 362; "covariate", 590; |
"brute", 870; "centipede", -658; "cobol", 362; "covariate", 590; |
||
Line 1,865: | Line 1,865: | ||
in |
in |
||
let res = aux [] d in |
let res = aux [] d in |
||
List.iter (fun (n,w) -> Printf.printf " %4d\t%s\n" w n) res</ |
List.iter (fun (n,w) -> Printf.printf " %4d\t%s\n" w n) res</syntaxhighlight> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{libheader|ntheory}} |
{{libheader|ntheory}} |
||
< |
<syntaxhighlight lang="perl">use ntheory qw/:all/; |
||
my %pairs = ( |
my %pairs = ( |
||
Line 1,889: | Line 1,889: | ||
lastfor, print "Length $n: @names[@_]\n" if vecsum(@weights[@_]) == 0; |
lastfor, print "Length $n: @names[@_]\n" if vecsum(@weights[@_]) == 0; |
||
} @names, $n; |
} @names, $n; |
||
}</ |
}</syntaxhighlight> |
||
Printing just the first one found for each number of elements: |
Printing just the first one found for each number of elements: |
||
{{out}} |
{{out}} |
||
Line 1,905: | Line 1,905: | ||
We can also use different modules for this brute force method. Assuming the same pairs/names/weights variables: |
We can also use different modules for this brute force method. Assuming the same pairs/names/weights variables: |
||
< |
<syntaxhighlight lang="perl">use List::Util qw/sum/; |
||
use Algorithm::Combinatorics qw/combinations/; |
use Algorithm::Combinatorics qw/combinations/; |
||
foreach my $n (1 .. @names) { |
foreach my $n (1 .. @names) { |
||
Line 1,914: | Line 1,914: | ||
last; |
last; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Simple Brute force |
Simple Brute force |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({{</span><span style="color: #008000;">"alliance"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">624</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"archbishop"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">915</span><span style="color: #0000FF;">},</span> |
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({{</span><span style="color: #008000;">"alliance"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">624</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"archbishop"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">915</span><span style="color: #0000FF;">},</span> |
||
Line 1,957: | Line 1,957: | ||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,998: | Line 1,998: | ||
This is significantly faster (near instant, in fact) than an "all possible combinations" approach. |
This is significantly faster (near instant, in fact) than an "all possible combinations" approach. |
||
Shows the first zero-sum subset found, only. |
Shows the first zero-sum subset found, only. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #000000;">weights</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">61</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">373</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">311</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">249</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">311</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">92</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">185</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">433</span><span style="color: #0000FF;">,</span> |
<span style="color: #008080;">constant</span> <span style="color: #000000;">weights</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">61</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">373</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">311</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">249</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">311</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">92</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">185</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">433</span><span style="color: #0000FF;">,</span> |
||
Line 2,031: | Line 2,031: | ||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,040: | Line 2,040: | ||
Using constraint modelling. |
Using constraint modelling. |
||
< |
<syntaxhighlight lang="picat">import cp. |
||
% |
% |
||
Line 2,109: | Line 2,109: | ||
[speakeasy, -745], |
[speakeasy, -745], |
||
[vein, 813 ] |
[vein, 813 ] |
||
].</ |
].</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,120: | Line 2,120: | ||
Get a solution - if possible - for a specific number of selected things. |
Get a solution - if possible - for a specific number of selected things. |
||
< |
<syntaxhighlight lang="picat">go2 => |
||
things(Things), |
things(Things), |
||
foreach(Len in 1..Things.length) |
foreach(Len in 1..Things.length) |
||
Line 2,131: | Line 2,131: | ||
nl |
nl |
||
end, |
end, |
||
nl.</ |
nl.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,223: | Line 2,223: | ||
There are in total 349167 solutions of any number of items (the empty set is not a solution in our book). |
There are in total 349167 solutions of any number of items (the empty set is not a solution in our book). |
||
< |
<syntaxhighlight lang="picat">go3 => |
||
things(Things), |
things(Things), |
||
Count = count_all(subset_sum(Things, _X, _Z)), |
Count = count_all(subset_sum(Things, _X, _Z)), |
||
println(count=Count), |
println(count=Count), |
||
nl. |
nl. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(de *Words |
||
(alliance . -624) (archbishop . -915) (balm . 397) (bonnet . 452) |
(alliance . -624) (archbishop . -915) (balm . 397) (bonnet . 452) |
||
(brute . 870) (centipede . -658) (cobol . 362) (covariate . 590) |
(brute . 870) (centipede . -658) (cobol . 362) (covariate . 590) |
||
Line 2,241: | Line 2,241: | ||
(infra . -847) (isis . -982) (lindholm . 999) (markham . 475) |
(infra . -847) (isis . -982) (lindholm . 999) (markham . 475) |
||
(mincemeat . -880) (moresby . 756) (mycenae . 183) (plugging . -266) |
(mincemeat . -880) (moresby . 756) (mycenae . 183) (plugging . -266) |
||
(smokescreen . 423) (speakeasy . -745) (vein . 813) )</ |
(smokescreen . 423) (speakeasy . -745) (vein . 813) )</syntaxhighlight> |
||
Minimal brute force solution: |
Minimal brute force solution: |
||
< |
<syntaxhighlight lang="picolisp">(load "@lib/simul.l") # For 'subsets' |
||
(pick |
(pick |
||
Line 2,249: | Line 2,249: | ||
(find '((L) (=0 (sum cdr L))) |
(find '((L) (=0 (sum cdr L))) |
||
(subsets N *Words) ) ) |
(subsets N *Words) ) ) |
||
(range 1 (length *Words)) )</ |
(range 1 (length *Words)) )</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>-> ((archbishop . -915) (gestapo . 915))</pre> |
<pre>-> ((archbishop . -915) (gestapo . 915))</pre> |
||
Line 2,255: | Line 2,255: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
===Version 1=== |
===Version 1=== |
||
< |
<syntaxhighlight lang="python">words = { # some values are different from example |
||
"alliance": -624, "archbishop": -925, "balm": 397, |
"alliance": -624, "archbishop": -925, "balm": 397, |
||
"bonnet": 452, "brute": 870, "centipede": -658, |
"bonnet": 452, "brute": 870, "centipede": -658, |
||
Line 2,289: | Line 2,289: | ||
for x in s[-neg]: |
for x in s[-neg]: |
||
print(x, words[x]) |
print(x, words[x]) |
||
break</ |
break</syntaxhighlight> |
||
{{out}}<pre> |
{{out}}<pre> |
||
('mycenae', 183) |
('mycenae', 183) |
||
Line 2,300: | Line 2,300: | ||
</pre> |
</pre> |
||
===Brute force=== |
===Brute force=== |
||
< |
<syntaxhighlight lang="python">>>> from itertools import combinations |
||
>>> |
>>> |
||
>>> word2weight = {"alliance": -624, "archbishop": -915, "balm": 397, "bonnet": 452, |
>>> word2weight = {"alliance": -624, "archbishop": -915, "balm": 397, "bonnet": 452, |
||
Line 2,320: | Line 2,320: | ||
>>> answer |
>>> answer |
||
[('archbishop', -915), ('gestapo', 915)]</ |
[('archbishop', -915), ('gestapo', 915)]</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
Line 2,358: | Line 2,358: | ||
(for ([i (sub1 len)]) (loop l len (add1 i) '() 0))) |
(for ([i (sub1 len)]) (loop l len (add1 i) '() 0))) |
||
(zero-subsets words) |
(zero-subsets words) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,371: | Line 2,371: | ||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
<lang |
<syntaxhighlight lang="raku" line>my @pairs = |
||
alliance => -624, archbishop => -915, balm => 397, bonnet => 452, |
alliance => -624, archbishop => -915, balm => 397, bonnet => 452, |
||
brute => 870, centipede => -658, cobol => 362, covariate => 590, |
brute => 870, centipede => -658, cobol => 362, covariate => 590, |
||
Line 2,388: | Line 2,388: | ||
default { "Length $n: (none)" } |
default { "Length $n: (none)" } |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Length 1: (none) |
<pre>Length 1: (none) |
||
Line 2,428: | Line 2,428: | ||
Added was "que pasa" informational messages. The sum (which is zero for this task) can be any number, |
Added was "que pasa" informational messages. The sum (which is zero for this task) can be any number, |
||
<br>and can be specifiable on the command line. |
<br>and can be specifiable on the command line. |
||
< |
<syntaxhighlight lang="rexx">/*REXX program finds some non─null subsets of a weighted list whose sum eqals zero.*/ |
||
parse arg target stopAt chunkette . /*option optional arguments from the CL*/ |
parse arg target stopAt chunkette . /*option optional arguments from the CL*/ |
||
if target=='' | target=="," then target= 0 /*Not specified? Then use the default.*/ |
if target=='' | target=="," then target= 0 /*Not specified? Then use the default.*/ |
||
Line 2,517: | Line 2,517: | ||
call tello |
call tello |
||
call tello 'There are ' N " entries in the (above)" arg(1) 'table.' |
call tello 'There are ' N " entries in the (above)" arg(1) 'table.' |
||
call tello; return</ |
call tello; return</syntaxhighlight> |
||
Output note: this program also writes the displayed output to file(s): SUBSET.nnn |
Output note: this program also writes the displayed output to file(s): SUBSET.nnn |
||
<br> ──────── where nnn is the ''chunk'' number. |
<br> ──────── where nnn is the ''chunk'' number. |
||
Line 2,583: | Line 2,583: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
# Project : Subset sum problem |
# Project : Subset sum problem |
||
Line 2,664: | Line 2,664: | ||
next |
next |
||
return alist |
return alist |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 2,677: | Line 2,677: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
a brute force solution: |
a brute force solution: |
||
< |
<syntaxhighlight lang="ruby">weights = { |
||
'alliance' =>-624, 'archbishop'=>-915, 'balm' => 397, 'bonnet' => 452, |
'alliance' =>-624, 'archbishop'=>-915, 'balm' => 397, 'bonnet' => 452, |
||
'brute' => 870, 'centipede' =>-658, 'cobol' => 362, 'covariate'=> 590, |
'brute' => 870, 'centipede' =>-658, 'cobol' => 362, 'covariate'=> 590, |
||
Line 2,699: | Line 2,699: | ||
puts "no subsets of length #{n} sum to zero" |
puts "no subsets of length #{n} sum to zero" |
||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,737: | Line 2,737: | ||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{Out}}Best seen running in your browser by [https://scastie.scala-lang.org/KnhJimmSTL6QXIGTAdZjBQ Scastie (remote JVM)]. |
{{Out}}Best seen running in your browser by [https://scastie.scala-lang.org/KnhJimmSTL6QXIGTAdZjBQ Scastie (remote JVM)]. |
||
< |
<syntaxhighlight lang="scala">object SubsetSum extends App { |
||
private val LIMIT = 5 |
private val LIMIT = 5 |
||
private val n = items.length |
private val n = items.length |
||
Line 2,799: | Line 2,799: | ||
zeroSum(0, 0) |
zeroSum(0, 0) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
< |
<syntaxhighlight lang="ruby">var pairs = Hash( |
||
alliance => -624, archbishop => -915, |
alliance => -624, archbishop => -915, |
||
brute => 870, centipede => -658, |
brute => 870, centipede => -658, |
||
Line 2,834: | Line 2,834: | ||
}) |
}) |
||
found || say "Length #{n}: (none)" |
found || say "Length #{n}: (none)" |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre style="height: 40ex; overflow: scroll"> |
<pre style="height: 40ex; overflow: scroll"> |
||
Line 2,870: | Line 2,870: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
As it turns out that the problem space has small subsets that sum to zero, it is more efficient to enumerate subsets in order of their size rather than doing a simple combination search. This is not true of all possible input data sets though; the problem is known to be NP-complete after all. |
As it turns out that the problem space has small subsets that sum to zero, it is more efficient to enumerate subsets in order of their size rather than doing a simple combination search. This is not true of all possible input data sets though; the problem is known to be NP-complete after all. |
||
< |
<syntaxhighlight lang="tcl">proc subsetsOfSize {set size} { |
||
if {$size <= 0} { |
if {$size <= 0} { |
||
return |
return |
||
Line 2,896: | Line 2,896: | ||
# Nothing was found |
# Nothing was found |
||
return -code error "no subset sums to zero" |
return -code error "no subset sums to zero" |
||
}</ |
}</syntaxhighlight> |
||
Demonstrating: |
Demonstrating: |
||
< |
<syntaxhighlight lang="tcl">set wordweights { |
||
alliance -624 |
alliance -624 |
||
archbishop -915 |
archbishop -915 |
||
Line 2,932: | Line 2,932: | ||
} |
} |
||
set zsss [searchForSubset $wordweights] |
set zsss [searchForSubset $wordweights] |
||
puts "Found zero-summing subset: [join [lsort $zsss] {, }]"</ |
puts "Found zero-summing subset: [join [lsort $zsss] {, }]"</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre> |
<pre> |
||
Line 2,940: | Line 2,940: | ||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
This solution scans the set sequentially while maintaining a record of all distinct sums obtainable by words encountered thus far, and stops when a zero sum is found. |
This solution scans the set sequentially while maintaining a record of all distinct sums obtainable by words encountered thus far, and stops when a zero sum is found. |
||
< |
<syntaxhighlight lang="ursala">#import std |
||
#import int |
#import int |
||
Line 2,982: | Line 2,982: | ||
#cast %zm |
#cast %zm |
||
main = nullset weights</ |
main = nullset weights</syntaxhighlight> |
||
The name of the function that takes the weighted set is <code>nullset</code>. It manipulates a partial result represented as a list of pairs, each containing a subset of weighted words and the sum of their weights. Here is a rough translation: |
The name of the function that takes the weighted set is <code>nullset</code>. It manipulates a partial result represented as a list of pairs, each containing a subset of weighted words and the sum of their weights. Here is a rough translation: |
||
* <code>=><></code> fold right combinator with the empty list as the vacuuous case |
* <code>=><></code> fold right combinator with the empty list as the vacuuous case |
||
Line 3,007: | Line 3,007: | ||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="ecmascript">import "/fmt" for Fmt |
||
class Item { |
class Item { |
||
Line 3,082: | Line 3,082: | ||
System.print("The weights of the following %(LIMIT) subsets add up to zero:\n") |
System.print("The weights of the following %(LIMIT) subsets add up to zero:\n") |
||
zeroSum.call(0, 0)</ |
zeroSum.call(0, 0)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,204: | Line 3,204: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="zkl">var items=T( |
||
T("alliance", -624), T("archbishop", -915), T("balm", 397), |
T("alliance", -624), T("archbishop", -915), T("balm", 397), |
||
T("bonnet", 452), T("brute", 870), T("centipede", -658), |
T("bonnet", 452), T("brute", 870), T("centipede", -658), |
||
Line 3,230: | Line 3,230: | ||
set:=List.createLong(items.len(),0); |
set:=List.createLong(items.len(),0); |
||
try{ subSum(set,0,0); }catch(TheEnd){}</ |
try{ subSum(set,0,0); }catch(TheEnd){}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |