from __future__ import print_function
import numpy as np

def backsubstitute(A, b):
    n = len(b)
    i,j = A.shape
    if i != n or j != n:
        raise ValueError("A should be shape (%d, %d), but is %s" % (n, n, str(A.shape)))
    
    x = b.copy()
    
    for i in range(n - 1, -1, -1):
        x[i] = b[i]
        for j in range(n - 1, i, -1):
            x[i] -= A[i, j] * x[j]
        x[i] /= A[i, i]
    
    return x

def gauss_eliminate(A_in, b_in):
    # Make copies of the matrix and the vector
    A = A_in.copy()
    b = b_in.copy()
    
    # Gauss eliminate
    # ....
    
    return A, b

def solve(A, b):
    A_res, b_res = gauss_eliminate(A, b)
    x = backsubstitute(A_res, b_res)
    return x

# Sample solution 1
A1 = np.array([[ 1.        ,  0.2       ,  0.04      ,  0.008     ],
               [ 1.        ,  0.53333333,  0.28444444,  0.1517037 ],
               [ 1.        ,  0.86666667,  0.75111111,  0.65096296],
               [ 1.        ,  1.2       ,  1.44      ,  1.728     ]])
b1 = np.array([ 0.95105652, -0.20791169, -0.74314483,  0.95105652])

x1 = solve(A1, b1)
print("solve(A1, b1)={}".format(x1))

# compare the result to the reference
x1_ref = np.array([ 1.27785932, -0.17219435, -8.75422788,  7.22564732])
if np.all(np.abs(x1 - x1_ref) < 1.e-5):
    print("Congratulations, the result is correct!")
else:
    print("This result is wrong!")

# Sample solution 2
A2 = np.array([[ 0.        ,  0.2       ,  0.04      ,  0.008     ],
               [ 1.        ,  0.53333333,  0.28444444,  0.1517037 ],
               [ 1.        ,  0.86666667,  0.75111111,  0.65096296],
               [ 1.        ,  1.2       ,  1.44      ,  1.728     ]])
b2 = np.array([ 0.95105652, -0.20791169, -0.74314483,  0.95105652])

x2 = solve(A2, b2)
print("solve(A2, b2)={}".format(x2))

# compare the result to the reference
x2_ref = np.array([ -0.85418404,   8.06213979, -18.74818115,  11.0694755 ])
if np.all(np.abs(x2 - x2_ref) < 1.e-5):
    print("Congratulations, the result is correct!")
else:
    print("This result is wrong!")
