# ETOOBUSY ðŸš€ minimal blogging for the impatient

# PWC170 - Primorial Numbers

**TL;DR**

Here we are with TASK #1 from The Weekly Challenge #170. Enjoy!

# The challenge

Write a script to generate first 10 Primorial Numbers.

Primorial numbers are those formed by multiplying successive prime numbers.

For example,

`P(0) = 1 (1) P(1) = 2 (1x2) P(2) = 6 (1x2Ã—3) P(3) = 30 (1x2Ã—3Ã—5) P(4) = 210 (1x2Ã—3Ã—5Ã—7)`

# The questions

I would only ask what does it mean to generate the *first 10* of the
lot. Is `P(0)`

to be considered the *first one*, so that we should stop
at `P(9)`

? Or is `P(1)`

the real *first* primorial number, because itâ€™s
the one involving the first prime?

Well, our fine host took the effort to put `P(0)`

in the example, so
Iâ€™ll assume itâ€™s also the *first one*.

# The solution

I **knew** that there was some sleight of hand to do this very compactly
in Raku, and I found *one way*. Iâ€™m curious to read more solution in
the days to come.

Letâ€™s go step-wise. I know how to generate a (lazy) infinite list of positive integers:

```
1 .. *
```

and this can be filtered for `1`

or primes, keeping the laziness intact:

```
(1 .. *).grep({$_ == 1 || .is-prime})
```

Now, though, we have to do the products. If we were to calculate *any
single primorial*, we might first isolate the terms of interest with
some slicing:

```
# $n leads to the $n-th primorial P($n - 1)
(1 .. *).grep({$_ == 1 || .is-prime})[^$n]
```

Then we might apply the hyperoperator `[*]`

to this slice and get our
primorial:

```
my $nth-primorial = [*] (1 .. *).grep({$_ == 1 || .is-prime})[^$n]
```

Alas, we have to *produce* a new sequence hereâ€¦

Sorry, I meant that we have to produce a new sequence here:

[produce] is similar to reduce, but returns a list with the accumulated values instead of a single result.

So we first produce, *then* we slice to the amount of items that we
need:

```
#!/usr/bin/env raku
use v6;
sub MAIN (Int:D $n where * > 0 = 10) {
.put for (1 .. *).grep({$_ == 1 || .is-prime}).produce(&[*]).[^$n];
}
```

Letâ€™s get to Perl now. Thereâ€™s none of this laziness craziness, hyperstuff or so, but we have our old friends iterators and some basic golfing capabilities to make the readers scratch their heads a bit:

```
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use ntheory 'next_prime';
my $it = primorial_it();
say $it->() for 1 .. shift || 10;
sub primorial_it ($n = 1, $p = 1) {
sub { (($p, $n) = ($p * $n, next_prime($n)))[0] };
}
```

In the iterator sub we use two variables (which are defined as
arguments, just to spare a line of codeâ€¦ sorry!), one is `$p`

which
keeps the ever-growing **p**roduct, and one is `$n`

which keeps track of
the **n**ext prime to use.

The fun thing is that the list assignment *first* calculates the list on
the right hand side, *then* it does the assignment. Hence, the
assignment between the two lists actually means the same as:

```
$p = $p * $n;
$n = next_prime($n);
```

and returns `($p, $n)`

. As weâ€™re interested into returning `$p`

, why not
return the first element of this small list?

You know, this can be golfed a bit **and** gain in readability:

```
sub primorial_it ($n = 1, $p = 1) {
# sub { (($p, $n) = ($p * $n, next_prime($n)))[0] };
sub { ($p, $n) = ($p * $n, next_prime($n)); $p };
}
```

Itâ€™s now clear that we want to return `$p`

, yay!

Last considerations:

- ntheory just rocks, thanks DANAJ;
- I know the product is going to become a non-integer quite soon and I would need to use big integersâ€¦ but weâ€™re requested to cope with the first 10 items, and the stock integers are fine for this.

Stay safe!

*Comments? Octodon, Twitter, GitHub, Reddit, or drop me a line!*