The algorithm I used to find that match is based on my imperfect recall of the one from Dominus's book mentioned by moritz. I'm sure it can be made much more elegant (for example, by not hard-wiring @list; and, less trivially, by not passing in $so_far_ref—I was just using it to print the diagnostics), but I think that this works:
use List::Util qw/first sum/; use strict; use warnings 'all'; my @list = (62, 83, 121, 281, 486, 734, 771, 854, 885, 1003); my $sum = sum(@list)/2; print "Trying for $sum with possibilities @list\n"; my @match = sum_to($sum, [], \@list); print @match ? "MATCH @match\n" : "No match\n"; sub sum_to { my ( $target, $so_far_ref, $possibilities_ref ) = @_; my @so_far = @$so_far_ref; my @possibilities = @$possibilities_ref; local $_; my $exact = first { $_ == $target } @possibilities; return $exact if $exact; local $_; my @indices = grep { $possibilities[$_] <= $target } 0 .. $#po +ssibilities; unless ( @indices ) { print "That branch didn't work.\n"; return; } my ( $sum, $try, @match ); INDEX: for my $index ( @indices ) { my @internal_possibilities = @possibilities; my @internal_so_far = @so_far; $try = splice @internal_possibilities, $index, 1; push @internal_so_far, $try; print "Guessed @internal_so_far; recursively trying fo +r ", $target - $try, " with possibilities @internal_possibilities\n"; @match = sum_to($target - $try, \@internal_so_far, \@i +nternal_possibilities) and last INDEX; } return @match ? ( $try, @match ) : (); }
In reply to Re^2: Divide array of integers into most similar value halves
by JadeNB
in thread Divide array of integers into most similar value halves
by Pepe
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |