aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrbaggy <js5@sanger.ac.uk>2021-10-04 13:57:36 +0100
committerdrbaggy <js5@sanger.ac.uk>2021-10-04 13:57:36 +0100
commitaa3d1f5a4960500481ae284124a31fe241908092 (patch)
tree819744de237029c560dc68819ac0f7a48a4367f3
parent8426cd2ce320586f8af64e0c4d33e29b72275eea (diff)
downloadperlweeklychallenge-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.pl68
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++;
+}
+
+