Subset sum problem: Difference between revisions
Content added Content deleted
m (→{{header|REXX}}: made the compN subroutine faster. -- ~~~~) |
(→{{header|REXX}}: added a 2nd version of the REXX program that is faster. -- ~~~~) |
||
Line 540: | Line 540: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
===version 1=== |
|||
This REXX solution isn't limited to integers. |
This REXX solution isn't limited to integers. |
||
<br>This is a brute force solution. |
<br>This is a brute force solution. |
||
Line 745: | Line 746: | ||
Stopped after finding 100 subsets. |
Stopped after finding 100 subsets. |
||
</pre> |
</pre> |
||
===version 2=== |
|||
This version requires the data to be in ascending order (by weight). |
|||
<br>Code could've been included to sort the table, but the extra code would've made the |
|||
<br>program more bulkier, so the list was just sorted externally. |
|||
<br>It's faster than version 1 (above) because it takes advantage of short-circuiting the |
|||
<br>summing process. |
|||
<lang rexx>/*REXX pgm finds some non-null subsets of a weighted list whose sum=0. */ |
|||
arg target stopAt . /*get arguments from command line*/ |
|||
if target=='' then target=0 /*No TARGET given? Use default.*/ |
|||
if stopAt=='' then stopAt=1 /*No max sols given? Use default.*/ |
|||
zzz= 'exorcism -983', |
|||
'isis -982', |
|||
'archbishop -915', |
|||
'mincemeat -880', |
|||
'filmy -874', |
|||
'infra -847', |
|||
'speakeasy -745', |
|||
'centipede -658', |
|||
'alliance -624', |
|||
'elysee -326', |
|||
'plugging -266', |
|||
'deploy 44', |
|||
'efferent 54', |
|||
'fiat 170', |
|||
'mycenae 183', |
|||
'cobol 362', |
|||
'eradicate 376', |
|||
'balm 397', |
|||
'smokescreen 423', |
|||
'bonnet 452', |
|||
'markham 475', |
|||
'flatworm 503', |
|||
'covariate 590', |
|||
'diophantine 645', |
|||
'moresby 756', |
|||
'vein 813', |
|||
'escritoire 856', |
|||
'brute 870', |
|||
'gestapo 915', |
|||
'departure 952', |
|||
'lindholm 999' /*list must be in ascending order by weight.*/ |
|||
@.=0; y=0; do N=1 until zzz=''; parse var zzz @.N #.N zzz |
|||
call t right('['N']',30) right(@.N,11) right(#.N,5) |
|||
end /*N*/ |
|||
solutions=0 |
|||
call t; call t 'There are' N "entries in the table." |
|||
do chunk=1 for N |
|||
call combN N,chunk |
|||
end /*chunk*/ |
|||
if solutions==0 then solutions='no' |
|||
call t 'Found' solutions "subsets whose summed weights =" target |
|||
exit |
|||
/*─────────────────────────────────────telly subroutine─────────────────*/ |
|||
telly: solutions=solutions+1; names= |
|||
do g=1 for y; o=!.g |
|||
names=names @.o |
|||
/* names=names @.o '{'#.o"}" <─── weights in this REXX statement.*/ |
|||
end /*g*/ |
|||
call t '['y" names]" space(names) |
|||
if solutions>=stopAt &, |
|||
stopAt\==0 then do |
|||
call t 'Stopped after finding' solutions "subsets." |
|||
exit |
|||
end |
|||
return |
|||
t: say arg(1); call lineout 'SUBSET.'y,arg(1) /*write to file*/; return |
|||
/*─────────────────────────────────────combN subroutine─────────────────*/ |
|||
combN: procedure expose @. #. solutions stopAt target; parse arg x,y; !.=0 |
|||
base=x+1; bbase=base-y; ym=y-1 /*!.n are the combination digits*/ |
|||
do n=1 for y; !.n=n; end /*build 1st combination*/ |
|||
do j=1; L=!.d; do d=2 for ym; L=L !.d; end /*d*/ |
|||
_=!.1; s=#._ |
|||
do k=2 for y-1 until s>target; _=!.k; s=s+#._; end /*sum weights.*/ |
|||
if s==target then call telly |
|||
!.y=!.y+1; if !.y==base then if .combUp(ym) then leave |
|||
end |
|||
return |
|||
.combUp: procedure expose !. y bbase; parse arg d; if d==0 then return 1 |
|||
p=!.d; do u=d to y; !.u=p+1 |
|||
if !.u>=bbase+u then return .combUp(u-1) |
|||
p=!.u |
|||
end |
|||
return 0</lang> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |