// Clase para manipular polinomios
// Antonio Carrillo Ledesma


// Se define al polinomio por sus coeficientes, es decir
//    A0 + A1x^1 + ...+Anx^n
// Quedando el arreglo como
//    A0, A1, ... An


import java.util.*;

public class Poly <T extends Numero> {



   // Coeficientes del polinomio
   private ArrayList<Numero> c;
   // Guarda la dimension del arreglo de coeficientes
   private int dim;

   // Constructor de la clase
   public Poly() {
      dim = 0;
      c = new ArrayList<Numero>();
   }


   // Asigna coeficientes
   public void asignaCoeficientes(Numero []coef) {
      int i, n = coef.length;
      c = new ArrayList<Numero>();

      for (i = 0; i < n; i++) c.add(coef[i]);
      dim = n;
   }


   // Retorna los coeficientes del polinomio
   Numero coeficiente(int i) {
      if (i >= dim)  System.out.print("Error");
      return c.get(i);
   }


   // Retorna la dimension del arreglo de coeficientes
   int dimension() {
      return dim;
   }


   // Visualiza el polinomio
   public void visualiza() {
      int i;

      for (i = 0; i < dim; i++) {
         if(c.get(i).esCero() == false) {
            System.out.print(" + ");
            c.get(i).visualiza();
            if (i == 0) continue;
            System.out.print("X^");
            System.out.print(i);
         }
      }
      System.out.println(" ");
   }



   // Suma con dos operandos
   public void suma(Poly a, Poly b) {
      int i, n, n1 = a.dim, n2 = b.dim;

      c.clear();
      if (n1 > n2) {
         for (i = 0; i < n2; i++)  {
            Numero x = a.coeficiente(0).nuevo();
            x.suma(a.coeficiente(i), b.coeficiente(i));
            c.add(i, x);
         }
         for (i = n2; i < n1; i++) c.add(i, a.coeficiente(i));
         dim = n1;
      } else {
         for (i = 0; i < n1; i++)  {
            Numero x = a.coeficiente(0).nuevo();
            x.suma(a.coeficiente(i), b.coeficiente(i));
            c.add(i, x);
         }
         for (i = n1; i < n2; i++) c.add(i, b.coeficiente(i));
         dim = n2;
      }

   }



   // Suma con un operando
   public void suma(Poly a) {
      int i, n, n1 = dim, n2 = a.dim;

      if (n1 > n2) {
         for (i = 0; i < n2; i++)  {
            Numero x = coeficiente(i);
            x.suma(a.coeficiente(i));
            c.set(i, x);
         }
         dim = n1;
      } else {
         for (i = 0; i < n1; i++)  {
            Numero x = coeficiente(i);
            x.suma(a.coeficiente(i));
            c.set(i, x);
         }
         for (i = n1; i < n2; i++) c.add(i, a.coeficiente(i));
         dim = n2;
      }

   }


   // Funcion Principal ....
   public static void main(String[] args) {

      // Ejemplito para polinomios de coeficientes de tipo Fraccion

      Double []r = new Double[4];
      r[0] = new Double(1);
      r[1] = new Double(2);
      r[2] = new Double(3);
      r[3] = new Double(6);
      Double []s = new Double[3];
      s[0] = new Double(5);
      s[1] = new Double(6);
      s[2] = new Double(7);

      Poly<Double> R = new Poly<Double> ();
      R.asignaCoeficientes(r);
      Poly<Double> S = new Poly<Double> ();
      S.asignaCoeficientes(s);
      Poly<Double> TT = new Poly<Double> ();

      System.out.println("Double");
      R.visualiza();
      System.out.println("+");
      S.visualiza();
      TT.suma(R, S);
      System.out.println("=====================");
      TT.visualiza();
      System.out.println("");
      System.out.println("");




      Fraccion []a = new Fraccion[3];
      a[0] = new Fraccion(1, 2);
      a[1] = new Fraccion(2, 2);
      a[2] = new Fraccion(3, 2);
      Fraccion []b = new Fraccion[4];
      b[0] = new Fraccion(1, 3);
      b[1] = new Fraccion(2, 3);
      b[2] = new Fraccion(3, 3);
      b[3] = new Fraccion(1, 3);

      Poly<Fraccion> A = new Poly<Fraccion> ();
      A.asignaCoeficientes(a);
      Poly<Fraccion> B = new Poly<Fraccion> ();
      B.asignaCoeficientes(b);
      Poly<Fraccion> C = new Poly<Fraccion> ();

      System.out.println("Fraccion");
      A.visualiza();
      System.out.println("+");
      B.visualiza();
      C.suma(A, B);
      System.out.println("=====================");
      C.visualiza();
      System.out.println("");
      System.out.println("");



      // Ejemplito de polinomios de coeficionets de tipo Complejos
      Complejos []x = new Complejos[3];
      x[0] = new Complejos(2, 3);
      x[1] = new Complejos(2, 2);
      x[2] = new Complejos(3, 2);
      Complejos []y = new Complejos[3];
      y[0] = new Complejos(-2, -3);
      y[1] = new Complejos(2, 3);
      y[2] = new Complejos(3, 3);

      Poly<Complejos> X = new Poly<Complejos>();
      X.asignaCoeficientes(x);
      Poly<Complejos> Y = new Poly<Complejos>();
      Y.asignaCoeficientes(y);
      Poly<Complejos> Z = new Poly<Complejos>();

      System.out.println("Complejo");
      X.visualiza();
      System.out.println("+");
      Y.visualiza();
      Z.suma(X, Y);
      System.out.println("=====================");
      Z.visualiza();
      System.out.println("");
      System.out.println("");



      // Ejemplito de polinomios de coeficionets de tipo ComplejoFraccionario
      ComplejoFraccionario []xx = new ComplejoFraccionario[3];
      xx[0] = new ComplejoFraccionario(2, 3, 4, 5);
      xx[1] = new ComplejoFraccionario(2, 2, 3, 7);
      xx[2] = new ComplejoFraccionario(3, 2);
      ComplejoFraccionario []xy = new ComplejoFraccionario[3];
      xy[0] = new ComplejoFraccionario(-2, 3, 5, 6);
      xy[1] = new ComplejoFraccionario(2, 3, 7, 9);
      xy[2] = new ComplejoFraccionario(3, 3);

      Poly<ComplejoFraccionario> xX = new Poly<ComplejoFraccionario>();
      xX.asignaCoeficientes(xx);
      Poly<ComplejoFraccionario> xY = new Poly<ComplejoFraccionario>();
      xY.asignaCoeficientes(xy);
      Poly<ComplejoFraccionario> xZ = new Poly<ComplejoFraccionario>();

      System.out.println("Complejo Fraccionario");
      xX.visualiza();
      System.out.println("+");
      xY.visualiza();
      xZ.suma(xX, xY);
      System.out.println("=====================");
      xZ.visualiza();
      System.out.println("");
      System.out.println("");

   }
}


