# ETOOBUSY đźš€ minimal blogging for the impatient

# PWC170 - Kronecker Product

**TL;DR**

On with TASK #2 from The Weekly Challenge #170. Enjoy!

# The challenge

You are given 2 matrices.

Write a script to implement

`Kronecker Product`

on the given 2 matrices.For more information, please refer 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 ]`

# The questions

The challenge text requests us to *implement* the product, so I wonder
if using modules is OK in this case. Iâ€™ll assume that it means in the
sense of â€śimplement something that can calculate the productâ€ť.

On a similar note, Iâ€™d ask if the output format is strict or can be varied a bitâ€¦ depending on whatâ€™s easy to accomplish. Again, Iâ€™ll assume that whatever goes, as long as itâ€™s readable.

# The solution

These are busy weeks and this usually increments my likelihood to go for simple and lazy solutions. Hence, you can imagine that between learning PDL and using Math::Matrixâ€¦ I opted for the second:

```
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use Math::Matrix;
my $A = Math::Matrix->new([1, 2], [3, 4]);
my $B = Math::Matrix->new([5, 6], [7, 8]);
my $K = $A->kron($B);
$K->print("K\n");
```

Iâ€™m not sure I *entirely* like the output format, but itâ€™s a gift and I
donâ€™t want to whine about it.

For the Raku solution, I remembered about the famous Wally Wood:

Never draw anything you can copy, never copy anything you can trace, never trace anything you can cut out and paste up.

This was definitely one of those occasions, as the solution is already there in Rosetta Code. So with very little cosmetics, here we go:

```
#!/usr/bin/env raku
use v6;
sub MAIN {
.say for kronecker-product([ <1 2>, <3 4> ],
[ <5 6>, <7 8> ]);
}
sub kronecker-product (@a, @b) {
(@a X @b).map: { .[0].list X* .[1].list };
}
```

Well, I guess I at least owe an explanation. To me.

We start with `@a`

and `@b`

being arrays of tuples:

```
> my @a = <1 2>, <3 4>;
[(1 2) (3 4)]
> my @b = <5 6>, <7 8>;
[(5 6) (7, 8)]
```

The `X`

operator creates pairs from the two operands, so it creates
pairs of rows from the two arrays:

```
> @a X @b
(((1 2) (5 6)) ((1 2) (7 8)) ((3 4) (5 6)) ((3 4) (7 8)))
```

These pairs are fed into the `map`

as the implicit variable `$_`

, which
we donâ€™t even have to mention. Thus, `.[0]`

and `.[1]`

are the two rows
coming respectively from `@a`

and `@b`

, and we multiply element by
element with `X*`

. The `.list`

part allows us tell Raku to do the
right thing with these sequences.

The sub can be put in a slightly more readable way:

```
sub kronecker-product (@a, @b) {
(@a X @b).map: -> (@A, @B) { @A X* @B };
}
```

Here we assign each pair from `map`

to `(@A, @B)`

, which then
get the respective row from `@a`

and `@b`

like before. Here we donâ€™t
even have to use the `.list`

, which in my humble opinion makes the
solution *more readable* **and** *shorter*.

OK, Iâ€™ve not been *that* lazy after allâ€¦ Stay safe!

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