aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordcw <d.white@imperial.ac.uk>2022-04-03 20:22:58 +0100
committerdcw <d.white@imperial.ac.uk>2022-04-03 20:22:58 +0100
commitbe8ff67228ea6566aa907e3d2620b15e54ca8a01 (patch)
treee2ac77322830e9b56d66bc7e543c78e3a49a58ba
parentca99c2fbb53988ba726be364def605c27328dadc (diff)
downloadperlweeklychallenge-club-be8ff67228ea6566aa907e3d2620b15e54ca8a01.tar.gz
perlweeklychallenge-club-be8ff67228ea6566aa907e3d2620b15e54ca8a01.tar.bz2
perlweeklychallenge-club-be8ff67228ea6566aa907e3d2620b15e54ca8a01.zip
imported my solutions to this week's challenge; 2 nice easy questions
-rw-r--r--challenge-158/duncan-c-white/README73
-rw-r--r--challenge-158/duncan-c-white/perl/MakePrimes.pm97
-rwxr-xr-xchallenge-158/duncan-c-white/perl/ch-1.pl39
-rwxr-xr-xchallenge-158/duncan-c-white/perl/ch-2.pl46
4 files changed, 200 insertions, 55 deletions
diff --git a/challenge-158/duncan-c-white/README b/challenge-158/duncan-c-white/README
index 424d544222..becee387dc 100644
--- a/challenge-158/duncan-c-white/README
+++ b/challenge-158/duncan-c-white/README
@@ -1,67 +1,30 @@
-TASK #1 - Pythagorean Means
+TASK #1 - Additive Primes
-You are given a set of integers.
+Write a script to find out all Additive Primes <= 100.
-Write a script to compute all three Pythagorean Means i.e Arithmetic Mean,
-Geometric Mean and Harmonic Mean of the given set of integers. Please
-refer to wikipedia page for more informations.
+Additive primes are prime numbers for which the sum of their decimal
+digits are also primes.
-Example 1:
+Output
- Input: @n = (1,3,5,6,9)
- Output: AM = 4.8, GM = 3.9, HM = 2.8
+ 2, 3, 5, 7, 11, 23, 29, 41, 43, 47, 61, 67, 83, 89
-Example 2:
+MY NOTES: ok. Pretty easy. Reuse my MakePrimes module, and code up
+isprime(n) and isprime(sum_digits(n))
- Input: @n = (2,4,6,8,10)
- Output: AM = 6.0, GM = 5.2, HM = 4.4
-Example 3:
+TASK #2 - First Series Cuban Primes
- Input: @n = (1,2,3,4,5)
- Output: AM = 3.0, GM = 2.6, HM = 2.2
+Write a script to compute first series Cuban Primes <= 1000. Please
+refer to https://en.wikipedia.org/wiki/Cuban_prime
+for more information.
-MY NOTES: ok. Pretty easy, although the geometric mean involves
-calculating the product of the numbers, which may get pretty huge.
-Tried bigrat, but it broke the nth-root calculation using **.
+[That says: p = (y+1)**3 - y**3 for y>0, or p = 3y**2 + 3y + 1 for y>0]
+Output
-TASK #2 - Brazilian Number
+ 7, 19, 37, 61, 127, 271, 331, 397, 547, 631, 919.
-You are given a number $n > 3.
-
-Write a script to find out if the given number is a Brazilian Number.
-
-A positive integer number N has at least one natural number B where
-1 < B < N-1 where the representation of N in base B has same digits.
-
-
-Example 1:
-
-Input: $n = 7
-Output: 1
-
-Since 7 in base 2 is 111.
-
-Example 2:
-
-Input: $n = 6
-Output: 0
-
-Since 6 in base 2 is 110,
- 6 in base 3 is 20 and
- 6 in base 4 is 12.
-
-Example 3:
-
-Input: $n = 8
-Output: 1
-
-Since 8 in base 3 is 22.
-
-
-MY NOTES: ok, so "same digits" really means "the same base-b digit
-repeated throughout the entire string". Sounds pretty easy.
-Added debugging mode to produce and display the "Since" messages,
-formatted nicely. Then added tabulate mode to show the first N
-Brazilian numbers (this interoperates nicely with -d).
+MY NOTES: ok. Not quite clear from Wikipedia page whether 3y**2 + 3y + 1
+for all y>0 is prime, I assume that's not true, so that we have to check
+isprime(3y**2 + 3y + 1)
diff --git a/challenge-158/duncan-c-white/perl/MakePrimes.pm b/challenge-158/duncan-c-white/perl/MakePrimes.pm
new file mode 100644
index 0000000000..6b5cd8e9fe
--- /dev/null
+++ b/challenge-158/duncan-c-white/perl/MakePrimes.pm
@@ -0,0 +1,97 @@
+#
+# mkprimes module (converted from mkprimes.c)
+#
+
+use strict;
+use warnings;
+use Function::Parameters;
+
+
+my $debug = 0;
+my @foundprimes; # remember all primes we've found..
+
+
+fun prime_debug( $d )
+{
+ $debug = $d;
+}
+
+
+#
+# my @primes = primes_upto( $n );
+# Find all primes up to N; return a list of all such primes
+# (note that 1 is not usually considered a prime)
+#
+fun primes_upto( $n )
+{
+ my @isprime;
+
+ for( my $i=1; $i<=$n; $i++ )
+ {
+ $isprime[$i] = 1; # initially
+ }
+
+ # now sieve the non-primes out..
+ my $upper = int(sqrt($n));
+ printf( "debug: n=%d, upper=%d\n", $n, $upper ) if $debug;
+ for( my $i=2; $i<=$upper; $i++ )
+ {
+ if( $isprime[$i] )
+ {
+ #printf( "debug: crossing out multiples of %d\n", $i );
+ for( my $j=$i*$i; $j<=$n; $j+=$i )
+ {
+ $isprime[$j] = 0;
+ }
+ }
+ }
+
+ # after sieving, extract the primes
+ my @primes = grep { $isprime[$_] } 2..$n;
+
+ # remember them
+ @foundprimes = @primes;
+
+ return @primes;
+}
+
+
+#
+# my @moreprimes = more_primes( $n, $m );
+# Need more primes! Have @foundprimes up to $n, but need
+# to sieve primes from $n+1..$m, so re-sieve, return
+# a list of all new primes (in the range $n+1..$m) that we find.
+#
+fun more_primes( $n, $m )
+{
+ my %isprime;
+
+ print "finding more primes from ", $n+1, "..$m\n" if $debug;
+
+ for( my $i=$n+1; $i<=$m; $i++ )
+ {
+ $isprime{$i} = 1; # pre-sieving
+ }
+
+ # now sieve the non-primes out..
+ foreach my $prime (@foundprimes)
+ {
+ # find first multiple of $prime > $n
+ my $mult = $prime * (int($n/$prime)+1);
+
+ #print "debug: xo multiples of $prime from $mult to $m\n";
+
+ for( my $j=$mult; $j<=$m; $j+=$prime )
+ {
+ delete $isprime{$j};
+ }
+ }
+
+ # after sieving, extract the primes
+ my @primes = grep { $isprime{$_} } $n+1..$m;
+ push @foundprimes, @primes;
+ return @primes;
+}
+
+
+1;
diff --git a/challenge-158/duncan-c-white/perl/ch-1.pl b/challenge-158/duncan-c-white/perl/ch-1.pl
new file mode 100755
index 0000000000..7e378d51d6
--- /dev/null
+++ b/challenge-158/duncan-c-white/perl/ch-1.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+#
+# TASK #1 - Additive Primes
+#
+# Write a script to find out all Additive Primes <= 100.
+#
+# Additive primes are prime numbers for which the sum of their decimal
+# digits are also primes.
+#
+# Output
+#
+# 2, 3, 5, 7, 11, 23, 29, 41, 43, 47, 61, 67, 83, 89
+#
+# MY NOTES: ok. Pretty easy. Reuse my MakePrimes module, and code up
+# isprime(n) and isprime(sum_digits(n))
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Getopt::Long;
+use List::Util qw(sum0);
+#use Data::Dumper;
+
+use lib qw(.);
+use MakePrimes;
+
+my $debug=0;
+die "Usage: additiive-primes [--debug] [limit] (default 100)\n"
+ unless GetOptions( "debug"=>\$debug ) && @ARGV<2;
+
+my $limit = shift // 100;
+
+my @primes = primes_upto( $limit );
+my %isprime = map { $_ => 1 } @primes;
+
+my @addprimes = grep { $isprime{ sum0( split(//,$_) ) } } @primes;
+
+say join(', ', @addprimes);
diff --git a/challenge-158/duncan-c-white/perl/ch-2.pl b/challenge-158/duncan-c-white/perl/ch-2.pl
new file mode 100755
index 0000000000..2b49eef7f6
--- /dev/null
+++ b/challenge-158/duncan-c-white/perl/ch-2.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+#
+# TASK #2 - First Series Cuban Primes
+#
+# Write a script to compute first series Cuban Primes <= 1000. Please
+# refer to https://en.wikipedia.org/wiki/Cuban_prime
+# for more information.
+#
+# [That says: p = (y+1)**3 - y**3 for y>0, or p = 3y**2 + 3y + 1 for y>0]
+#
+# Output
+#
+# 7, 19, 37, 61, 127, 271, 331, 397, 547, 631, 919.
+#
+# MY NOTES: ok. Not quite clear from Wikipedia page whether 3y**2 + 3y + 1
+# for all y>0 is prime, I assume that's not true, so that we have to check
+# isprime(3y**2 + 3y + 1)
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Getopt::Long;
+#use Data::Dumper;
+
+use lib qw(.);
+use MakePrimes;
+
+my $debug=0;
+die "Usage: first-cuban-primes [--debug] [limit] (default 1000)\n"
+ unless GetOptions( "debug"=>\$debug ) && @ARGV<2;
+
+my $limit = shift // 1000;
+
+my @primes = primes_upto( $limit );
+my %isprime = map { $_ => 1 } @primes;
+
+my @cuban1primes;
+for( my $y=1; ; $y++ )
+{
+ my $cubediff = 3 * $y * $y + 3 * $y + 1;
+ last if $cubediff > $limit;
+ push @cuban1primes, $cubediff if $isprime{$cubediff};
+}
+
+say join(', ', @cuban1primes);