From ff3c07c3e4409c8d507b3e69496c690b58de524d Mon Sep 17 00:00:00 2001 From: Steve Rogerson Date: Fri, 23 Oct 2020 12:25:40 +0100 Subject: Add ch-2.pl --- challenge-083/steve-rogerson/perl/ch-2.pl | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 challenge-083/steve-rogerson/perl/ch-2.pl 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..bfa393a3c0 --- /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; -- cgit From ed3a0647f1f420a5862498c5b9d17efd68fb0de3 Mon Sep 17 00:00:00 2001 From: Steve Rogerson Date: Sun, 25 Oct 2020 08:22:00 +0000 Subject: I was allowing 0 as one of the 'positive numbers' --- challenge-083/steve-rogerson/perl/ch-2.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-083/steve-rogerson/perl/ch-2.pl b/challenge-083/steve-rogerson/perl/ch-2.pl index bfa393a3c0..726e650d97 100644 --- a/challenge-083/steve-rogerson/perl/ch-2.pl +++ b/challenge-083/steve-rogerson/perl/ch-2.pl @@ -17,7 +17,7 @@ use List::MoreUtils qw{pairwise}; my @NUMBERS = @ARGV; -if ( @NUMBERS == 0 or grep { !looks_like_number($_) || $_ < 0 } @NUMBERS ) { +if ( @NUMBERS == 0 or grep { !looks_like_number($_) || $_ <= 0 } @NUMBERS ) { die "Was expecting a list of positive numbers"; } -- cgit