Calculate the Kronecker Product
CJam, 13 bytes
{ffff*::.+:~}
This is an unnamed block that expects two matrices on top of the stack and leaves their Kronecker product in their place.
Test suite.
Explanation
This is just the Kronecker product part from the previous answer, therefore I'm here just reproducing the relevant parts of the previous explanation:
Here is a quick overview of CJam's infix operators for list manipulation:
f
expects a list and something else on the stack and maps the following binary operator over the list, passing in the other element as the second argument. E.g.[1 2 3] 2 f*
and2 [1 2 3] f*
both give[2 4 6]
. If both elements are lists, the first one is mapped over and the second one is used to curry the binary operator.:
has two uses: if the operator following it is unary, this is a simple map. E.g.[1 0 -1 4 -3] :z
is[1 0 1 4 3]
, wherez
gets the modulus of a number. If the operator following it is binary, this will fold the operator instead. E.g.[1 2 3 4] :+
is10
..
vectorises a binary operator. It expects two lists as arguments and applies the operator to corresponding pairs. E.g.[1 2 3] [5 7 11] .*
gives[5 14 33]
.
ffff* e# This is the important step for the Kronecker product (but
e# not the whole story). It's an operator which takes two matrices
e# and replaces each cell of the first matrix with the second matrix
e# multiplied by that cell (so yeah, we'll end up with a 4D list of
e# matrices nested inside a matrix).
e# Now the ffff* is essentially a 4D version of the standard ff* idiom
e# for outer products. For an explanation of ff*, see the answer to
e# to the Kronecker sum challenge.
e# The first ff maps over the cells of the first matrix, passing in the
e# second matrix as an additional argument. The second ff then maps over
e# the second matrix, passing in the cell from the outer map. We
e# multiply them with *.
e# Just to recap, we've essentially got the Kronecker product on the
e# stack now, but it's still a 4D list not a 2D list.
e# The four dimensions are:
e# 1. Columns of the outer matrix.
e# 2. Rows of the outer matrix.
e# 3. Columns of the submatrices.
e# 4. Rows of the submatrices.
e# We need to unravel that into a plain 2D matrix.
::.+ e# This joins the rows of submatrices across columns of the outer matrix.
e# It might be easiest to read this from the right:
e# + Takes two rows and concatenates them.
e# .+ Takes two matrices and concatenates corresponding rows.
e# :.+ Takes a list of matrices and folds .+ over them, thereby
e# concatenating the corresponding rows of all matrices.
e# ::.+ Maps this fold operation over the rows of the outer matrix.
e# We're almost done now, we just need to flatten the outer-most level
e# in order to get rid of the distinction of rows of the outer matrix.
:~ e# We do this by mapping ~ over those rows, which simply unwraps them.
MATLAB / Octave, 83 42 Bytes
Saved 41 bytes, thanks to FryAmTheEggman!
@(A,B)cell2mat(arrayfun(@(n)n*B,A,'un',0))
Test it here!
Breakdown
arrayfun
is a disguised for-loop that multiplies n*B
, for a variable n
defined by the second argument. This works because looping through a 2D matrix is the same as looping through a vector. I.e. for x = A
is the same as for x = A(:)
.
'un',0
is equivalent to the more verbose 'UniformOutput', False
, and specifies that the output contains cells instead of scalars.
cell2mat
is used to convert the cells back to a numeric matrix, which is then outputted.
Jelly, 10 9 bytes
×€€;"/€;/
Uses Büttner's Algorithm (ü
pronounced when trying to make an ee
sound [as in meet] in the mouth-shape of an oo
sound [as in boot]).
The ;"/€;/
is inspired by Dennis Mitchell. It was originally Z€F€€;/
(which costs one more byte).
- Test case 1
- Test case 2
- Test case 3
- Test case 4