import numpy as np
import time
import matplotlib.pyplot as plt
import sympy as sym


pts = [[0.1, 10.0], [0.2, 5.0], [0.30000000000000004, 3.333333333333333], [0.4, 2.5], [0.5, 2.0], [0.6, 1.6666666666666667], [0.7000000000000001, 1.4285714285714284], [0.8, 1.25], [0.9, 1.1111111111111112], [1.0, 1.0], [1.1, 0.9090909090909091], [1.2000000000000002, 0.8333333333333333], [1.3000000000000003, 0.769230769230769], [1.4000000000000001, 0.7142857142857142], [1.5000000000000002, 0.6666666666666665], [1.6, 0.625], [1.7000000000000002, 0.588235294117647], [1.8000000000000003, 0.5555555555555555], [1.9000000000000001, 0.5263157894736842], [2.0, 0.5], [2.1, 0.47619047619047616], [2.2, 0.45454545454545453], [2.3000000000000003, 0.4347826086956521], [2.4000000000000004, 0.41666666666666663], [2.5000000000000004, 0.3999999999999999], [2.6, 0.3846153846153846], [2.7, 0.37037037037037035], [2.8000000000000003, 0.3571428571428571], [2.9000000000000004, 0.3448275862068965], [3.0000000000000004, 0.33333333333333326], [3.1, 0.3225806451612903], [3.2, 0.3125], [3.3000000000000003, 0.303030303030303], [3.4000000000000004, 0.2941176470588235], [3.5000000000000004, 0.2857142857142857], [3.6, 0.2777777777777778], [3.7, 0.27027027027027023], [3.8000000000000003, 0.2631578947368421], [3.9000000000000004, 0.2564102564102564], [4.0, 0.25], [4.1, 0.24390243902439027], [4.2, 0.23809523809523808], [4.3, 0.23255813953488372], [4.3999999999999995, 0.2272727272727273], [4.5, 0.2222222222222222], [4.6, 0.2173913043478261], [4.7, 0.2127659574468085], [4.8, 0.20833333333333334], [4.9, 0.2040816326530612], [5.0, 0.2]]


def lagrange_eq(pts):
    n_equations = len(pts)
    crr_eq = list()

    for k in range(n_equations):
        crr_factors = list()
        for i in range(n_equations):
            if i != k:
                crr_factors.append(f'(x-{pts[i][0]})/({pts[k][0]}-{pts[i][0]})')
        crr_eq.append('*'.join(crr_factors) + '*' + str(pts[k][1]))

    eq_txt = '+'.join(crr_eq)
    eq = lambda x: eval(eq_txt)
    return eq


def lagrange_eq_lambdas(pts):
    n_equations = len(pts)
    crr_eq = list()
    x = sym.symbols('x')

    for k in range(n_equations):
        crr_factors = list()

        for i in range(n_equations):
            if pts[k][0] != pts[i][0]:
                kx1 = pts[k][0]
                ix1 = pts[i][0]
                crr_factors.append(((x-ix1) / (kx1-ix1)))

        yk = pts[k][1]
        eq = np.prod([subeq for subeq in crr_factors])
        eqq = eq * yk

        eqq = sym.lambdify(x, eqq)
        crr_eq.append(eqq)

    final_eq = lambda x: sum([e(x) for e in crr_eq])
    return final_eq


titxt = time.time()
P1 = lagrange_eq(pts)
print(P1(4))
print(P1(2.5))
print(f'Finished. Time necessary: {time.time()-titxt}')


tilambda = time.time()
P2 = lagrange_eq_lambdas(pts)
print(P2(4))
print(P2(2.5))
print(f'Finished. Time necessary: {time.time()-tilambda}')


# rango = np.linspace(1, 5, 1000)
# domain = [P2(x) for x in rango]
# print(len(rango))
# print(len(domain))
# correct = lambda x: 0.05*x**2 - 0.425*x + 1.15
#
#
# plt.plot(rango, domain)
# plt.plot(rango, correct(rango))
# plt.grid()
# plt.show()
#

