diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2020-10-25 12:03:10 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-25 12:03:10 +0000 |
| commit | 50e377dbe670cb1cce207911f39327f4e4d24c5b (patch) | |
| tree | ef28a19aba8d98a4815b2ac7069f08463c2bc1a8 | |
| parent | df5be3e1dc1b348b4ec7309e0441bfccc2645992 (diff) | |
| parent | ed3a0647f1f420a5862498c5b9d17efd68fb0de3 (diff) | |
| download | perlweeklychallenge-club-50e377dbe670cb1cce207911f39327f4e4d24c5b.tar.gz perlweeklychallenge-club-50e377dbe670cb1cce207911f39327f4e4d24c5b.tar.bz2 perlweeklychallenge-club-50e377dbe670cb1cce207911f39327f4e4d24c5b.zip | |
Merge pull request #2597 from yewtc/master
Add ch-2.pl
| -rw-r--r-- | challenge-083/steve-rogerson/perl/ch-2.pl | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/challenge-083/steve-rogerson/perl/ch-2.pl b/challenge-083/steve-rogerson/perl/ch-2.pl new file mode 100644 index 0000000000..726e650d97 --- /dev/null +++ b/challenge-083/steve-rogerson/perl/ch-2.pl @@ -0,0 +1,47 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use utf8; +use 5.028; +use Scalar::Util 'looks_like_number'; +use List::Util qw{sum}; +use List::MoreUtils qw{pairwise}; +# +# We get a list of positive numbers from the command line and "do the flip" +# +# I tried to think of nifty algorithm and failed, so going for brute force. +# One observation though is that if we change every sign, then the sign +# of the total will change, we only need 2^(N-1) values, look for +# the lowest non-zero absolute value and flip all signs if it's less than 0. +# + +my @NUMBERS = @ARGV; + +if ( @NUMBERS == 0 or grep { !looks_like_number($_) || $_ <= 0 } @NUMBERS ) { + die "Was expecting a list of positive numbers"; +} + +my $nums = int @NUMBERS; +if ( int $nums == 1 ) { + say $NUMBERS[0]; +} +my $smallest = sum(@NUMBERS); +my @best_bits= (1) x @NUMBERS; +for my $i ( 0 .. 2**( $nums - 1 ) ) { + my $pattern = sprintf("%0${nums}b", $i); # get pattern of 0s and 1s. + my @bits= split //, $pattern; # split into array + # 2*$a-1 turns 0 or 1 into -1 and 1 respectively. + # then bring out the heavy guns.. + my $sum =sum ( pairwise { (2*$a -1) * $b} @bits, @NUMBERS); + # We don't care about sign here. + if (abs($sum) != 0 and abs($sum) < abs($smallest)) { + @best_bits = @bits; # Remember the best so far. + $smallest = $sum; + } +} +# is the smallest is < 0 we need to flip all signs. +my $flip = ($smallest>0)*2-1; + +my @flipped_numbers = pairwise { $flip * (2*$a -1) * $b} @best_bits, @NUMBERS; +say "@flipped_numbers"; +say $flip * $smallest; |
