aboutsummaryrefslogtreecommitdiff
path: root/challenge-107
diff options
context:
space:
mode:
authordrbaggy <js5@sanger.ac.uk>2021-04-06 09:24:02 +0100
committerdrbaggy <js5@sanger.ac.uk>2021-04-06 09:24:02 +0100
commit2b79dbff795727e5ee8227de995c0cc27a92db34 (patch)
tree447e9f10632f5390cf8250db66fd0f882f9e990d /challenge-107
parenta3af256668c8a6d723e5596ec1f7c6d15c87904f (diff)
downloadperlweeklychallenge-club-2b79dbff795727e5ee8227de995c0cc27a92db34.tar.gz
perlweeklychallenge-club-2b79dbff795727e5ee8227de995c0cc27a92db34.tar.bz2
perlweeklychallenge-club-2b79dbff795727e5ee8227de995c0cc27a92db34.zip
Documentation, some more golfing on ch-2 and an example of the difference between use & require.
Diffstat (limited to 'challenge-107')
-rw-r--r--challenge-107/james-smith/perl/Calc_Require.pm (renamed from challenge-107/james-smith/perl/Calc.pm)0
-rw-r--r--challenge-107/james-smith/perl/Calc_Use.pm11
-rw-r--r--challenge-107/james-smith/perl/ch-1.pl84
-rw-r--r--challenge-107/james-smith/perl/ch-2.pl12
4 files changed, 105 insertions, 2 deletions
diff --git a/challenge-107/james-smith/perl/Calc.pm b/challenge-107/james-smith/perl/Calc_Require.pm
index 4123090fde..4123090fde 100644
--- a/challenge-107/james-smith/perl/Calc.pm
+++ b/challenge-107/james-smith/perl/Calc_Require.pm
diff --git a/challenge-107/james-smith/perl/Calc_Use.pm b/challenge-107/james-smith/perl/Calc_Use.pm
new file mode 100644
index 0000000000..ee777771ca
--- /dev/null
+++ b/challenge-107/james-smith/perl/Calc_Use.pm
@@ -0,0 +1,11 @@
+package Calc_Use;
+
+use strict;
+use warnings;
+
+sub new { bless {}, shift; }
+sub add { }
+sub mul { }
+sub div { }
+
+1;
diff --git a/challenge-107/james-smith/perl/ch-1.pl b/challenge-107/james-smith/perl/ch-1.pl
index 753fe48f64..fff417572c 100644
--- a/challenge-107/james-smith/perl/ch-1.pl
+++ b/challenge-107/james-smith/perl/ch-1.pl
@@ -43,3 +43,87 @@ while( ++$c && @res<3 ) {
say "@res";
+## We can reduce this further - by rewriting the inner if with
+## using the && trick. && is evaluated lazily - so that if
+## the left hand side is false then the right hand side is not
+## evaluated.
+##
+## So if($x) { y() } can be written as $x && y();
+##
+## Similarly - unless($x) { y() } can be written $x || y()] and
+## if($x) { y() } else { z() } can be written $x ? y() : z()
+##
+## This means we can make the statement inside the loop a single
+## statement and postfix the while...
+
+($c,@res) = 0;
+
+( $c == join q(),
+ map { scalar @{[ $c=~m{($_)}g ]} }
+ 0 .. -1 + length $c
+) && push @res, $c while ++$c && @res<3;
+
+say "@res";
+
+## Note we have to wrap the "condition" in brackets to force
+## it to be evaluated before the && as o/w the line ends in
+## 0 .. -1 + length( $x && push @res, $c);
+##
+## This is why we right the "yoda" looking -1 + length $c as
+## if you write length $c - 1 this evaluates to length($c-1)...
+##
+## I wouldn't do this in "normal" code as I think it can get
+## confusing $x && f() is not obviously a piece of logic &
+## especially if f() has implicit side effects as here
+
+## If we don't want to capture the values - but just display
+## the results - we can drop this into a perl 1-liner on the
+## command liner
+
+=cut
+perl -E '($c-join"",map{0+@{[$c=~/($_)/g]}}0..-1+length$c)||++$n&&say$c while++$c&&$n<3'
+
+# or
+
+perl -E '($c-join"",map{0+(@Q=$c=~/($_)/g)}0..-1+length$c)||++$n&&say$c while++$c&&$n<3'
+=cut
+
+## You will note so slightly different tricks here...
+## (Mainly because we haven't enabled strict!!)
+##
+## * We use -E this enables more modern perl features - including say!
+##
+## * We don't collect results - and we just keep a counter - this time
+## we use || and && in the "logic"...
+##
+## We know ++$n is always going to be true (it starts of
+## explicitly) and so we always run say$c if we get to the ++$n..
+##
+## Note here - this is a place where it is important to choose ++$n
+## rather than the more common $n++, as the first evaluates to 0
+## the first time it is invoked - meaning we would skip the first
+## answer...
+##
+## * We show a different trick to count the elements of the list.
+##
+## Rather than using the scalar @{[ ]} trick to convert it to
+## an array we store it in a variable which makes it an array
+## we can then get the length of the array.
+##
+## As we are keeping the code short - we can replace the keyword
+## scalar with a simple 0+ which forces the array to be converted
+## into a scalar (and hence returns the length)
+##
+## * To gain another character as the equality is numeric we can
+## rewrite if($a==$b) { f() } as ($a-$b)||f().
+## $a-$b is non-zero (true) if $a!=$b so we can rewrite:
+##
+## if( $a == $b ) { f() }
+##
+## as
+##
+## unless( $a - $b ) { f() }
+##
+## which we know we mentioned we could rewrite as:
+##
+## ($a-$b) || f()
diff --git a/challenge-107/james-smith/perl/ch-2.pl b/challenge-107/james-smith/perl/ch-2.pl
index 7895f22840..7cb40e74a7 100644
--- a/challenge-107/james-smith/perl/ch-2.pl
+++ b/challenge-107/james-smith/perl/ch-2.pl
@@ -6,11 +6,19 @@ use warnings;
use feature qw(say);
#use Test::More;
use lib '.';
-use Calc;
+require Calc_Require;
+use Calc_Use;
## %{class}:: contains a list of the methods for the class,
## so we can just dump these (to make it deterministic) we
## sort first....
+##
+## We "import" the classes in two ways... use & require.
+##
+## By "require"ing the class - we don't get the additional
+## import method added to the class... (and so get the same
+## list of fns as in the question)
-say join "\n", sort keys %Calc::;
+say "Calc_Require:\n",join "\n ", sort keys %Calc_Require::;
+say "Calc_Use:\n",join "\n ", sort keys %Calc_Use::;