### Perl Weekly Challenge: Week 170

#### Challenge 1:

**Primorial Numbers**

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

This can be computed in Raku as a one-liner.

```
my $n = 1; (1, |(0 .. *).grep({ .is-prime })[^9]).map({ $n *= $_ }).join(q{, }).say
```

First we set up a variable `$n`

which will hold the current running total of multiplied primes (i.e. the current primorial number.)

Then we set up an list primed (haha! get it?) with 1 because apparently 1 is the first primorial number even though it isn't a prime by most definitions.

`(0 .. *).grep({ .is-prime })[^9]`

uses a lazy list to give us the next 9 prime numbers. The `|`

before this is to flatten the results so we can add them as individual elements to our primorial list.

`.map({ $n *= $_ })`

takes `$n`

and multiplies it by each member of the list which gives us a list of 10 primorials.

Then the standard `.join(q{, }).say`

is used to print out the results in a nice way.

For Perl I had to break out my veteran `isPrime()`

and `nextPrime()`

functions and instead of `grep()`

and `map()`

, I used a loop to
create the list of Primorials.

```
my @primorials = (1);
my $n = 1;
until (scalar @primorials == 10) {
push @primorials, $n *= nextPrime();
}
say join q{, }, @primorials;
```

In case you wanted to know, the first 10 primorials are 1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690 and 223092870.

#### Challenge 2:

**Kroneker Product**

You are given 2 matrices.

Write a script to implement

`Kronecker Product`

on the given 2 matrices.For more information, please refer to the wikipedia page.

For example,

```
A = [ 1 2 ]
[ 3 4 ]
B = [ 5 6 ]
[ 7 8 ]
A x B = [ 1 x [ 5 6 ] 2 x [ 5 6 ] ]
[ [ 7 8 ] [ 7 8 ] ]
[ 3 x [ 5 6 ] 4 x [ 5 6 ] ]
[ [ 7 8 ] [ 7 8 ] ]
= [ 1x5 1x6 2x5 2x6 ]
[ 1x7 1x8 2x7 2x8 ]
[ 3x5 3x6 4x5 4x6 ]
[ 3x7 3x8 4x7 4x8 ]
= [ 5 6 10 12 ]
[ 7 8 14 16 ]
[ 15 18 20 24 ]
[ 21 24 28 32 ]
```

Lucky for me, my daughter Shailaja has taken linear algebra recently enough that she still remembers this stuff. Once I was up to speed, this was rather easy in Raku. Even so, I hard-coded the two matrices from the example rather than allowing for arbitrary input.

```
printMatrix((@A X @B).map({ [X*] $_ }));
```

`@A X @B`

gives the cross product of the two arrays. In orther words it produces an array where each element is an array consisting of one element from `@A`

and one element from `@B`

. Then `.map({ [X*] $_ })`

multiplies the elements of each of those arrays together. The result is a matrix that contains the Kroneker Product of `@A`

and `@B`

.

`printMatrix()`

is just a small function to pretty-print a two-dimensional array of integers like our matrices.

```
sub printMatrix(@matrix) {
for @matrix -> @row {
for @row -> $col {
$col.fmt('%2d ').print;
}
print "\n";
}
}
```

I am not that happy with my Perl version. For a start, deprived of all those fancy Raku operators, it uses 4-level nested loops which can't be good with large matrices from an efficiency point of view. It works well enough for the sample input though.

```
sub kroneckerProduct {
my @A = @{$_[0]};
my @B = @{$_[1]};
my @answer;
for my $a (0 .. scalar @A - 1) {
for my $aa (@{$A[$a]}) {
for my $b (0 .. scalar @B - 1) {
for my $bb (@{$B[$b]}) {
```

Also the line below for ensuring the results get put in the right place in the output matrix feels hacky to me. If I had a 3 x 3 matrix, would it be enough to change it to `$a * 3`

or would some more complex calculation be needed? Again, what I have works
for the task at hand but one day I really should try and generalize this.

```
push @{$answer[$a * 2 + $b]}, $aa * $bb;
}
}
}
}
return \@answer;
}
```

The Perl version of `printMatrix()`

looks like this.

```
sub printMatrix {
my @matrix = @{$_[0]};
for my $row (@matrix) {
for my $col (@{$row}) {
printf '%2d ', $col;
}
print "\n";
}
}
printMatrix(kroneckerProduct(\@A, \@B));
```