diff options
| -rw-r--r-- | challenge-144/james-smith/perl/ch-1.pl | 55 | ||||
| -rw-r--r-- | challenge-144/james-smith/perl/ch-2.pl | 44 |
2 files changed, 89 insertions, 10 deletions
diff --git a/challenge-144/james-smith/perl/ch-1.pl b/challenge-144/james-smith/perl/ch-1.pl index 97fe5b4e33..39a78002de 100644 --- a/challenge-144/james-smith/perl/ch-1.pl +++ b/challenge-144/james-smith/perl/ch-1.pl @@ -8,16 +8,55 @@ use Test::More; use Benchmark qw(cmpthese timethis); use Data::Dumper qw(Dumper); +my($C,$I) = (100,100_000); +#say foreach sp_loop(100);exit; +cmpthese( 100, { + 'sp' => sub { semiprimes($I); }, + 'sl' => sub { sp_loop( $I); }, + 'sm' => sub { sp_map( $I); }, +}); -my $N = 1000; -my @primes = (2); -my @semi_primes = (4); +sub sp_loop { + my $N = shift; + my @p; my %ph; + my @sp; + foreach my $t ( 2..$N ) { + my $prime = 1; + foreach(@p) { + next if $t%$_; + $prime = 0; + (push @sp,$t) && (last) if exists $ph{$t/$_}; + } + if( $prime ) { + push @p,$t; $ph{$t}=1; + } + } + @sp; +} + +sub sp_map { + my $N = shift; + my @primes = (2); + my @semi_primes = (4); -foreach my $p ( map { 1+2*$_ } 1..($N/4) ) { - map { ($p%$_)||(next) } @primes; - push @primes,$p; - push @semi_primes,grep {$_<=$N} map{$p*$_} @primes; + foreach my $p ( map { 1+2*$_ } 1..($N/4) ) { + map { ($p%$_)||(next) } @primes; + push @primes,$p; + push @semi_primes,grep {$_<=$N} map{$p*$_} @primes; + } + sort {$a<=>$b} @semi_primes; } -say for sort {$a<=>$b} @semi_primes; +sub semiprimes { + my $N = shift; + my @primes = (2); + my @semi_primes = (4); + + foreach my $p ( map { 1+2*$_ } 1..($N/4) ) { + map { ($p%$_)||(next) } @primes; + push @primes,$p; + ($p*$_>$N) ? (next) : (push @semi_primes,$p*$_) for @primes; + } + sort {$a<=>$b} @semi_primes; +} diff --git a/challenge-144/james-smith/perl/ch-2.pl b/challenge-144/james-smith/perl/ch-2.pl index 024a36197b..a3a2b2590e 100644 --- a/challenge-144/james-smith/perl/ch-2.pl +++ b/challenge-144/james-smith/perl/ch-2.pl @@ -8,13 +8,53 @@ use Test::More; use Benchmark qw(cmpthese timethis); use Data::Dumper qw(Dumper); -my (@seq,%seq_hash); - +say "@{[ ulam_expanded(1,2,1000) ]}"; +say "@{[ ulam_map(1,2,1000) ]}"; +say "@{[ ulam(1,2,1000) ]}"; +say "@{[ ulam_expanded(1,2,100) ]}"; +say "@{[ ulam_map(1,2,100) ]}"; say "@{[ ulam(1,2,100) ]}"; say "@{[ ulam(2,3,100) ]}"; say "@{[ ulam(2,5,100) ]}"; +cmpthese( 200, { + 'u' => sub { ulam(1,2,1000) }, +# 'm' => sub { ulam_map(1,2,1000) }, + 'e' => sub { ulam_expanded(1,2,1000) }, +} ); + sub ulam { + my%h=map{$_,$_}my@s=($_[0],my$n=$_[1]); + for(my$c=0;@s<$_[2];++$n,$c=0){ + ($_>=$n/2)?(last):($h{$n-$_})&&$c++&&(last) for@s; + push@s,$h{$n}=$n if$c==1; + } + @s; +} + +sub ulam_expanded { + my ($m, $n, $l) = @_; + my @seq = ($m,$n); + my %seq_hash = ( $m => 1, $n => 1 ); + while( @seq < $l ) { + $n++; + my $count = 0; + foreach ( @seq ) { + last if $_ >= $n/2; + if( exists $seq_hash{ $n - $_ } ) { + $count++; + last if $count>1; + } + } + if( $count == 1 ) { + push @seq, $n; + $seq_hash{ $n } = 1; + } + } + return @seq; +} + +sub ulam_map { my%seq_hash=map{$_,$_}my@seq=($_[0],my$n=$_[1]); for(;scalar @seq<$_[2];++$n){ push@seq,$seq_hash{$n}=$n if 1==grep{2*$_<$n&&$seq_hash{$n-$_}}@seq; |
