#!/usr/bin/python
# -*- coding: utf-8 -*-


from Fraccion import Fraccion
from Complejos import Complejos

""" Bosquejo de un programa para manipular polinomios 
      Autor: Antonio Carrillo Ledesma
"""


class Poly:
    C = []  # Coeficientes del polinomio
    Dim = 0  # Guarda la dimension del arreglo de coeficientes

    def __init__(self, coef):
        """Cosntructor de la clase"""
        self.cero = 0
        if isinstance(coef[0], Fraccion):
            self.cero = Fraccion()
        elif isinstance(coef[0], Complejos):
            self.cero = Complejos()
        self.Dim = len(coef)
        self.C = [self.cero for i in range(self.Dim)]
        for i in range(self.Dim):
            self.C[i] = coef[i]

    def __str__(self):
        """Visualiza el polinomio"""
        r = ""
        for i in range(self.Dim):
            if self.C[i] != self.cero:
                r += " + " + str(self.C[i])
                if i == 0:
                    continue
                r += "X^" + str(i)
        return r

    def visualiza(self):
        """Visualiza el polinomio"""
        print(self)

    def grado(self):
        """Grado del polinomio"""
        for i in range(self.Dim - 1, 0, -1):
            if self.C[i] != self.cero:
                return i
        return 0

    def __add__(self, b):
        """suma polinomios"""
        n1, n2 = self.Dim, b.Dim
        Dim = n1 + n2
        C = [self.cero for i in range(Dim)]
        if n1 > n2:
            for i in range(n2):
                C[i] = self.C[i] + b.C[i]
            for i in range(n2, n1):
                C[i] = self.C[i]
        else:
            for i in range(n1):
                C[i] = self.C[i] + b.C[i]
            for i in range(n1, n2):
                C[i] = b.C[i]
        return Poly(C)

    def __mul__(self, b):
        """multiplica polinomios"""
        Dim = self.Dim + b.Dim
        C = [self.cero for i in range(Dim)]
        for i in range(self.Dim):
            for j in range(b.Dim):
                C[i + j] += self.C[i] * b.C[j]
        return Poly(C)

    def deriva(self):
        """Deriva el polinomio"""
        C = [self.cero for i in range(self.Dim - 1)]
        if isinstance(self.cero, Fraccion):
            for i in range(1, self.Dim):
                C[i - 1] = self.C[i] * Fraccion(i)
        elif isinstance(self.cero, Complejos):
            for i in range(1, self.Dim):
                C[i - 1] = self.C[i] * Complejos(i)
        else:
            for i in range(1, self.Dim):
                C[i - 1] = self.C[i] * i
        return Poly(C)

    def integra(self):
        """Integra el polinomio"""
        C = [self.cero for i in range(self.Dim + 1)]
        if isinstance(self.cero, Fraccion):
            for i in range(self.Dim):
                C[i + 1] = self.C[i] / (Fraccion(i) + Fraccion(1))
        elif isinstance(self.cero, Complejos):
            for i in range(self.Dim):
                C[i + 1] = self.C[i] / (Complejos(i) + Complejos(1))
        else:
            for i in range(self.Dim):
                C[i + 1] = self.C[i] / (i + 1)
        return Poly(C)

    def evalua(self, x):
        """Evalua el polinomio"""
        r = self.cero
        p = 1
        if isinstance(self.cero, Fraccion):
            p = Fraccion(1)
        elif isinstance(self.cero, Complejos):
            p = Complejos(1)
        for i in range(self.Dim):
            r += self.C[i] * p
            p *= x
        return r


"""
Prueba de las clases
"""
if __name__ == "__main__":
    print("\n\nENTERO")
    a = Poly([1, 2, 3])
    a.visualiza()

    b = Poly([4, 5])
    b.visualiza()

    print("Suma")
    c = Poly([0])
    c = a + b
    c.visualiza()

    print("Multiplicacion")
    d = Poly([0])
    d = a * b
    d.visualiza()

    print("Deriva")
    a.visualiza()
    d = Poly([0])
    d = a.deriva()
    d.visualiza()

    print("Integra")
    d.visualiza()
    e = Poly([0])
    e = d.integra()
    e.visualiza()

    print("evalua")
    a.visualiza()
    print(a.evalua(10))

    print("\n\nDOUBLE")
    a = Poly([1.0, 2.0, 3.0])
    a.visualiza()

    b = Poly([4.0, 3.0])
    b.visualiza()

    print("Suma")
    c = Poly([0.0])
    c = a + b
    c.visualiza()

    print("Multiplicacion")
    d = Poly([0.0])
    d = a * b
    d.visualiza()

    print("Deriva")
    a.visualiza()
    d = Poly([0])
    d = a.deriva()
    d.visualiza()

    print("Integra")
    d.visualiza()
    e = Poly([0])
    e = d.integra()
    e.visualiza()

    print("evalua")
    a.visualiza()
    print(a.evalua(10))

    print("\n\nComplejos")
    a = Poly([1.0 + 1.0j, 2.0 + 2.0j, 3.0 + 3.0j])
    a.visualiza()

    b = Poly([4.0 + 1.0j, 5.0 + 2.0j])
    b.visualiza()

    print("Suma")
    c = Poly([0.0j])
    c = a + b
    c.visualiza()

    print("Multiplicacion")
    d = Poly([0.0j])
    d = a * b
    d.visualiza()

    print("Deriva")
    a.visualiza()
    d = Poly([0])
    d = a.deriva()
    d.visualiza()

    print("Integra")
    d.visualiza()
    e = Poly([0])
    e = d.integra()
    e.visualiza()

    print("evalua")
    a.visualiza()
    print(a.evalua(10))

    print("\n\nFRACCION")
    v1, v2, v3, v4, v5, v6 = (
        Fraccion(1, 2),
        Fraccion(1, 3),
        Fraccion(1, 4),
        Fraccion(1, 5),
        Fraccion(1, 6),
        Fraccion(),
    )
    a = Poly([v1, v2, v3])
    a.visualiza()

    b = Poly([v4, v5])
    b.visualiza()

    print("Suma")
    c = Poly([v6])
    c = a + b
    c.visualiza()

    print("Multiplicacion")
    d = Poly([v6])
    d = a * b
    d.visualiza()

    print("Deriva")
    a.visualiza()
    d = Poly([0])
    d = a.deriva()
    d.visualiza()

    print("Integra")
    d.visualiza()
    e = Poly([0])
    e = d.integra()
    e.visualiza()

    print("evalua")
    a.visualiza()
    print(a.evalua(Fraccion(10)))

    print("\n\nCOMPLEJO FRACCIONARIO")
    v1, v2, v3, v4, v5, v6 = (
        Complejos(1, 2, 1, 2),
        Complejos(1, 3, 1, 2),
        Complejos(1, 4, 1, 2),
        Complejos(1, 5, 1, 2),
        Complejos(1, 6, 1, 2),
        Complejos(),
    )
    a = Poly([v1, v2, v3])
    a.visualiza()

    b = Poly([v4, v5])
    b.visualiza()

    print("Suma")
    c = Poly([v6])
    c = a + b
    c.visualiza()

    print("Multiplicacion")
    d = Poly([v6])
    d = a * b
    d.visualiza()

    print("Deriva")
    a.visualiza()
    d = Poly([0])
    d = a.deriva()
    d.visualiza()

    print("Integra")
    d.visualiza()
    e = Poly([0])
    e = d.integra()
    e.visualiza()

    print("evalua")
    a.visualiza()
    print(a.evalua(Complejos(10)))