/*
  Questo programma trova tutte le soluzioni dell'equazione
  x^2 + y^2 = 4 z^2 con x, y, z interi compresi tra 1 e un 
  valore limite (NUM_MAX). Sono implementati 3 diversi metodi.
  Il primo metodo esegue tre cicli annidati (uno per la x, 
  uno per la y, uno per la z) e cerca se tra i valori trovati
  vi e' una soluzione. In questo modo l'istruzione if del 
  metodo1() viene eseguita NUM_MAX^3 volte. Il secondo metodo
  assegna a z un valore tra 1 e NUM_MAX, calcola tutti i 
  possibili valori di y e infine trova x come soluzione 
  di Math.sqrt(4z^2 - y^2). In questo modo il programma diventa
  estremamente piu' efficiente. 
  Le soluzioni trovate, sia nel caso del metodo1() sia nel caso
  del metodo2(), vengono via via accumulate in una stringa.
  Il terzo metodo di soluzione segue la stessa strada del metodo2()
  ma in piu' accumula le soluzioni in un oggetto di tipo StringBuffer.
  Un controllo dei tempi per vari valori di NUM_MAX permette di vedere
  le grandi differenze di prestazione dei 3 metodi.
  Al problema si potrebbe dare una 4a soluzione, basata sul fatto che
  si stanno cercando tutte le soluzioni razionali dell'equazione
  u^2 + v^2 = 1 (ove u = x/(2z) e v = y/(2z) e che, si puo' dimostrare,
  sono della forma: x = a^2 - b^2, y = 2ab, z = (a^2 + b^2)/2 (con a e 
  b interi). Questa soluzione qui non e' implementata, ma sarebbe
  di gran lunga piu' efficiente delle soluzioni proposte.
*/

public class Terne {

    private static final int NUM_MAX = 100;

    private static String soluzioni;  // stringa che accumula le soluz. trovate

    private static StringBuffer sol;  // oggetto che accumula le sol. trovate
                                      // (nel metodo3()).

    public static void main(String[] a) {

	// catturo l'istante in cui inizia il conto:
	long inizio = System.currentTimeMillis();  
	// viene eseguito uno dei tre metodi, in questo caso metoso1():
	metodo1();	

	// catturo l'istante in cui finisce il conto:
	long fine = System.currentTimeMillis();

	// stampo i risultati:
	System.out.println(soluzioni.length());
	// System.out.println(sol.length());
	System.out.println("Finito conto");

	// stampo il tempo di esecuzione:
	System.out.println("\nTempo: " 
			   + (double)(fine - inizio)/1000 + " sec");
	// System.out.println(soluzioni);
	// System.out.println(sol);
    }

    // i tre metodi per la soluzione del problema:

    private static void metodo1() {

	soluzioni = "";

	int contatore = 0;

	for (int x = 1; x <= NUM_MAX; x++) {
	    for (int y = 1; y <= NUM_MAX; y++) {
		for (int z = 1; z <= NUM_MAX; z++) {
		    if (x * x + y * y == 4 * z * z) {
			if (contatore == 5) {
			    contatore = 0;
			    soluzioni += "\n";
			}
			contatore++;
			soluzioni += "[" + x + ", " + y + ", " + z + "] ";
		    }
		}
	    }
	}
    }

    private static void metodo2() {

	soluzioni = "";

	int contatore = 0;

	for (int z = 1; z <= NUM_MAX; z++) {
	    for (int y = 1; y <= Math.min(2 * z, NUM_MAX); y++) {
		int x = (int)(Math.sqrt(4 * z * z - y * y));
		if (x > 0 && x <= NUM_MAX && x * x + y * y == 4 * z * z) {
		    if (contatore == 5) {
			contatore = 0;
			soluzioni += "\n";
		    }
		    contatore++;
		    soluzioni += "[" + x + ", " + y + ", " + z + "] ";
		}
	    }
	}
    }

    private static void metodo3() {

	sol = new StringBuffer("");

	int contatore = 0;

	for (int z = 1; z <= NUM_MAX; z++) {
	    for (int y = 1; y <= Math.min(2 * z, NUM_MAX); y++) {
		int x = (int)(Math.sqrt(4 * z * z - y * y));
		if (x > 0 && x <= NUM_MAX && x * x + y * y == 4 * z * z) {
		    if (contatore == 5) {
			contatore = 0;
			sol.append("\n");
		    }
		    contatore++;
		    sol.append("[" + x + ", " + y + ", " + z + "] ");
		}
	    }
	}
    }
}
