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

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


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

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

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

    def __add__(self, b):
        """suma polinomios"""
        C = [Fraccion() for i in range(self.Dim)]
        for i in range(self.Dim):
            C[i] = self.C[i] + b.C[i]
        return Poly(C)

    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].P != 0:
                return i
        return 0


class Fraccion:
    """Definicion de la clase fraccion"""

    Pr = []  # inicializa el arreglo que contendra los primos encontrados
    nPr = 1000

    def __init__(self, p=0, q=1):
        """Constructor fraccion p/q"""
        self.P = p
        self.Q = q
        self.criba_Eratostenes()

    def __str__(self):
        """Visualiza la Fraccion"""
        self.simplifica()
        return str(self.P) + "/" + str(self.Q)

    def visualiza(self):
        """Visualiza la Fraccion"""
        self.simplifica()
        print("{} / {}".format(self.P, self.Q))

    def __add__(self, a):
        """Suma"""
        p = self.P * a.Q + a.P * self.Q
        q = self.Q * a.Q
        return Fraccion(p, q)

    def __sub__(self, a):
        """Resta"""
        p = self.P * a.Q - a.P * self.Q
        q = self.Q * a.Q
        return Fraccion(p, q)

    def criba_Eratostenes(self):
        """Calcular los primeros N numeros primos
        por el algoritmo de la criba de Eratostenes
        """
        # Guarda los primeros 2 primos
        self.Pr.append(2)
        self.Pr.append(3)
        npr = 2
        # Empieza la busqueda de primos a partir del numero 4
        n = 4
        # Ciclo para buscar los primeros N primos
        while npr < self.nPr:
            for i in range(npr):
                if (n % self.Pr[i]) == 0:
                    break
            if i == npr - 1:
                self.Pr.append(n)
                npr += 1
            n += 1

    def visualizaPrimos(self):
        """Visualiza los primos encontrados"""
        print("Visualiza los primeros " + str(self.nPr) + " primos ")
        for i in range(self.nPr):
            print(self.Pr[i])

    def simplifica(self):
        """Simplifica la fraccion"""
        for i in range(self.nPr):
            sw = 1
            while sw == 1:
                sw = 0
                if abs(self.P) < 2 or self.Q < 2:
                    break
                if self.P % self.Pr[i] == 0 and self.Q % self.Pr[i] == 0:
                    self.P //= self.Pr[i]
                    self.Q //= self.Pr[i]
                    sw = 1


"""
Prueba de las clases
"""
if __name__ == "__main__":
    f1 = Fraccion(1, 2)
    f2 = Fraccion(1, 3)
    f3 = Fraccion(1, 4)
    a = Poly([f1, f2, f3])
    a.visualiza()

    b = Poly([f1, f2])
    b.visualiza()

    c = Poly([f1])
    c.visualiza()

    print("Suma")
    c = a + b
    c.visualiza()
