diff options
| author | drbaggy <js5@sanger.ac.uk> | 2021-10-04 13:57:36 +0100 |
|---|---|---|
| committer | drbaggy <js5@sanger.ac.uk> | 2021-10-04 13:57:36 +0100 |
| commit | aa3d1f5a4960500481ae284124a31fe241908092 (patch) | |
| tree | 819744de237029c560dc68819ac0f7a48a4367f3 | |
| parent | 8426cd2ce320586f8af64e0c4d33e29b72275eea (diff) | |
| download | perlweeklychallenge-club-aa3d1f5a4960500481ae284124a31fe241908092.tar.gz perlweeklychallenge-club-aa3d1f5a4960500481ae284124a31fe241908092.tar.bz2 perlweeklychallenge-club-aa3d1f5a4960500481ae284124a31fe241908092.zip | |
newer more compact version of smith numbers
| -rw-r--r-- | challenge-133/james-smith/perl/ch-2.pl | 68 |
1 files changed, 32 insertions, 36 deletions
diff --git a/challenge-133/james-smith/perl/ch-2.pl b/challenge-133/james-smith/perl/ch-2.pl index 5f7bed5d67..6163b97940 100644 --- a/challenge-133/james-smith/perl/ch-2.pl +++ b/challenge-133/james-smith/perl/ch-2.pl @@ -4,46 +4,42 @@ use strict; use warnings; use feature qw(say); -use Data::Dumper qw(Dumper); - -my @primes = (2,3); -my %ds; -my %comp; -my @t = smith_numbers(@ARGV?$ARGV[0]:100); -print "@t\n"; - -sub smith_numbers { - my $C = shift; - my @sn = (); - my $n = 4; - while(1) { - my @q = prime_factors($n); - if( @q ) { - my $t = sum_digits($n); - $t-= sum_digits($_) foreach @q; - unless($t) { - push @sn, $n; - return @sn if @sn==$C; - } - } - $n++; - } -} -sub sum_digits { - return $ds{$_[0]} if exists $ds{$_[0]}; - my $t = 0; - $t+= $_ foreach split //, $_[0]; - return $ds{$_[0]} = $t; -} +my(@primes,%ds,%comp) = (2,3); +say $_ foreach smith_numbers(@ARGV?$ARGV[0]:100); +#say $_ foreach smith_numbers_readable(@ARGV?$ARGV[0]:100); + +sub sum { my $t = 0; $t+=$_ foreach @_; $t; } +sub sum_digits { return $ds{$_[0]} ||= sum split //, $_[0]; } sub prime_factors { my $N = shift; - my @factors; - foreach (@primes) { - return @{ $comp{$N} = [ $_, exists $comp{$N/$_}? @{$comp{$N/$_}} : $N/$_ ] } unless $N % $_; - } - push @primes,$N; + + ## If we are composite then store the factors for the composite and return... + ( $N % $_) or ( return @{ $comp{$N} = [ $_, @{$comp{ $N / $_ }||[$N/$_]}] } ) foreach @primes; + + ## Otherwise we are prime so add to primes and return nothing.... + push @primes, $N; return; } +sub smith_numbers_readable { + my ( $C, $n, @sn ) = (shift,3); + while($n++) { ## $n starts at 4 ... lowest possible smith number is 4 ( composite or 2 x 2 ) + next unless my @q = prime_factors($n); ## Must be composite as prime_factors returns list... + next if sum_digits($n) - sum map { sum_digits $_ } @q; ## Digit sums are equal... + push @sn, $n; + return @sn if @sn==$C; + } +} + + +sub smith_numbers { ## This is the short form! using && + my ( $C, $n, @sn ) = (shift,3); + ( sum_digits( $n ) - sum map { sum_digits $_ } prime_factors( $n ) ) || + ( push @sn, $n ) && + ( @sn == $C ) && + ( return @sn ) while $n++; +} + + |
