Obviously there are quite a few ways to do this including El Bruto (brute force).

In a similar problem, optimization problem, the aim is to find a combination of weights to reach a certain total. With the difference that you have integers and any combination is acceptable. I have suggested using genetic algorithms and there is code there to do that.

Another way, possibly inefficient, is to use a tree.

#!/usr/bin/env perl # depth-first search on a tree of combinations # aim is to use @input numbers to make the target sum. # by bliako # for https://perlmonks.org/?node_id=11102502 # 08/07/2019 use strict; use warnings; # from https://github.com/hadjiprocopis/Tree-Nary-Tiny # or any other nary-tree implementation, e.g. # https://metacpan.org/pod/Tree::Simple use Tree::Nary::Tiny; #for deep recursion try this: #my @input = map { 2+int(rand(20)) } 0..100; #my $target = 15783; my @input = qw/ 2 5 7 /; my $target = 15; my $T = Tree::Nary::Tiny->new( undef, # parent "root", undef, # data sub { return $_[0] } ); my @solutions; find($T, \@input, $target, \@solutions); print "$0 : here are all the solutions:\n"; my $i = 1; foreach (@solutions){ my $sum = 0; $sum += $_ foreach (@$_); if( $sum != $target ){ die "wrong solution, this should not be hap +pening." } print $i . ")". join(",", @$_)."\n"; $i++; } sub find { my $n = $_[0]; my $input = $_[1]; my $target = $_[2]; my $solutions = $_[3]; my $v = $n->value(); if( defined $v && $v->{'sum'} == $target ){ my @asol = (); while( defined $n->parent() ){ push @asol, $n->value()->{'number'}; $n = $n->parent(); } push @$solutions, \@asol; print "found solution: ".join(",",@asol)."\n"; return } my $sum = defined($v) ? $v->{'sum'} : 0; foreach(@$input){ # added this to make sure that we have combinations ra +ther than permutations: # see haukex's comment below next if( defined($v) && $_ < $v->{'number'} ); if( $sum + $_ <= $target ){ my $nn = Tree::Nary::Tiny->new( $n, # parent $_, # an id, nothing important { 'sum' => $sum + $_, 'number' => $_ }, # the data to hold ); find($nn, $input, $target, $solutions); } } }
tr.pl : here are all the solutions: 1)5,2,2,2,2,2 2)2,5,2,2,2,2 3)7,2,2,2,2 4)2,2,5,2,2,2 5)2,7,2,2,2 6)2,2,2,5,2,2 7)2,2,7,2,2 8)2,2,2,2,5,2 9)2,2,2,7,2 10)2,2,2,2,2,5 11)5,5,5 12)2,2,2,2,7

EDIT after soonix's comment below: I have added the next if ... statement to my code above like so (so above code now is corrected to give combinations rather than permutations (=order matters)):

foreach(@$input){ # added this to make sure that we have combinations ra +ther than permutations: # see haukex's comment below next if( defined($v) && $_ < $v->{'number'} ); ...

bw, bliako


In reply to Re: check possible combination of sum using given array by bliako
in thread check possible combination of sum using given array by dideod.yang

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.