aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrbaggy <js5@sanger.ac.uk>2022-10-03 13:41:01 +0100
committerdrbaggy <js5@sanger.ac.uk>2022-10-03 13:41:01 +0100
commit83bc52b1fca0b905f547fc6b30895794c6c88ee7 (patch)
tree7953493f78d380a6e49f1415323212a279a8347b
parentc2fd7944c7c124bc5f6eee823d88e0e5d4cce8e2 (diff)
downloadperlweeklychallenge-club-83bc52b1fca0b905f547fc6b30895794c6c88ee7.tar.gz
perlweeklychallenge-club-83bc52b1fca0b905f547fc6b30895794c6c88ee7.tar.bz2
perlweeklychallenge-club-83bc52b1fca0b905f547fc6b30895794c6c88ee7.zip
added methods speed is speedier
-rw-r--r--challenge-184/james-smith/README.md24
-rw-r--r--challenge-184/james-smith/perl/ch-1.pl24
-rw-r--r--challenge-184/james-smith/perl/ch-2.pl53
3 files changed, 79 insertions, 22 deletions
diff --git a/challenge-184/james-smith/README.md b/challenge-184/james-smith/README.md
index 9549dc68db..5a09b87a4d 100644
--- a/challenge-184/james-smith/README.md
+++ b/challenge-184/james-smith/README.md
@@ -39,13 +39,29 @@ The second we can try three approaches.
These are the codes:
```perl
-sub seq_number_substr { my $s = '00'; return map { ($s++).substr $_,2 } @_ }
-sub seq_number_subrep { my $s = '00'; return map { substr $_,0,2,$s++; $_ } @_ }
-sub seq_number_regexp { my $s = '00'; return map { s/../$s++/re } @_ }
+sub seq_no_regexp { my $s = '00'; map { s/../$s++/re } @_ }
+sub seq_no_subrep { my $s = '00'; map { substr $_, 0, 2, $s++; $_ } @_ }
+sub seq_no_substr { my $s = '00'; map { $s++ . substr $_,2 } @_ }
```
The ratio of speeds for the three methods is 3 : 2.25 : 1.
+Additionally in the code we show that the string increment is more efficient than the integer increment - with or without `sprintf`.
+
+```perl
+sub seq_no_sprint { my $s = 0; map { sprintf('%02d',$s++). substr $_,2 } @_ }
+sub seq_no_number { my $s = 0; map { (($s<10)?'0':'').$s++.substr $_,2 } @_ }
+```
+
+These are slower than the simple string increment version, the `sprintf` versions is 80% of the speed of the fast version, but the version with without `sprintf` is closer - running at around 95% of the speed of the fastest...
+
+
+This just goes to show you - even with a very simple problem - looking at different approaches can get you better performance..
+
+## Rule: regex are good except when they aren't! sprintf is your friend except when it isn't!
+
+Well general use of `sprintf` and regular expressions is good - it is often worth while for speed to forgo the niceties - here just proves it! We can with our domain knowledge optimize the code!
+
# Task 2 - Split array
***You are given list of strings containing 0-9 and a-z separated by space only. Write a script to split the data into two arrays, one for integers and one for alphabets only.***
@@ -65,7 +81,7 @@ sub split_array_code {
my (@r,@s);
for (@_) {
my(@n,@l);
- m{\d} ? push( @n,$_ ) : push( @l,$_ ) for split;
+ $_ lt '@' ? push( @n,$_ ) : push( @l,$_ ) for split;
push @r, \@n if @n;
push @s, \@l if @l;
}
diff --git a/challenge-184/james-smith/perl/ch-1.pl b/challenge-184/james-smith/perl/ch-1.pl
index 24540f5fb3..06513dbec6 100644
--- a/challenge-184/james-smith/perl/ch-1.pl
+++ b/challenge-184/james-smith/perl/ch-1.pl
@@ -13,18 +13,24 @@ my @TESTS = (
[ [ qw(pq1122 rs3334) ], '001122 013334' ],
);
-is( join( ' ', seq_number_substr(@{$_->[0]})), $_->[1] ) foreach @TESTS;
-is( join( ' ', seq_number_subrep(@{$_->[0]})), $_->[1] ) foreach @TESTS;
-is( join( ' ', seq_number_regexp(@{$_->[0]})), $_->[1] ) foreach @TESTS;
+is( join( ' ', seq_no_substr(@{$_->[0]})), $_->[1] ) foreach @TESTS;
+is( join( ' ', seq_no_sprint(@{$_->[0]})), $_->[1] ) foreach @TESTS;
+is( join( ' ', seq_no_number(@{$_->[0]})), $_->[1] ) foreach @TESTS;
+is( join( ' ', seq_no_subrep(@{$_->[0]})), $_->[1] ) foreach @TESTS;
+is( join( ' ', seq_no_regexp(@{$_->[0]})), $_->[1] ) foreach @TESTS;
done_testing();
cmpthese( 1_000_000, {
- 'substr' => sub { seq_number_substr(@{$_->[0]}) foreach @TESTS },
- 'subrep' => sub { seq_number_subrep(@{$_->[0]}) foreach @TESTS },
- 'regexp' => sub { seq_number_regexp(@{$_->[0]}) foreach @TESTS },
+ 'substr' => sub { seq_no_substr(@{$_->[0]}) foreach @TESTS },
+ 'sprint' => sub { seq_no_sprint(@{$_->[0]}) foreach @TESTS },
+ 'number' => sub { seq_no_number(@{$_->[0]}) foreach @TESTS },
+ 'subrep' => sub { seq_no_subrep(@{$_->[0]}) foreach @TESTS },
+ 'regexp' => sub { seq_no_regexp(@{$_->[0]}) foreach @TESTS },
});
-sub seq_number_substr { my $s = '00'; return map { ($s++).substr $_,2 } @_ }
-sub seq_number_subrep { my $s = '00'; return map { substr $_,0,2,$s++; $_ } @_ }
-sub seq_number_regexp { my $s = '00'; return map { s/../$s++/re } @_ }
+sub seq_no_regexp { my $s = '00'; map { s/../$s++/re } @_ }
+sub seq_no_subrep { my $s = '00'; map { substr $_, 0, 2, $s++; $_ } @_ }
+sub seq_no_sprint { my $s = 0; map { sprintf('%02d',$s++). substr $_,2 } @_ }
+sub seq_no_number { my $s = 0; map { (($s<10)?'0':'').$s++.substr $_,2 } @_ }
+sub seq_no_substr { my $s = '00'; map { $s++ . substr $_,2 } @_ }
diff --git a/challenge-184/james-smith/perl/ch-2.pl b/challenge-184/james-smith/perl/ch-2.pl
index da14494bde..f06ec32a29 100644
--- a/challenge-184/james-smith/perl/ch-2.pl
+++ b/challenge-184/james-smith/perl/ch-2.pl
@@ -13,26 +13,61 @@ my @TESTS = (
[ '1 2', 'p q r', 's 3', '4 5 t' ],
);
-print Dumper split_array_map( @{$_} ) for @TESTS;
-print Dumper split_array_code( @{$_} ) for @TESTS;
+print Dumper split_array_map( @{$_} ) for @TESTS;
+print Dumper split_array_closure( @{$_} ) for @TESTS;
+print Dumper split_array_closure_no_regex( @{$_} ) for @TESTS;
+print Dumper split_array_code( @{$_} ) for @TESTS;
+print Dumper split_array_code_no_regex( @{$_} ) for @TESTS;
+
+cmpthese( 100_000, {
+ 'map' => sub { split_array_map( @{$_} ) for @TESTS },
+ 'closure' => sub { split_array_closure( @{$_} ) for @TESTS },
+ 'closure_no_regex' => sub { split_array_closure_no_regex( @{$_} ) for @TESTS },
+ 'code' => sub { split_array_code( @{$_} ) for @TESTS },
+ 'code_no_regex' => sub { split_array_code_no_regex( @{$_} ) for @TESTS },
+});
sub split_array_map {
return [
- [ grep { @{$_} } map { [ grep { m/\d/ } split ] } @_ ],
- [ grep { @{$_} } map { [ grep { m/\D/ } split ] } @_ ],
+ [ grep { @{$_} } map { [ grep { /\d/ } split ] } @_ ],
+ [ grep { @{$_} } map { [ grep { /\D/ } split ] } @_ ],
]
}
-cmpthese( 100_000, {
- 'map' => sub { split_array_map( @{$_} ) for @TESTS },
- 'code' => sub { split_array_code( @{$_} ) for @TESTS },
-});
+sub split_array_closure {
+ sub {
+ [ [ map { @{$_->[0]} ? $_->[0] : () } @_ ],
+ [ map { @{$_->[1]} ? $_->[1] : () } @_ ], ]
+ }->(
+ map { my $r=[[],[]]; push @{$r->[/[a-z]/]}, $_ for split; $r } @_
+ );
+}
+
+sub split_array_closure_no_regex {
+ sub {
+ [ [ map { @{$_->[0]} ? $_->[0] : () } @_ ],
+ [ map { @{$_->[1]} ? $_->[1] : () } @_ ], ]
+ }->(
+ map { my $r=[[],[]]; push @{$r->[$_ gt '@']}, $_ for split; $r } @_
+ );
+}
sub split_array_code {
my (@r,@s);
for (@_) {
my(@n,@l);
- m{\d} ? push( @n,$_ ) : push( @l,$_ ) for split;
+ m/\d/ ? push @n, $_ : push @l, $_ for split;
+ push @r, \@n if @n;
+ push @s, \@l if @l;
+ }
+ [\@r,\@s]
+}
+
+sub split_array_code_no_regex {
+ my (@r,@s);
+ for (@_) {
+ my(@n,@l);
+ '@' gt $_ ? push @n, $_ : push @l, $_ for split;
push @r, \@n if @n;
push @s, \@l if @l;
}