# Perl Weekly Challenge 014.1

This week’s challenge starts off with something Perl 6 can do exceedingly well: filter values based on fixed criteria. The problem statement:

Write a script to generate first 10 strong and weak prime numbers.

For example, the nth prime number is represented by p(n).

``````  p(1) = 2
p(2) = 3
p(3) = 5
p(4) = 7
p(5) = 11
``````

Strong Prime number `p(n) when p(n) > [ p(n-1) + p(n+1) ] / 2`

Weak Prime number `p(n) when p(n) < [ p(n-1) + p(n+1) ] / 2`

Interestingly, we have our solution partially written for us, above. All we need to do is put that pseudocode into Perl 6 like so:

``````my @primes = (2,3,*+2 ... *).grep: {.is-prime};

my @strong-primes = lazy @primes.pairs.grep(-> (:\$key, :\$value) {
\$key != 0 and \$value > (@primes[\$key-1] + @primes[\$key+1])/2.0}
).map: {.value};
my @weak-primes = lazy @primes.pairs.grep(-> (:\$key, :\$value) {
\$key != 0 and \$value < (@primes[\$key-1] + @primes[\$key+1])/2.0}
).map: {.value};
``````

and as a bonus, the balanced primes:

``````my @balanced-primes = lazy @primes.pairs.grep(-> (:\$key, :\$value) {
\$key != 0 and \$value == (@primes[\$key-1] + @primes[\$key+1])/2.0}
).map: {.value};
``````

But that’s a lot of duplicated code… what can we do about that? Well…

Perl 6 lets us pass a block to a subroutine with placeholder variables, so we can define the generator for each of these sequences as a function taking one `Code` parameter:

``````sub powerful-primes(&cmp) {
lazy @primes.pairs.grep(-> (:\$key, :\$value) {
\$key != 0 and cmp(\$value, (@primes[\$key-1] + @primes[\$key+1])/2.0)}
).map: {.value};
}
``````

And then we can call this like so:

``````my @strong-primes = powerful-primes({\$^a > \$^b});
my @weak-primes = powerful-primes({\$^a < \$^b});
my @balanced-primes = powerful-primes({\$^a == \$^b});
``````

Here’s the whole program with tests.

``````use Test;

my @primes = (2,3,*+2 ... *).grep: {.is-prime};

sub powerful-primes(&cmp) {
lazy @primes.pairs.grep(-> (:\$key, :\$value) {
\$key != 0 and cmp(\$value, (@primes[\$key-1] + @primes[\$key+1])/2.0)}
).map: {.value};
}

my @strong-primes = powerful-primes({\$^a > \$^b});
my @weak-primes = powerful-primes({\$^a < \$^b});
my @balanced-primes = powerful-primes({\$^a == \$^b});

for (
("strong", @strong-primes, [11, 17, 29, 37, 41, 59, 67, 71, 79, 97]),
("weak", @weak-primes, [3, 7, 13, 19, 23, 31, 43, 47, 61, 73]),
("ballanced", @balanced-primes, [5, 53, 157, 173, 211, 257, 263, 373, 563, 593])) -> (\$name, \$seq, \$oeis) {
say "Calculating \$name primes...";
say "First 10 \$name primes: {\$seq[^10]}";
cmp-ok \$seq[^10], '~~', \$oeis, "OEIS canned values compared";
}
``````

Updated: