diff options
| author | drbaggy <js5@sanger.ac.uk> | 2022-04-04 19:41:37 +0100 |
|---|---|---|
| committer | drbaggy <js5@sanger.ac.uk> | 2022-04-04 19:41:37 +0100 |
| commit | d0335bccd0294b93ca8539b22390c0064baa3193 (patch) | |
| tree | 264ee4c1a0cdf1ced8e90d0be0d8b97ec7c15610 | |
| parent | 9bd3a76992e2c016e85625c4d94969ec05ca7a43 (diff) | |
| download | perlweeklychallenge-club-d0335bccd0294b93ca8539b22390c0064baa3193.tar.gz perlweeklychallenge-club-d0335bccd0294b93ca8539b22390c0064baa3193.tar.bz2 perlweeklychallenge-club-d0335bccd0294b93ca8539b22390c0064baa3193.zip | |
faster code
| -rw-r--r-- | challenge-159/james-smith/perl/ch-2.pl | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/challenge-159/james-smith/perl/ch-2.pl b/challenge-159/james-smith/perl/ch-2.pl index 5c86128a4d..7d22c8df6d 100644 --- a/challenge-159/james-smith/perl/ch-2.pl +++ b/challenge-159/james-smith/perl/ch-2.pl @@ -13,26 +13,65 @@ my @TESTS = ( [ 5, -1 ], [ 10, 1 ], [ 20, 0 ], +## The following are good examples where the second algorithm works well! + [ 2, -1 ], + [ 6, 1 ], + [ 30, -1 ], + [ 210, 1 ], + [ 2310, -1 ], + [ 30030, 1 ], + [ 510510, -1 ], + [ 9699690, 1 ], + [ 6895531, -1 ], + [ 206865930, 1 ], + [ 223092870, -1 ], + [ 6469693230, 1 ], ); -is( moebius( $_->[0]), $_->[1] ) foreach @TESTS; -is( moebius_exp($_->[0]), $_->[1] ) foreach @TESTS; +warn "exp"; +is( moebius_exp( $_->[0] ), $_->[1] ) for @TESTS; +warn "opt"; +is( moebius_div_opt( $_->[0] ), $_->[1] ) for @TESTS; +timethis( 500_000, sub { moebius_div_opt( $_->[0] ) for @TESTS } ); +warn "div"; +is( moebius_div( $_->[0] ), $_->[1] ) for @TESTS; +timethis( 100, sub { moebius_div( $_->[0] ) for @TESTS } ); +warn "dumb"; +is( moebius( $_->[0] ), $_->[1] ) for @TESTS; +timethis( 5, sub { moebius( $_->[0] ) for @TESTS } ); done_testing(); sub moebius { my ($n,$p,$r) = (shift,1,1); return -1 if is_prime($n); - $n%($p**2) ? ($n%$p && ($r=-$r)) : return 0 while ($p = next_prime $p) < $n; + $n%($p**2) ? ($n%$p || ($r=-$r)) : return 0 while ($p = next_prime $p) <= $n; + $r; +} + +sub moebius_div { + my ($n,$p,$r) = (shift,1,1); + return -1 if is_prime $n; + $n%($p**2) ? ( $n%$p || ($r=-$r,$n/=$p)) : return 0 while ($p = next_prime $p) && $n>1; + $r; +} + +sub moebius_div_opt { + my ($n,$p,$r) = (shift,1,1); + return -1 if is_prime $n; + $n%$p || ($r=-$r,$n/=$p) && ( $n%$p ? ( (is_prime $n) && (return -$r) ) : return 0 ) while ($p = next_prime $p)**2 <= $n; $r; } sub moebius_exp { my ($n,$p,$r) = (shift,1,1); - return -1 if is_prime($n); - while( ($p = next_prime $p ) < $n ) { - return 0 unless $n%($p**2); - $r=-$r unless $n%$p; + return -1 if is_prime $n; + while( ($p = next_prime $p )**2 <= $n ) { + next if $n%$p; + $r=-$r; + $n/=$p; + return 0 unless $n%$p; + return -$r if is_prime $n; } $r; } |
