aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCY Fung <fungcheokyin@gmail.com>2022-06-19 12:17:43 +0800
committerCY Fung <fungcheokyin@gmail.com>2022-06-19 12:17:43 +0800
commit9a4c469e476880da27c844a2037de73e93d38361 (patch)
tree21bc63a4979ccedc2d8e7a1dd711bb5b042b894a
parentd70c75981e688be5a8052024a98e88e9db6573bf (diff)
downloadperlweeklychallenge-club-9a4c469e476880da27c844a2037de73e93d38361.tar.gz
perlweeklychallenge-club-9a4c469e476880da27c844a2037de73e93d38361.tar.bz2
perlweeklychallenge-club-9a4c469e476880da27c844a2037de73e93d38361.zip
done Task 1
-rw-r--r--challenge-169/cheok-yin-fung/perl/ch-1.pl98
1 files changed, 82 insertions, 16 deletions
diff --git a/challenge-169/cheok-yin-fung/perl/ch-1.pl b/challenge-169/cheok-yin-fung/perl/ch-1.pl
index 35de02700c..5a82cb55f9 100644
--- a/challenge-169/cheok-yin-fung/perl/ch-1.pl
+++ b/challenge-169/cheok-yin-fung/perl/ch-1.pl
@@ -1,34 +1,100 @@
#!/usr/bin/perl
# The Weekly Challenge 169
-# Task 1 Brilliant Numbers
+# Task 1 Brilliant Numbers Version 3.0
+# See https://e7-87-83.github.io/coding/challenge_169.html
+# for a simpler version, up to first 241 brilliant numbers
+
+=pod DATA
+ number of 1-digit primes = 4
+ number of 2-digit primes = 21
+ number of 3-digit primes = 143
+ number of 4-digit primes = 1061
+ number of brilliant numbers from 1-digit primes = 10
+ number of brilliant numbers from 2-digit primes = 231
+ number of brilliant numbers from 3-digit primes = 10296 #OEIS limit
+ number of brilliant numbers from 4-digit primes = 563391
+=cut
+
use v5.24.0;
-use warnings;
+no warnings;
+use Math::Prime::Util qw/forprimes/;
+use POSIX;
-my $req = $ARGV[0] || 20;
+if (defined($ARGV[0])) {
+ say bn($ARGV[0]);
+}
+else {
+ say bn(20);
+}
-my @prime = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
- 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97);
-die "You're asking too many, or I am too little!\n"
- if $req > 241; # 21*20/2 + 21 + 4*3/2 + 4
+sub bn {
+ my $req = $_[0];
+ my $show_all_values = $req <= 50;
+ # show all values if the required number is small
-my $pt = ceil( ( sqrt(8*$req-79) +7 )/2 ) - 1;
+ my %prime = (1 => [2, 3, 5, 7],
+ 2 => [11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+ 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97],
+ 3 => [],
+ 4 => [],
+ );
-my @brilliant = (-1, 4, 6, 9, 10, 14, 15, 21, 25, 35, 49);
+ my $digit_len;
-my @temp;
+ given ($req) {
+ $digit_len = 1 when $_ <= 10;
+ $digit_len = 2 when $_ > 10 && $_ <= 241;
+ $digit_len = 3 when $_ > 241 && $_ <= 10537;
+ $digit_len = 4 when $_ > 10537 && $_ <= 573928;
+ die "You're asking too many!\n" when $_ > 573928;
+ }
+ eval { forprimes {push $prime{3}->@*, $_} 100, 999; } if $digit_len >= 3;
+ eval { forprimes {push $prime{4}->@*, $_} 1000,9999; } if $digit_len >= 4;
-for my $i (4..$pt) {
- for my $j ($i..24) {
- my $product = $prime[$i]*$prime[$j];
- push @temp, $product;
+ my $ind = $req;
+ $ind = $req-10 if $digit_len == 2;
+ $ind = $req-241 if $digit_len == 3;
+ $ind = $req-10537 if $digit_len == 4;
+ my $c = 3;
+ $c = ceil( ( sqrt(8*$ind+1) - 1 ) / 2 ) - 1;
+
+ my @temp;
+
+ for my $i (0..$c) {
+ for my $j ($i..scalar $prime{$digit_len}->@* - 1) {
+ my $product = $prime{$digit_len}[$i]*$prime{$digit_len}[$j];
+ push @temp, $product;
+ }
}
+ @temp = sort {$a<=>$b} @temp;
+ if ($show_all_values) {
+ my @brilliant = (-1, 4, 6, 9, 10, 14, 15, 21, 25, 35, 49);
+ push @brilliant, @temp;
+ say join "\n", @brilliant[1..$req];
+ return;
+ }
+ return $temp[$ind-1];
}
-push @brilliant, sort {$a<=>$b} @temp;
-say join ", ", @brilliant[1..$req];
+use Test::More tests=> 13;
+ok bn(60) == 841;
+ok bn(80) == 1079;
+ok bn(100) == 1369;
+ok bn(120) == 1763;
+ok bn(140) == 2231;
+ok bn(160) == 2809;
+ok bn(241) == 9409;
+ok bn(5000) == 197503;
+ok bn(10000) == 696191;
+ok bn(10416) == 851927;
+ok bn(10537) == 994009;
+ok bn(10538) == 1009*1009;
+ok bn(573928) == 9973*9973;
+
+# ref: OEIS:A078972