Write a function that accepts two square (`NxN`) matrices (two dimensional arrays), and returns the product of the two. Only square matrices will be given.

How to multiply two square matrices: 

We are given two matrices, A and B, of size 2x2 (note: tests are not limited to 2x2). Matrix C, the solution, will be equal to the product of A and B. To fill in cell `[0][0]` of matrix C, you need to compute: `A[0][0] * B[0][0] + A[0][1] * B[1][0]`.

More general: To fill in cell `[n][m]` of matrix C, you need to first multiply the elements in the nth row of matrix A by the elements in the mth column of matrix B, then take the sum of all those products. This will give you the value for cell `[m][n]` in matrix C. 

## Example
```
  A         B          C
|1 2|  x  |3 2|  =  | 5 4|
|3 2|     |1 1|     |11 8|
```

Detailed calculation:
```
C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0] = 1*3 + 2*1 =  5
C[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1] = 1*2 + 2*1 =  4
C[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0] = 3*3 + 2*1 = 11
C[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1] = 3*2 + 2*1 =  8
```
Link to Wikipedia explaining matrix multiplication (look at the square matrix example): 
http://en.wikipedia.org/wiki/Matrix_multiplication

A more visual explanation of matrix multiplication: http://matrixmultiplication.xyz

~~~if:c
**Note:** In **C**, the dimensions of both square matrices `n` will be passed into your function.  However, since the dimensions of your returned "matrix" is expected to be the same as that of the inputs, you will not need to keep track of the dimensions of your matrix in another variable.
~~~

Difficulty: EASY
Tags: Matrices

Starter code:
def matrix_mult(a, b):
	

Solutions:
from numpy import matrix

def matrix_mult(a, b):
	return (matrix(a) * matrix(b)).tolist()


def matrix_mult(a, b):
	return [[sum((a[i][k] * b[k][j] for k in range(len(a)))) for j in range(len(a))] for i in range(len(a))]


import numpy as np

def matrix_mult(a, b):
	return np.dot(a, b).tolist()


def matrix_mult(a, b):
	n = len(a)
	x = [[0 for i in range(n)] for j in range(n)]
	for k in range(n):
		for i in range(n):
			for j in range(n):
				x[i][j] += a[i][k] * b[k][j]
	return x


class Matrix:

	def __init__(self, data):
		self._data = data
		self._rows = len(data)
		self._columns = len(data[0])

	@classmethod
	def empty(cls, rows, columns):
		data = [[None for _ in range(columns)] for _ in range(rows)]
		return cls(data)

	def __getitem__(self, key):
		return self._data[key]

	@property
	def data(self):
		return self._data

	@property
	def rows(self):
		return self._rows

	@property
	def columns(self):
		return self._columns

	def row(self, row_index):
		for elem in self._data[row_index]:
			yield elem

	def column(self, column_index):
		for row in self._data:
			yield row[column_index]

	def __str__(self):
		str_rows = []
		for row in self._data:
			str_rows.append('  '.join(map(str, row)))
		return '\n'.join(str_rows)

	def __mul__(self, matrix):
		result = Matrix.empty(self.rows, self.columns)
		for result_row in range(result.rows):
			for result_column in range(result.columns):
				current_row = self.row(result_row)
				current_column = matrix.column(result_column)
				result_element = 0
				while True:
					try:
						row_element = next(current_row)
						column_element = next(current_column)
					except StopIteration:
						break
					result_element += row_element * column_element
				result[result_row][result_column] = result_element
		return result

def matrix_mult(a, b):
	product = Matrix(a) * Matrix(b)
	return product.data


def matrix_mult(a, b):
	b = list(zip(*b))
	return [[sum((n * m for (n, m) in zip(a[x], b[y]))) for y in range(len(a))] for x in range(len(a))]


def matrix_mult(a, b):
	C = []
	for i in range(len(a)):
		row = []
		for j in range(len(a)):
			z = 0
			for k in range(len(a)):
				z += a[i][k] * b[k][j]
			row.append(z)
		C.append(row)
	return C


import numpy as np

def matrix_mult(a, b):
	a = np.array(a)
	b = np.array(b)
	return np.matmul(a, b).tolist()


def matrix_mult(A, B):
	item_multiply = lambda x, y: sum((x[i] * y[i] for i in range(len(x))))
	B = [[j[i] for j in B] for i in range(len(B[0]))]
	result = []
	cycles = list(range(len(A)))
	for k in cycles:
		items = []
		for l in cycles:
			items.append(item_multiply(A[k], B[l]))
		result.append(items)
	return result


def matrix_mult(a, b):
	c = [[0] * len(a) for i in range(len(a))]
	for i in range(len(a)):
		for j in range(len(a)):
			for n in range(len(a)):
				c[i][j] += a[i][n] * b[n][j]
	return c