import java.util.Scanner;

class Frazione {
	int num;
	int den;
}


class Exp  {
	int codice;
	Frazione f;
	Exp e1;
	Exp e2;
}



public class MainClass {

	
	public static Exp creaExpFrazione (Frazione f){
		Exp e = new Exp();
		e.codice=0;
		e.f=f;
		e.e1=null;
		e.e2=null;
		return e;
	}
	
	public static Exp creaExpSomma (Exp a, Exp b){
		Exp e = new Exp();
		e.codice=1;
		e.f=null;
		e.e1=a;
		e.e2=b;
		return e;
	}
	
	public static Exp creaExpDifferenza (Exp a, Exp b){
		Exp e = new Exp();
		e.codice=2;
		e.f=null;
		e.e1=a;
		e.e2=b;
		return e;
	}
	
	public static Exp creaExpProdotto (Exp a, Exp b){
		Exp e = new Exp();
		e.codice=3;
		e.f=null;
		e.e1=a;
		e.e2=b;
		return e;
	}
	
	public static Exp creaExpDivisione (Exp a, Exp b){
		Exp e = new Exp();
		e.codice=4;
		e.f=null;
		e.e1=a;
		e.e2=b;
		return e;
	}
	
	
	public static void stampaExp (Exp e){
		if (e==null) {
			System.out.print ("?");
			return;
		}
		switch (e.codice){
		case 0:
			stampaFrazione(e.f);
			break;
		case 1:
			System.out.print("(");
			stampaExp (e.e1);
			System.out.print ("+");
			stampaExp (e.e2);
			System.out.print(")");
			break;
		case 2:
			System.out.print("(");
			stampaExp (e.e1);
			System.out.print ("-");
			stampaExp (e.e2);
			System.out.print(")");
			break;	
		case 3:
			System.out.print("(");
			stampaExp (e.e1);
			System.out.print ("*");
			stampaExp (e.e2);
			System.out.print(")");
			break;
		case 4:
			System.out.print("(");
			stampaExp (e.e1);
			System.out.print ("/");
			stampaExp (e.e2);
			System.out.print(")");
			break;	
		}
	}
	
	public static Frazione evalExp (Exp e){
		if (e==null) return null;
		switch (e.codice){
		case 0:
			Frazione copia = copiaFrazione (e.f);
			semplificaFrazione (copia);
			return copia;
		case 1:
		{
			Frazione f1 = evalExp (e.e1);
			Frazione f2 = evalExp (e.e2);
		    return sommaFrazione (f1, f2);
		}
			
		case 2:
		{
			Frazione f1 = evalExp (e.e1);
			Frazione f2 = evalExp (e.e2);
		    return differenzaFrazione (f1, f2);
		}
		case 3:
		{
			Frazione f1 = evalExp (e.e1);
			Frazione f2 = evalExp (e.e2);
		    return prodottoFrazione (f1, f2);
		}
		case 4:
		{
			Frazione f1 = evalExp (e.e1);
			Frazione f2 = evalExp (e.e2);
		    return divisioneFrazione (f1, f2);
		}	
		}
		return null;
	}
	
	public static Exp leggiExpFacile(){
		Scanner s = new Scanner (System.in);
		System.out.println();
		System.out.println("0 - frazione semplice");
		System.out.println("1 - somma");
		System.out.println("2 - differenza");
		System.out.println("3 - prodotto");
		System.out.println("4 - divisione");
		System.out.println("Inserisci la tua scelta: ");
		int scelta;
		do {
			scelta = s.nextInt();
			s.nextLine();
		} while (scelta<0 || scelta>4);
		
		switch (scelta){
		case 0:
			return creaExpFrazione ( leggiFrazione() );
		case 1:
		{
			System.out.println ("Inserisci la prima sottoespressione:");
			Exp e1 = leggiExpFacile();
			System.out.println ("Inserisci la seconda sottoespressione:");
			Exp e2 = leggiExpFacile();
			return creaExpSomma (e1,e2);
		}
		case 2:
		{
			System.out.println ("Inserisci la prima sottoespressione:");
			Exp e1 = leggiExpFacile();
			System.out.println ("Inserisci la seconda sottoespressione:");
			Exp e2 = leggiExpFacile();
			return creaExpDifferenza (e1,e2);
		}
		case 3:
		{
			System.out.println ("Inserisci la prima sottoespressione:");
			Exp e1 = leggiExpFacile();
			System.out.println ("Inserisci la seconda sottoespressione:");
			Exp e2 = leggiExpFacile();
			return creaExpProdotto (e1,e2);
		}
		case 4:
		{
			System.out.println ("Inserisci la prima sottoespressione:");
			Exp e1 = leggiExpFacile();
			System.out.println ("Inserisci la seconda sottoespressione:");
			Exp e2 = leggiExpFacile();
			return creaExpDivisione (e1,e2);
		}
		}
		return null;	
		
	}
	
	public static Exp leggiExp(){
		Exp e = leggiExpCrea (null);
		leggiExpRiempi (e, e);
		return e;
	}
	
	public static Exp leggiExpCrea(Exp mainExp){
		Scanner s = new Scanner (System.in);
		System.out.print("Inserisci l'espressione corrispondente al primo ? in ");
		stampaExp (mainExp);
		System.out.println();
		System.out.println("0 - frazione semplice");
		System.out.println("1 - somma");
		System.out.println("2 - differenza");
		System.out.println("3 - prodotto");
		System.out.println("4 - divisione");
		System.out.print("Inserisci la tua scelta: ");
		int scelta;
		do {
			scelta = s.nextInt();
			s.nextLine();
		} while (scelta<0 || scelta>4);
		switch (scelta){
		case 0:
			return creaExpFrazione (null);
		case 1:
			return creaExpSomma (null, null);
		case 2:
			return creaExpDifferenza (null, null);
		case 3:
			return creaExpProdotto (null, null);	
		case 4:
			return creaExpDivisione (null, null);		
		}
		return null;
	}
	
	public static void leggiExpRiempi (Exp e, Exp mainExp){
		switch (e.codice){
		case 0:
			e.f = leggiFrazione();
			break;
		case 1:
		case 2:
		case 3:
		case 4:
			e.e1= leggiExpCrea (mainExp);
			leggiExpRiempi (e.e1, mainExp);
			e.e2= leggiExpCrea (mainExp);
			leggiExpRiempi (e.e2, mainExp);
		}
	}
	
	
	
	public static int abs (int a){
		return (a>0)?a:-a;
	}
	
    // Algoritmo di Euclide
	public static int MCD (int a, int b){
		a = abs(a);
		b = abs(b);
		int max = (a>b)?a:b;
		int min = (a<b)?a:b;
		while (min>0){
			int resto = max % min;
			max=min;
			min=resto;
		}
		return max;		
	}
	
	public static int MCDric (int a, int b){
		a = abs(a);
		b = abs(b);
		int max = (a>b)?a:b;
		int min = (a<b)?a:b;
		if (min==0) return max;
		return MCDric ( max % min, min);
	}
	
	public static int mcm (int a, int b){
		return a/MCD(a,b)*b;
	}
	
	public static Frazione creaFrazione (int numeratore, int denominatore){
		if (denominatore==0) return null;
		Frazione f = new Frazione();
		f.num=numeratore;
		f.den=denominatore;
		return f;
	}
	
	public static Frazione leggiFrazione (){
		Scanner s= new Scanner(System.in);
		System.out.print ("Inserisci il numeratore: ");
		int num = s.nextInt();
		s.nextLine();
		System.out.print ("Inserisci il denominatore: ");
		int den = s.nextInt();
		s.nextLine();
		return creaFrazione (num, den);
	}
	
	public static void stampaFrazione (Frazione f){
		if (f==null) return;
		System.out.print (" ");
		boolean positiva = ( (f.num>=0 && f.den>=0) || (f.num<=0 && f.den<=0) );
		if (!positiva) System.out.print ("(-");
		System.out.print(abs(f.num));
		if (abs(f.den) != 1) System.out.print("/" + abs(f.den));
		if (!positiva) System.out.print (")");
		System.out.print (" ");
	}
	
	public static boolean ugualeFrazione (Frazione f1, Frazione f2){
		if (f1==null || f2==null) return false;
		return (f1.num==f2.num) && (f1.den==f2.den);
	}

	static boolean apparenteFrazione (Frazione f1){
		if (f1==null) return false;
		return f1.num%f1.den==0;
	}
	
	public static Frazione copiaFrazione (Frazione f){
		if (f==null) return null;
		return creaFrazione (f.num, f.den);
	}
	
	public static void semplificaFrazione (Frazione f){
		if (f==null) return;
		int MCD = MCD(f.num,f.den);
		if (MCD!=0){
			f.num = f.num / MCD;
			f.den /= MCD;
		}		
	}
	
	public static Frazione sommaFrazione (Frazione f1, Frazione f2){
		if (f1==null || f2==null) return null;
		Frazione copia1 = copiaFrazione (f1);
		Frazione copia2 = copiaFrazione (f2);
		semplificaFrazione (copia1);
		semplificaFrazione (copia2);
		int denominatore = mcm (copia1.den, copia2.den);
		int numeratore = denominatore/copia1.den*copia1.num 
				         + denominatore/copia2.den*copia2.num;
		Frazione ris = creaFrazione (numeratore, denominatore);
		semplificaFrazione (ris);
		return ris;
	}
	
	public static Frazione prodottoFrazione (Frazione f1, Frazione f2){
		if (f1==null || f2==null) return null;
		Frazione copia1 = copiaFrazione (f1);
		Frazione copia2 = copiaFrazione (f2);
		semplificaFrazione (copia1);
		semplificaFrazione (copia2);
		int MCD1 = MCD (copia1.num, copia2.den);
		copia1.num /= MCD1;
		copia2.den /= MCD1;
		int MCD2 = MCD (copia1.den, copia2.num);
		copia2.num /= MCD2;
		copia1.den /= MCD2;
		Frazione ris = creaFrazione (copia1.num * copia2.num, 
				                     copia1.den * copia2.den);
		semplificaFrazione (ris);
		return ris;
	}
		
		
	public static Frazione oppostaFrazione (Frazione f){
		if (f==null) return null;
		return creaFrazione (-f.num, f.den);
	}
	
	public static Frazione differenzaFrazione (Frazione f1, Frazione f2){
		if (f1==null || f2==null) return null;
	    return sommaFrazione (f1, oppostaFrazione(f2));
	}
	
	public static Frazione inversaFrazione (Frazione f){
		if (f==null) return null;
		return creaFrazione (f.den, f.num);
	}
	
	public static Frazione divisioneFrazione (Frazione f1, Frazione f2){
		if (f1==null || f2==null) return null;
	    return prodottoFrazione (f1, inversaFrazione(f2));
	}
	
	public static boolean equivalenteFrazione (Frazione f1, Frazione f2){
		if (f1==null || f2==null) return false;
		boolean positiva1 = ( (f1.num>=0 && f1.den>=0) || (f1.num<=0 && f1.den<=0) );
		boolean positiva2 = ( (f2.num>=0 && f2.den>=0) || (f2.num<=0 && f2.den<=0) );
		if (positiva1 != positiva2) return false;		
		Frazione copia1 = copiaFrazione (f1);
		Frazione copia2 = copiaFrazione (f2);
		semplificaFrazione (copia1);
		semplificaFrazione (copia2);
		return ( abs(copia1.num)==abs(copia2.num) 
				  && abs(copia1.den)==abs(copia2.den));
	}
	
	
	public static void test(){
		System.out.println ("Inserisci la prima frazione");
		Frazione f1=leggiFrazione();
		
		System.out.println ("Inserisci la seconda frazione");
		Frazione f2=leggiFrazione();
		
				
		//semplificaFrazione(f1);
		stampaFrazione(f1); 
		System.out.print ("*");
		stampaFrazione(f2); 
		System.out.print ("=");
		
		Frazione somma = prodottoFrazione (f1,f2);
		stampaFrazione(somma);
		
	}
	
	
	public static void test2 (){
		Exp e = creaExpProdotto (
				   creaExpSomma(
						   creaExpFrazione(creaFrazione(3,4)),
						   creaExpFrazione(creaFrazione(2,1))
						   ),
				   creaExpFrazione(creaFrazione(5,3))
				);
		stampaExp (e);
		System.out.print ("=");
		stampaFrazione (evalExp(e));
	}
	
	public static void test3 (){
		Exp e = leggiExp();
		stampaExp (e);
		System.out.print ("=");
		stampaFrazione (evalExp(e));
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		test3();
	}

}
