Perl Weekly Challenge W022 - Sexy Primes

I was googling about perl, hoping to see an active community that is dedicated to perl. I have been an active member of codesignal and I primarily use perl to solve the challenges. And then, I came across the website perlweeklychallenge.org that is being maintained by Mohammad Anwar. The website as the name implies, post challenges every week it usually consist of three tasks.

Task #1 - Sexy Prime
For this week, the first task is to print the first 10 sexy primes

Write a script to print first 10 Sexy Prime Pairs. Sexy primes are prime numbers that differ from each other by 6. For example, the numbers 5 and 11 are both sexy primes, because 11 - 5 = 6. The term “sexy prime” is a pun stemming from the Latin word for six: sex. For more information, please checkout wiki page.

Solution #1

Below is my perl5 solution for the task:

Note: The code was intentionally obfuscated for fun (The syntax highlighter fails in $')


@_=grep{@_[ map $x*$_,$_..@_/($x=$_) ] =0 if $_[$_] > 1}@_=0..54;
map { ($_[$_]-$_[$'] == 6) && print "$_[$'] $_[$_]\n" for $_+//..$#_ } 0..$#_;

The first line of the code:

@_=grep{@_[ map $x*$_,$_..@_/($x=$_) ] =0 if $_[$_] > 1}@_=0..54; 

Is a actually a sieve of erathosenes. It is an algorithm which finds all primes up to any given limit. In my code this is set by the range 0-54. The maximum value 54 was chosen to limit the sexy primes generated to exactly ten (10) pairs.

The range of values from 0 to 54 are stored in @_ with the code:

@_=0..54; 

It was then later on grep'd with:

@_[ map $x*$_,$_..@_/($x=$_) ] =0 if $_[$_] > 1

This piece of code set the multiples of current value of $_ (from $_ to max range / $_) to 0 when $_ is greater than 1, leaving only numbers without multiples (primes).


The prime numbers are then stored to array @_ which was later used in the next line of code:
map { ($_[$_]-$_[$'] == 6) && print "$_[$'] $_[$_]\n" for  $_+//..$#_ } 0..$#_;

The code is pretty straight-forward, two prime values are printed if their difference is equal to 6. But the use of match // and $' variable is a bit tricky, its a golfing technique to avoid use of another variable to store the value of $_ from map which will be used inside the for loop.

The trick is that with //, the value of $_ from map is transferred to the perl special variable $' and would return 1 in: for $_+//..$#_ equivalent to for $_+1..$#_
See perlvar for more info

Output:

5 11
7 13
11 17
13 19
17 23
23 29
31 37
37 43
41 47
47 53

2 Comments

Welcome on board Yet Ebreo. Happy to see you blog about your first solutions to the Perl Weekly Challenge.

Leave a comment

About Yet Ebreo

user-pic I blog about Perl.