Thursday, August 11, 2022

Perl Weekly Challenge - 177 Task 2

    This challenge built on a previous week's challenge where individuals needed to locate all the prime numbers up to a certain number. Since that had already been accomplished, it was a lot easier to get started on this challenge!

    First, what's a Palindromic Prime Cyclops number? Well, it's a prime palindrome (number that is the same when read forwards and backawards). For example the number 11 is a prime palindrome. Now what makes this challenge interesting is that the prime palindrome now needs to have a 0 in the middle of the number; in other words the cyclops 'eye' is the zero. While 11 is a prime palindrome, it's not cyclopic, technically no two digit number could fit the bill! This leads to the first possible number that can be a prime cyclopic palindrome being 101, since 101 backwards is..... 101! Note how there is the 'cyclops eye' (zero) in the middle. Shockingly the next value that meets the requirements is the number 16061!

    The challenge luckily only wanted the first 20 prime cyclopic palindromes and provided the list to confirm that user's code produced the correct results. Here is the list:

101, 16061, 31013, 35053, 38083, 73037, 74047, 91019, 94049, 1120211, 1150511, 1160611, 1180811, 1190911, 1250521, 1280821, 1360631, 1390931, 1490941, 1520251

    Let's get started! The first step, I chose to start by filtering out any number that wasn't a palindrome. I specifically started at 3 due to also needing to find prime numbers for later use in the program. I could have and probably should have just pre-made an array of all the primes up to 100 to save some program execution time.

foreach (3..1600000) { 
	if ($_ == reverse($_))

     The above code is pretty simple. The foreach loop simply iterates through the number range 3-1600000. The if statement takes the number, stored in $_, and checks to see if the number is the same forwards and backwards. If it is, then we continue on to the next piece of the challenge, determine if the number is prime. There's a number of ways to do this step.

# If number ends in these it's not prime
my @nums = split(//, $_);
if ( $nums[-1] =~ /0|2|4|5|6|8/) { next; }

# If the sum of the digits is divisble by 3, it's not prime
my $sum = 0;
$sum += $_ for split(//, $_);;
if ( $sum % 3 == 0) { next; }
    The above code rules out a large selection of numbers that aren't prime which helps to reduce the list of palindromes even further. The next step is checking the cyclopic aspect of the number.

my $dig_length = length($_);
if ( 0 == $nums[int((($dig_length/2)))] and 0 ne $dig_length % 2 and check_cyclops $_ and not $_ =~ /0{2,}/ ) { 		
	print ("$_ is a palindromic prime cyclops number!\n"); 
}
    This code does quite a bit. First it checks that middle digit is 0. Then checks that the length of the digit isn't even; even length means that there wouldn't be a zero as the middle digit. Then there is a subroutine called 'check_cyclops'; this will be discussed in a moment. Finally it checks that there aren't multiple zeros in the number. If all of those checks pass, then the program has found a Prime Cyclopic Palindrome!

    Let's revisit the 'check_cyclops' subroutine now. This sub is responsible for ensuring that any value that has made it through all the checks so far is indeed a prime number. Unfortunately to do this the number has to be checked to make sure that it isn't divisible by any other number except 1 and itself. The previous checks were able to get a large portion of the options but there is still a chance that the number is divisible by another prime. So there was also code in this program that builds an array of all the prime numbers up to 10000 while also checking for palindromes. Here is the code to build the array of primes:

if ( $_ < 10000) {
	# Find primes to be used later to check palindromes
	my $i;
	for ( $i=3; $i < $_; $i++) {
		if ( ($_ % $i) == 0 ) { last; }
	}
	if ( $i eq $_ ) { push (@primes, $_); }
  }

    The loop takes the number picked earlier in the foreach loop and attempts to modulo it to every number smaller than it. If the result is ever 0, then that number isn't prime! If the loop makes it all the way to the same number as the number itself, then it is definitely prime and that number gets added to an array of other prime numbers that will be used later to confirm that any potential cyclops values are indeed prime. Finally, 'check_cyclops' is the sub-routine used to confirm the final palindromes are indeed prime.

sub check_cyclops {
	
	my $check_val = shift;
	
	foreach my $prime ( @primes ) {
		if ( $check_val % $prime == 0 ) { return 0; }
	}
	
	return 1;
}

    Time for the moment of truth. Running the program presents the following list of Prime Cyclopic Palindromes: 

aut0exec@aut0exec:~/Projects/Weekly-Challenges$ time ./TWC-177-c1.pl 
101 is a palindromic prime cyclops number!
16061 is a palindromic prime cyclops number!
31013 is a palindromic prime cyclops number!
35053 is a palindromic prime cyclops number!
38083 is a palindromic prime cyclops number!
73037 is a palindromic prime cyclops number!
74047 is a palindromic prime cyclops number!
91019 is a palindromic prime cyclops number!
94049 is a palindromic prime cyclops number!
1120211 is a palindromic prime cyclops number!
1150511 is a palindromic prime cyclops number!
1160611 is a palindromic prime cyclops number!
1180811 is a palindromic prime cyclops number!
1190911 is a palindromic prime cyclops number!
1250521 is a palindromic prime cyclops number!
1280821 is a palindromic prime cyclops number!
1360631 is a palindromic prime cyclops number!
1390931 is a palindromic prime cyclops number!
1490941 is a palindromic prime cyclops number!
1520251 is a palindromic prime cyclops number!
1550551 is a palindromic prime cyclops number!
1580851 is a palindromic prime cyclops number!

real	0m0.811s
user	0m0.807s
sys	0m0.005s
The complete challenge code can be found on my github page. I'm sure there are some better ways to handle the math aspects of this challenge but this worked and was surprisingly quick. I'm looking forward to how other's solved this problem as well.

No comments:

Post a Comment

Have a thought or question? Please share!