aboutsummaryrefslogtreecommitdiff
path: root/challenge-109/james-smith
diff options
context:
space:
mode:
authordrbaggy <js5@sanger.ac.uk>2021-04-21 00:56:59 +0100
committerdrbaggy <js5@sanger.ac.uk>2021-04-21 00:56:59 +0100
commitcede56d142cf3553f6e96ecdbc7ba4ca142ca27f (patch)
treecefa94e3b1cf569ddd7eb89466639baf2943f432 /challenge-109/james-smith
parentf89db52bf23d2277b9fc3c3007d20beb614e329c (diff)
downloadperlweeklychallenge-club-cede56d142cf3553f6e96ecdbc7ba4ca142ca27f.tar.gz
perlweeklychallenge-club-cede56d142cf3553f6e96ecdbc7ba4ca142ca27f.tar.bz2
perlweeklychallenge-club-cede56d142cf3553f6e96ecdbc7ba4ca142ca27f.zip
push changes to chowla so that we can compare performances with Benchmark
Diffstat (limited to 'challenge-109/james-smith')
-rw-r--r--challenge-109/james-smith/perl/ch-1.pl58
1 files changed, 51 insertions, 7 deletions
diff --git a/challenge-109/james-smith/perl/ch-1.pl b/challenge-109/james-smith/perl/ch-1.pl
index 2c38afe0c4..1b89226a6a 100644
--- a/challenge-109/james-smith/perl/ch-1.pl
+++ b/challenge-109/james-smith/perl/ch-1.pl
@@ -5,18 +5,62 @@ use strict;
use warnings;
use feature qw(say);
use Test::More;
+use Benchmark qw(cmpthese);
-my @answer = (9999, 0, 0, 0, 2, 0, 5, 0, 6, 3, 7, 0, 15, 0, 9, 8, 14, 0, 20, 0, 21);
+my @answer = qw(9999
+ 0 0 0 2 0 5 0 6 3 7
+ 0 15 0 9 8 14 0 20 0 21
+);
-is( chowla($_), $answer[ $_ ] ) foreach 1..20;
+is( chowla_map($_), $answer[ $_ ] ) foreach 1..20;
+is( chowla_for($_), $answer[ $_ ] ) foreach 1..20;
done_testing();
-sub my_function {
- sub chowla {
- my ($t,$n) = (0,@_);
- return ( map { (($n%$_) || ($t+=$_)) && () } 2..$n-1 ), $t;
- }
+## We will quickly run benchmarking...
+## This suggests the for loop to be approximately 40-50%
+## faster than the map solution...
+## It is also 9 characters shorter...
+
+cmpthese(1_000_000, {
+ 'Map' => sub { chowla_map($_) foreach 1..20; },
+ 'For' => sub { chowla_for($_) foreach 1..20; },
+});
+
+##
+## Rate Map For
+## Map 38670/s -- -33%
+## For 57670/s 49% --
+##
+
+sub chowla_map {
+ my ($t,$n) = (0,@_);
+## First attempt - the one-liner is to write this as a map,
+## we add $t at the end which is the value returned
+ ( map { (($n%$_) || ($t+=$_)) && () } 2..$n-1 ), $t;
+}
+
+sub chowla_for {
+ my($t,$n)=(0,@_);
+
+ ## This time we won't write this as a nasty map/reduce solution...
+ ##
+ ## Just a for loop;
+ ##
+ ## Notes:
+ ## * To allow for an "unless" in a postfix loop, we rewrite this
+ ## by noting:
+ ## unless( $condition ) { fun(); }
+ ## can be rewritten as:
+ ## ($condition)||($fun())
+ ## * in perl `foreach` and `for` are synonymous - so we can shorten
+
+ ($n%$_)||($t+=$_) for 2..$n-1;
+
+ ## Now a quick "shortening" - if there is no specific return
+ ## statement - we can just omit the return in the last statement...
+
+ $t;
}