### Perl Weekly Challenge: Week 158

Congratulations and thanks to Mohammed for 3 years of the weekly challenge.

#### Challenge 1:

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
``````

This problem can be solved as a one-liner. First we take the range, 2 to 100. (1 is not a prime so we can safely ignore it.) Then we find the prime numbers in that range by `.grep()`ing with `.is-prime()`. These prime numbers are filtered yet again by splitting them into individual digits with `.comb()` and summing the digits with `[+]` and checking if that number is prime. The result of all this is a list of additive primes which is joined up with commas via `.join()` and printed.

``````(2 .. 100).grep({ .is-prime }).grep({ ([+] .comb).is-prime }).join(q{, }).say;
``````

(Full code on Github.)

Alas we cannot be quite so succint with Perl due to a lack of `[+]` and `.is-prime`. But as this comes up a lot in these challenges I have long since developed `sum()` and `isPrime()` functions and I used them again this week. With these, the core of the solution can be expressed in one line like this:

``````say join q{, }, grep { isPrime(sum([split //])) } grep { isPrime(\$_) } 2 .. 100;
``````

(Full code on Github.)

It's just like the Raku solution except the order of operations is right to left instead of left to right.

#### Challenge 2:

First Series Cuban Primes

Write a script to compute first series `Cuban Primes <= 1000`. Please refer wikipedia page for more informations.

##### Output
``````7, 19, 37, 61, 127, 271, 331, 397, 547, 631, 919.
``````

Here is the Perl solution:

The Wikepedia page given has a formula for calculating these types of primes in terms of x and y. So first we create a variable to hold the current value of y starting from 1. x is always going to be y + 1 so it can be calculated in terms of `\$y`. We also create a list, `@cubans` to hold the results.

``````my \$y = 1;
my @cubans;
``````

Then we enter an infinite loop in which to calculate Cuban primes.

``````while(1) {
``````

A simple transposition of the formula on the Wikipedia page could be:

``````    my \$x = \$y + 1;
my \$p = ((\$x ** 3) - (\$y ** 3)) / (\$x - \$y);
``````

One might notice that x - y is always 1 so the calculation can be simplified to

``````    my \$p - (\$x ** 3) - (\$y ** 3);
``````

However the page also notes that this formula can be simplified even further to 3y2 + 3y + 1 so I have coded it like this:

``````    my \$p = 3 * \$y ** 2 + 3 * \$y + 1;
``````

This way also has the advantage of removing the need for representing x.

If the value calculated for `\$p` is greater than 1000, we can stop and break out of the loop.

``````    if (\$p > 1000) {
last;
}
``````

If it isn't and `\$p` is a prime number, we add it to the results.

``````    if (isPrime(\$p)) {
push @cubans, \$p;
}
``````

We increment `\$y` and do the next iteration of the loop.

``````    \$y++;
}
``````

Finally, we join all the results with commas and print them out.

``````say join q{, }, @cubans;
``````

(Full code on Github.)

For Raku, I normally would have followed a similar method as with Perl but I remembered that it has a nifty feature, `gather` and `take` which I should be using more of. As I understand it, `gather` executes a block asynchronously in a coroutine from which results are emitted by `take`. So it is more efficient and potentially faster than the traditional approach. Another benefit is that we don't need an intermediate list to store the results; we can directly `.join()` and `.say()` the output of the `gather` block.

``````my \$y = 1;

gather {
loop {
my \$p = 3 * \$y ** 2 + 3 * \$y + 1;
if \$p > 1000 {
last;
}
if (\$p.is-prime) {
take \$p;
}
\$y++;
}
}.join(q{, }).say;
``````

(Full code on Github.)