Given a n*m matrix A and a p*q matrix B, their Kronecker product C = A tensor B, also called their matrix direct product, is an (np)*(mq) matrix.
A tensor B
=
|a_{11}B    a_{12}B|            
|a_{21}B    a_{22}B|
=   
|a_{11}b_{11   } a_{11}b_{12   } a_{12}b_{11   } a_{12}b_{12}|
|a_{11}b_{21   } a_{11}b_{22   } a_{12}b_{21   } a_{12}b_{22}|
|a_{11}b_{31   } a_{11}b_{32   } a_{12}b_{31   } a_{12}b_{32}|
|a_{21}b_{11   } a_{21}b_{12   } a_{22}b_{11   } a_{22}b_{12}|
|a_{21}b_{21   } a_{21}b_{22   } a_{22}b_{21   } a_{22}b_{22}|
|a_{21}b_{31   } a_{21}b_{32   } a_{22}b_{31   } a_{22}b_{32}|
 
Example 1:
Input: 
n = 2, m = 2 
p = 2, q = 2
A = {{1, 2}, 
     {3, 4}}
B = {{0, 5}, 
     {6, 7}}
Output: {{0, 5, 0, 10}, 
         {6, 7, 12, 14}, 
         {0, 15, 0, 20}, 
         {18, 21, 24, 28}}
Explaination: If the multiplication process 
is followed then this will be the answer.
 
Your Task:
You do not need to read input or print anything. Your task is to complete the function kroneckerProduct() which takes n, m, p, q and A and B as input parameters and returns the resultant matrix.
 
Expected Time Complexity: O(n*m*p*q)
Expected Auxiliary Space: O(n*m*p*q)
 
Constraints:
1 ≤ n, m, p, q ≤ 20
1 ≤ A[i][j], B[i][j] ≤ 100

Difficulty: EASY
Tags: Matrices

Data structures
Skill types: Data structures
Expected Time Complexity: O(n*m*p*q)
Expected Auxiliary Space: O(n*m*p*q)

Starter code:
#User function Template for python3

class Solution:
    def kroneckerProduct(self, n, m, p, q, A, B):
        # code here

Solutions:
import numpy as np

class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		(A, B) = (np.array(A), np.array(B))
		return np.kron(A, B)


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		ans = [[0] * (m * q) for _ in range(n * p)]
		startr = 0
		startc = 0
		for i in range(n):
			for j in range(m):
				for k in range(p):
					for l in range(q):
						ans[startr + k][startc + l] = A[i][j] * B[k][l]
				startc += q
			startc = 0
			startr += p
		return ans


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		output = []
		for rowA in A:
			for rowB in B:
				output.append([])
				for itemA in rowA:
					for itemB in rowB:
						output[-1].append(itemA * itemB)
		return output


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		result = []
		for i in range(n):
			for j in range(p):
				a = []
				for k in range(m):
					for l in range(q):
						a.append(A[i][k] * B[j][l])
				result.append(a)
		return result


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		out = []
		for i in range(n):
			for k in range(p):
				aux = []
				for j in range(m):
					for l in range(q):
						aux.append(A[i][j] * B[k][l])
				out.append(aux)
		return out


import numpy as np

class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		(A, B) = (np.array(A), np.array(B))
		return np.kron(A, B)
if __name__ == '__main__':
	t = int(input())
	for _ in range(t):
		(n, m, p, q) = [int(x) for x in input().split()]
		A = [[0] * m for x in range(n)]
		B = [[0] * q for x in range(p)]
		for i in range(n):
			a1 = input().split()
			for j in range(m):
				A[i][j] = int(a1[j])
		for i in range(p):
			a1 = input().split()
			for j in range(q):
				B[i][j] = int(a1[j])
		ob = Solution()
		ans = ob.kroneckerProduct(n, m, p, q, A, B)
		for i in range(n * p):
			for j in range(m * q):
				print(ans[i][j], end=' ')
			print()


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		x = 0
		result_matrix = [[] for b in range(n * p)]
		for i in range(0, n):
			for k in range(0, p):
				for j in range(0, m):
					for l in range(0, q):
						result_matrix[x].append(A[i][j] * B[k][l])
				x = x + 1
		return result_matrix


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		s = []
		for i in range(n * p):
			l = []
			for j in range(m * q):
				l.append(0)
			s.append(l)
		for i in range(n):
			for j in range(m):
				for k in range(p):
					for l in range(q):
						s[i * p + k][j * q + l] = A[i][j] * B[k][l]
		return s


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		matrix = []
		c = [[0 for j in range(m * q)] for i in range(n * p)]
		matrix = []
		for i in range(0, n):
			for k in range(0, p):
				x = []
				for j in range(0, m):
					for l in range(0, q):
						c[i + l + 1][j + k + 1] = A[i][j] * B[k][l]
						z = c[i + l + 1][j + k + 1]
						x.append(z)
				matrix.append(x)
		return matrix


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		li = []
		for i in range(n):
			for k in range(p):
				li1 = []
				for j in range(m):
					for l in range(q):
						li1.append(A[i][j] * B[k][l])
				li.append(li1)
				li1 = []
		return li


import numpy

class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		kronecker = numpy.kron(A, B)
		return kronecker


from numpy import array, kron

class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		(A, B) = (array(A), array(B))
		return kron(A, B)


class Solution:

	def kroneckerProduct(self, n, m, p, q, A, B):
		ans = [[0] * m * q for _ in range(p * n)]
		for x in range(n):
			for y in range(m):
				for i in range(p):
					for j in range(q):
						l = j + y * q
						k = i + x * p
						ans[k][l] = A[x][y] * B[i][j]
		return ans