Perl Weekly Challenge 168.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 168.
Task 1: Perrin Prime
Submitted by: Roger Bell_West
The Perrin sequence is defined to start with [3, 0, 2]; after
that, term N is the sum of terms N-2 and N-3. (So it continues
3, 2, 5, 5, 7, ….)
A Perrin prime is a number in the Perrin sequence which is
also a prime number.
Calculate the first 13 Perrin Primes.
f(13) = [2, 3, 5, 7, 17, 29, 277, 367, 853, 14197, 43721,
1442968193, 792606555396977]
A simple solution is to iteratively generate Perrin numbers
and test them for primality. There is a slight problem in that
the first few Perrin numbers are prime, are produced out of
order and have repetitions. Thus, I could start slightly
ahead in the sequence or keep track of seen numbers and sort
the resulting array. This leads to a 3-liner, using is_prime
from Math:::Prime::Util
to test primeness.
perl -d -MMath::Prime::Util=is_prime -E '$N=shift; @p=(3,0,2); while(@pp<$N){
push @p, $p=$p[-3]+$p[-2]; $pp{$p}=1, push @pp,$p if is_prime($p) and !$pp{$p}; }
say join " ", sort {$a<=>$b} @pp;' 13
Results:
2 3 5 7 17 29 277 367 853 14197 43721 1442968193 792606555396977
The complete code is:
1 # Perl weekly challenge 168
2 # Task 1: Perrin prime
3 #
4 # See https://wlmb.github.io/2022/06/06/PWC168/#task-1-perrin-prime
5 use v5.12;
6 use warnings;
7 use bigint;
8 use Math::Prime::Util qw(is_prime);
9 die "Usage: $0 N\n to write the first N Perrin Primes" unless @ARGV;
10 my $N=shift;
11 my @last_perrins=(3,0,2);
12 my @perrin_primes;
13 my %seen;
14 while(@perrin_primes<$N){
15 push @last_perrins, my $perrin=$last_perrins[-3]+$last_perrins[-2];
16 shift @last_perrins; # no need to keep old Perrins
17 $seen{$perrin}=1, push @perrin_primes, $perrin if is_prime($perrin) and !$seen{$perrin};
18 }
19 say join " ", sort {$a<=>$b} @perrin_primes;
Example:
./ch-1.pl 13
Results:
2 3 5 7 17 29 277 367 853 14197 43721 1442968193 792606555396977
A curious example:
./ch-1.pl 1
Results:
3
Three is indeed a Perrin prime but, is it the first? I’m not sure which is the convention, but surely it is not too important.
A final example:
./ch-1.pl 17|fmt
Results:
2 3 5 7 17 29 277 367 853 14197 43721 1442968193 792606555396977
187278659180417234321 66241160488780141071579864797
22584751787583336797527561822649328254745329
29918426252927024136988188355201180399482197
The last numbers are much larger than what fits in an integer,
thus the use bigint
in line 7.
Task 2: Home Prime
Submitted by: Mohammad S Anwar
You are given an integer greater than 1.
Write a script to find the home prime of the given number.
In number theory, the home prime HP(n) of an integer n greater
than 1 is the prime number obtained by repeatedly factoring
the increasing concatenation of prime factors including
repetitions.
Further information can be found on Wikipedia and OEIS.
Example
As given in the Wikipedia page,
HP(10) = 773, as 10 factors as 2×5 yielding HP10(1) = 25, 25
factors as 5×5 yielding HP10(2) = HP25(1) = 55, 55 = 5×11
implies HP10(3) = HP25(2) = HP55(1) = 511, and 511 = 7×73
gives HP10(4) = HP25(3) = HP55(2) = HP511(1) = 773, a prime
number.
This task is simple with the appropriate tools to factor a
number, with ordered factors, and to test for primeness. As
both are included in the package Math::Prime::Util
the task
may be solved with a oneliner.
perl -MMath::Prime::Util=factor,is_prime -E '
for(@ARGV){$N=$_; $N=join "", factor($N) while(!is_prime($N)); say "HP$_=$N"}' 10 25 55 511 773
Results:
HP10=773
HP25=773
HP55=773
HP511=773
HP773=773
which confirms the correctness of the sequence discussed in the task description.
Another example:
perl -MMath::Prime::Util=factor,is_prime -E '
for(@ARGV){$N=$_; $N=join "", factor($N) while(!is_prime($N)); say "HP$_=$N"}' 2 3 4 5 6 7 8 9 10
Results:
HP2=2
HP3=3
HP4=211
HP5=5
HP6=23
HP7=7
HP8=3331113965338635107
HP9=311
HP10=773
the first few home primes.
The full version is
1 # Perl weekly challenge 168
2 # Task 2: Home prime
3 #
4 # See https://wlmb.github.io/2022/06/06/PWC168/#task-2-home-prime
5 use v5.12;
6 use warnings;
7 use Math::Prime::Util qw(is_prime factor);
8 die "Usage: $0 n1 [n2... ]\n to obtain the home primes of n1..." unless @ARGV;
9 for(@ARGV){
10 say("The argument ($_) should have been >=2"), next unless $_>=2;
11 my $N=$_;
12 $N=join "", factor($N) while(!is_prime($N));
13 say "HP$_=$N"
14 }
Example:
./ch-2.pl 2 3 4 5 6 7 8 9 10
Results:
HP2=2
HP3=3
HP4=211
HP5=5
HP6=23
HP7=7
HP8=3331113965338635107
HP9=311
HP10=773