# Run this cell using Ctrl+Enter (⌘+Enter on Mac).
from testing import exercise, create_empty_matrix
from typing import List

import math, cmath

Matrix = List[List[complex]]

@exercise
def matrix_add(a : Matrix, b : Matrix) -> Matrix:
    # You can get the size of a matrix like this:
    rows = len(a)
    columns = len(a[0])
    
    # You can use the following function to initialize a rows×columns matrix filled with 0s to store your answer
    c = create_empty_matrix(rows, columns)
    
    # You can use a for loop to execute its body several times;
    # in this loop variable i will take on each value from 0 to n-1, inclusive
    for i in range(rows):
        # Loops can be nested
        for j in range(columns):
            # You can access elements of a matrix like this:
            x = a[i][j]
            y = b[i][j]
            
            # You can modify the elements of a matrix like this:
            c[i][j] = ...
    
    return c

@exercise
def scalar_mult(x : complex, a : Matrix) -> Matrix:
    # Fill in the missing code and run the cell to check your work.
    return ...

@exercise
def matrix_mult(a : Matrix, b : Matrix) -> Matrix:
    return ...

@exercise
def matrix_inverse(a : Matrix) -> Matrix:
    return ...

@exercise
def transpose(a : Matrix) -> Matrix:
    return ...

@exercise
def conjugate(a : Matrix) -> Matrix:
    return ...

@exercise
def adjoint(a : Matrix) -> Matrix:
    return ...

from pytest import approx

@exercise
def is_matrix_unitary(a : Matrix) -> bool:
    return ...

@exercise
def inner_prod(v : Matrix, w : Matrix) -> complex:
    return ...

@exercise
def normalize(v : Matrix) -> Matrix:
    return ...

@exercise
def outer_prod(v : Matrix, w : Matrix) -> Matrix:
    return ...

@exercise
def tensor_product(a : Matrix, b : Matrix) -> Matrix:
    return ...

@exercise
def find_eigenvalue(a : Matrix, v : Matrix) -> float:
    return ...

@exercise
def find_eigenvector(a : Matrix, x : float) -> Matrix:
    return ...