#include <stdio.h>

#include <iostream>

// #include <string>

#include "sudoku2lib.h"

using namespace std;

type_tavola tab;

int livello_annidamento = 0;

int main()

{

  char orai[5] = {'?', '?', '?', '?', '?'};

  char oraf[5] = {'?', '?', '?', '?', '?'};

  int i = 1;

  int j = 1;

  int spia = 0;

  int tent = 0;

  int tentmille = 0;

  int tentmigli = 0;

  int tentmiliar = 0;

  // int tentativicella = 0;

  cout << "    Algoritmo di risoluzione del SUDOKU    " << endl;

  cout << "Ingegneria fisica - Politecnico di Milano  " << endl;

  cout << "     Informatica A - Prof. Sam Guinea      " << endl << endl << endl << endl;

  cout << "Inserire valori noti (0 se non si conosce)." << endl << endl;

  // string bla;

  // cout << "Debug: inserire una stringa:" << endl;

  // cin >> bla;

  // cout << "la stringa inserita è: " << bla << "!!!!!!"<< endl;

  /**********************************************/

  /*       Inserimento dei valori - BEGIN       */

  /**********************************************/ /*

  for (i = 1; i <= 9; i++) {

   cout << " RIGA " << i << endl;

   for (j = 1; j <= 9; j++) {

     do {

       cout << "(" << i << ":" << j << ")= " endl;

       cin >> tab[i][j].num; // non sono sicuro se serve passargli l'indirizzo, credo di sì in realtà!!

       if ((tab[i][j].num >= 1) && (tab[i][j].num <= 9)) // Da 1 a 9, il valore è certo

         tab[i][j].status=FOUND;

       else

         tab[i][j].status=EMPTY;

     } while (tab[i][j].num<0 || tab[i][j].num>9); // sotto 0 e sopra 9, ciclo da rifare

     if ((j % 3) == 0)

       cout << endl;

   }

   cout << endl;

  } */

  /********************************************/

  /*       Inserimento dei valori - END       */

  /********************************************/

  /***********************************************************/

  /*        PARTE TEMPORANEA: VALORI VALIDI ASSEGNATI        */

  /*       PER BYPASSARE L'INSERIMENTO MANUALE - BEGIN       */

  /***********************************************************/

  tab[1][1].num = 0; tab[1][2].num = 4; tab[1][3].num = 5;

  tab[1][4].num = 3; tab[1][5].num = 2; tab[1][6].num = 7;

  tab[1][7].num = 6; tab[1][8].num = 9; tab[1][9].num = 8;

  tab[2][1].num = 8; tab[2][2].num = 3; tab[2][3].num = 9;

  tab[2][4].num = 6; tab[2][5].num = 5; tab[2][6].num = 4;

  tab[2][7].num = 1; tab[2][8].num = 2; tab[2][9].num = 7;

  tab[3][1].num = 6; tab[3][2].num = 7; tab[3][3].num = 2;

  tab[3][4].num = 9; tab[3][5].num = 1; tab[3][6].num = 8;

  tab[3][7].num = 5; tab[3][8].num = 4; tab[3][9].num = 3;

  tab[4][1].num = 4; tab[4][2].num = 9; tab[4][3].num = 6;

  tab[4][4].num = 1; tab[4][5].num = 8; tab[4][6].num = 5;

  tab[4][7].num = 3; tab[4][8].num = 7; tab[4][9].num = 2;

  tab[5][1].num = 2; tab[5][2].num = 1; tab[5][3].num = 8;

  tab[5][4].num = 4; tab[5][5].num = 7; tab[5][6].num = 3;

  tab[5][7].num = 9; tab[5][8].num = 5; tab[5][9].num = 6;

  tab[6][1].num = 7; tab[6][2].num = 5; tab[6][3].num = 3;

  tab[6][4].num = 2; tab[6][5].num = 9; tab[6][6].num = 6;

  tab[6][7].num = 4; tab[6][8].num = 8; tab[6][9].num = 1;

  tab[7][1].num = 3; tab[7][2].num = 6; tab[7][3].num = 7;

  tab[7][4].num = 5; tab[7][5].num = 4; tab[7][6].num = 2;

  tab[7][7].num = 8; tab[7][8].num = 1; tab[7][9].num = 9;

  tab[8][1].num = 9; tab[8][2].num = 8; tab[8][3].num = 4;

  tab[8][4].num = 7; tab[8][5].num = 6; tab[8][6].num = 0; /**/

  tab[8][7].num = 2; tab[8][8].num = 3; tab[8][9].num = 5;

  tab[9][1].num = 5; tab[9][2].num = 2; tab[9][3].num = 1;

  tab[9][4].num = 8; tab[9][5].num = 3; tab[9][6].num = 9;

  tab[9][7].num = 7; tab[9][8].num = 6; tab[9][9].num = 4;

  for (i = 1; i <= 9; i++)

   for (j = 1; j <= 9; j++)

     tab[i][j].status = FOUND;

  tab[1][1].status = EMPTY;

  tab[8][6].status = EMPTY;

  /*********************************************************/

  /*       PARTE TEMPORANEA: VALORI VALIDI ASSEGNATI       */

  /*       PER BYPASSARE L'INSERIMENTO MANUALE - END       */

  /*********************************************************/

  cout << "I valori inseriti sono:\n" << endl;

  mostra_soluzione(tab);

  cout << "\nPremi un tasto per continuare.\n" << endl;

  fflush(stdin);

  // getchar();

  // controllo della validità  dei dati immessi

  if (!soluzione_valida(tab))

  {

   cout << "I dati inseriti contengono errori; il programma verra' terminato." << endl;

   fflush(stdin);

   getchar();

   return ERRORE;

  }

  /*

  cout << "Inserisci l'orario attuale [HH:MM]:" << endl;

  cin >> orai; // no indirizzo perché il char è già un puntatore a carattere

  fflush(stdin);

  cout << "Inizio della risoluzione..." << endl;

  */

  for (tent = 0;

                ( (soluzione_valida(tab) != OK   )

                  ||

                  (status_tabella  (tab) != FOUND)

                )

                &&

                (tentmigli < 500);

      tent++

     )

  {

   resetta_ipotesi(tab);

   // conteggio dei tentativi

   // WARNING: IL CONTEGGIO DEI TENTATIVI NON FUNZIONA PERCHE' L'ALGORITMO

   // ESCE DA "risolvi()" SOLO QUANDO LA SOLUZIONE È GIA' STATA TROVATA

   if (tent == 1000)

   {

     tent = 0;

     tentmille++;

     if (tentmille == 1000)

     {

       tentmille = 0;

       tentmigli++;

       if (tentmigli == 1000)

       {

         tentmigli = 0;

         tentmiliar++;

       }

     }

   }

   // Stampa del numero di tentativi

   if ((tent == 0) && ((tentmille % 50) == 0))

   {

     if (tentmiliar != 0)

       cout << tentmiliar << " miliardi ";

     if (tentmigli != 0)

       cout << tentmigli << " milioni ";

     if (tentmille != 0)

       cout << tentmille << " mila tentativi" << endl;

     else if (spia != 0)

       cout << "di tentativi" << endl;

     spia = 1;

   }

   // cuore dell'algoritmo

   risolvi(tab, &livello_annidamento);

   // Conclusioni

   if (soluzione_valida(tab) && status_tabella(tab)==FOUND) {

     cout << "La soluzione e' stata trovata!";

     cout << "Inserisci l'orario attuale [HH:MM]: " << endl;

     cin >> oraf;

     fflush(stdin);

     cout << "Inizio ore " << orai << "; fine ore " << oraf << "." << endl;

     cout << "Numero di tentativi: ";

     if (tentmiliar)

       cout << tentmiliar << " miliardi ";

     if (tentmigli)

       cout << tentmigli << " milioni ";

     if (tentmille)

       cout << tentmille << " mila ";

     cout << tent << "!" << endl;

     cout << "Premi un tasto per visualizzare la soluzione." << endl;

     getchar();

     fflush(stdin);

     mostra_soluzione(tab);

     getchar();

     return OK;

   }

   else

   {

     cout << "Soluzione non trovata, mi dispiace!!!" << endl;

     cout << "Il programma non dovrebbe mai visualizzare questa dicitura." << endl;

     cout << "Soluzione valida: " << soluzione_valida(tab) << "; status tabella: " << status_tabella(tab) << "." << endl;

     getchar();

     return ERRORE;

   }

  }

}