aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2020-10-25 12:35:28 +0000
committerGitHub <noreply@github.com>2020-10-25 12:35:28 +0000
commitd9b1a8fb57bde164178d562e599bf375a60eb38e (patch)
tree9d229513cef60a83a40b0899d41c04864660ccce
parenta48ff2cd3f70a00492b6ab95394af1efa68e52c1 (diff)
parent357753f6fc4471450af9755b156409b3be79a1c0 (diff)
downloadperlweeklychallenge-club-d9b1a8fb57bde164178d562e599bf375a60eb38e.tar.gz
perlweeklychallenge-club-d9b1a8fb57bde164178d562e599bf375a60eb38e.tar.bz2
perlweeklychallenge-club-d9b1a8fb57bde164178d562e599bf375a60eb38e.zip
Merge pull request #2601 from jo-37/contrib
Solutions to challenge 083
-rwxr-xr-xchallenge-083/jo-37/perl/ch-1.pl18
-rwxr-xr-xchallenge-083/jo-37/perl/ch-2.pl62
2 files changed, 80 insertions, 0 deletions
diff --git a/challenge-083/jo-37/perl/ch-1.pl b/challenge-083/jo-37/perl/ch-1.pl
new file mode 100755
index 0000000000..ccacecf211
--- /dev/null
+++ b/challenge-083/jo-37/perl/ch-1.pl
@@ -0,0 +1,18 @@
+#!/usr/bin/perl
+
+use Test2::V0;
+
+sub inner_length {
+ local $_ = shift;
+
+ # Split the string into words, pick all between the first and the
+ # last, join them and return the length.
+ length join '', splice @{[split qr{\s+}]}, 1, -1;
+
+}
+
+is inner_length('The Weekly Challenge'), 6, 'Example 1';
+is inner_length('The purpose of our lives is to be happy'), 23, 'Example 2';
+is inner_length('nothing intermediate'), 0, 'Out of scope: no inner words';
+
+done_testing;
diff --git a/challenge-083/jo-37/perl/ch-2.pl b/challenge-083/jo-37/perl/ch-2.pl
new file mode 100755
index 0000000000..6a3d578b7b
--- /dev/null
+++ b/challenge-083/jo-37/perl/ch-2.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+
+use Test2::V0;
+use List::Util 'sum';
+use List::MoreUtils 'pairwise';
+use Math::Utils 'copysign';
+use Benchmark 'cmpthese';
+
+# Count the minimum number of sign flips to achieve the mimimum signed
+# sum. The efford to find the solution with this brute-force
+# implementation grows exponentially with the length of the given list
+# of numbers. For larger lists a smarter approach is required.
+sub minflips {
+ my ($minsum, $minflips) = ('inf');
+ my $len = @_;
+
+ # Take the sign flips from the ones in the binary representation of
+ # a counter.
+ foreach (map {sprintf "%0${len}b", $_} 1 .. 2**$len - 2) {
+
+ # Apply ones in $_ as negative signs to the given numbers and
+ # sum these.
+ my $sum = sum pairwise {copysign $b, -$a} @{[split '']}, @_;
+
+ # Skip sums out of range
+ next if $sum < 0 || $sum > $minsum;
+
+ # Count the number of flips, i.e. the number of ones in $_.
+ my $flips = y/1/1/;
+
+ # A smaller sum is taken as the new best solution or
+ # a sum achieved with less flips.
+ ($minsum, $minflips) = ($sum, $flips)
+ if $sum < $minsum || $flips < $minflips;
+ }
+
+ $minflips;
+}
+
+is minflips(3, 10, 8), 1, 'Example 1';
+is minflips(12, 2, 10), 1, 'Example 2';
+is minflips(2, 3, 5, 9, 4), 2;
+is minflips(4, 1, 1, 1), 3;
+is minflips(2, 1, 1, 1), 1;
+
+SKIP: {
+ skip 'optional benchmark', 3;
+ cmpthese 1, {
+ 15 => sub {is minflips(1 .. 15), 5},
+ 16 => sub {is minflips(1 .. 16), 5},
+ 17 => sub {is minflips(1 .. 17), 6}
+ }
+
+ # s/iter 17 16 15
+ # 17 2.33 -- -54% -78%
+ # 16 1.08 116% -- -53%
+ # 15 0.510 357% 112% --
+ #
+}
+
+done_testing;
+