diff options
| author | drbaggy <js5@sanger.ac.uk> | 2022-10-03 13:41:01 +0100 |
|---|---|---|
| committer | drbaggy <js5@sanger.ac.uk> | 2022-10-03 13:41:01 +0100 |
| commit | 83bc52b1fca0b905f547fc6b30895794c6c88ee7 (patch) | |
| tree | 7953493f78d380a6e49f1415323212a279a8347b | |
| parent | c2fd7944c7c124bc5f6eee823d88e0e5d4cce8e2 (diff) | |
| download | perlweeklychallenge-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.md | 24 | ||||
| -rw-r--r-- | challenge-184/james-smith/perl/ch-1.pl | 24 | ||||
| -rw-r--r-- | challenge-184/james-smith/perl/ch-2.pl | 53 |
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; } |
