Bienvenido: ( Identificarse | Registrarse )      
Foros de Trucos Windows
 
Closed TopicStart new topicStart Poll

Outline · [ Estándar ] · Lineal+

> Solucionador de sudokus, Un problemilla con java

LordSauron
post Dec 8 2006, 10:43 PM
Publicado: #1


Señor Oscuro
Group Icon

Grupo: Admin
Mensajes: 4.742
Registrado: 21-October 04
Desde: Un diminuto punto en el Universo
Miembro nº: 27.156



Bueno, veréis, resulta que para el lunes tengo que entregar un trabajo en la uni y tengo problemas con el código (que encima es lo menos importante del trabajo). El caso es que el proyecto trata sobre la probabilidad de que un sudoku de 9x9 tenga solución.

Para implementar el código utilicé un solucionador de sudokus en java que encontré en internet. Este código parece que funciona bien y resuelve los sudokus que tú le metas. Va acompañado de un applet donde le introduces los valores iniciales con los que quieres crear el sudoku y donde luego te muestra el sudoku resuelto.

Ahora bien, mi código lo que hace es crear una serie de números aleatorios. Estos números son insertados en celdas aleatorias de un sudoku y luego utilizo el código que descargué para que me solucione el sudoku creado aleatoriamente.

Finalmente, ejecuto este código tantas veces como quiera, es decir, resuelvo 1000 sudokus, por ejemplo, y le pido que me muestre con qué probabilidad se han resuelto los sudokus y el tiempo que ha tardado en hacerlo.

Os pongo aquí el código:
CODE

package ISAL;

/**
* Esta clase se encarga de crear y resolver un sudoku,
* guardarlo en un array y sacar el número de sudokus
* resueltos y no resueltos.
*/




import java.util.Random;

public class ProbSudoku {

// Array que guardará el tablero del sudoku.
   private int[][] tablero = new int[9][9];
   private int aFila;
   private int aCol;
   private long elapsed;
   private Random rnd = new Random();
   private int[] valoresAl;
   private int[] comp = new int[41];
   private static int count;
   
   
/*********************************************Inicio código de resolución de sudokus******************************************************/
   
/**
* Método para limpiar el tablero del sudoku y dejarlo sin números dentro.
*/

   public void limpiar() {
       for (int f = 0; f < 9; f++){
           for (int c = 0; c < 9; c++){
               tablero[f][c] = 0;
           }
       }
   }
   
/**
* Método para imprimir por pantalla el tablero del sudoku en formato texto.
*/

   public void crearTabla() {
       for (int f = 0; f < 9; f++) {
           for (int c = 0; c < 9; c += 3) {
               System.out.print(tablero[f][c]);
               System.out.print(tablero[f][c + 1]);
               System.out.print(tablero[f][c + 2]);
               System.out.print("\t");
           }
           System.out.print("\n");
           if ((f + 1) % 3 == 0)
               System.out.print("\n");
       }
   }

/**
* Insertamos el valor indicado en los parámetros en la posición indicada por los mismo.
*
* @param fila fila en la que insertaremos el valor.
* @param col  columna en la que insertaremos el valor.
* @param valor valor que queremos insertar en la celda determinada por la columna y fila dadas.
*/

   public void insertarValor(int fila, int col, int valor) {
       tablero[fila][col] = valor;
   }

/**
* Método que comprueba si el número (valor) insertado se encuentra en alguna fila, columna o caja.
*/

   public boolean Valido() {
       // Comprobamos si está en su fila.
       for (int f = 0; f < 9; f++) {
           boolean[] Insertado = new boolean[10]; // Vector que contiene a las celdas de una fila. Vale "false" si el número no está en esa celda y "true" si sí que lo está.
           for (int aux = 0; aux < 10; aux++)
           Insertado[aux] = false;
           for (int c = 0; c < 9; c ++) {
               if ((tablero[f][c]) == 0) continue; // Si la celda tiene valor "0", está vacía y continuamos.
               else {
                   if (Insertado[tablero[f][c]]){
                       // La celda tiene el número que íbamos a poner en otra de la misma fila, por tanto, no se puede poner.
                       return false;
                   }
                   else Insertado[tablero[f][c]] = true; // Marca el número como usado.
               }
               
           }
       }
       // Comprobamos si está en su columna.
       for (int c = 0; c < 9; c++) {
           boolean[] Insertado = new boolean[10]; // Vector que contiene a las celdas de una columna. Vale "false" si el número no está en esa celda y "true" si sí que lo está.
           for (int aux = 0; aux < 10; aux++)
           Insertado[aux] = false;
           for (int f = 0; f < 9; f ++) {
               if ((tablero[f][c]) == 0) continue; // Si la celda tiene valor "0", está vacía y continuamos.
               else {
                   if (Insertado[tablero[f][c]]) {
                       // La celda tiene el número que íbamos a poner en otra de la misma columna, por tanto, no se puede poner.
                       return false;
                   }
                   else Insertado[tablero[f][c]] = true; // Marca el número como usado.
               }
               
           }
       }
       // Comprobamos si está en su caja.
       for (int bf = 0; bf < 3; bf++) {
           for (int bc = 0; bc < 3; bc++) { // Para nueve cajas.
               boolean[] Insertado = new boolean[10]; // Vector que contiene a las celdas de una caja. Vale "false" si el número no está en esa celda y "true" si sí que lo está.
               for (int aux = 0; aux < 10; aux++)
                   Insertado[aux] = false;
               for (int f = 0; f < 3; f++) { // Para cada celda en una caja.
                   for (int c = 0; c < 3; c++) {
                       if ((tablero[bf*3 + f][bc*3 + c]) == 0) continue; // Si la celda tiene valor "0", está vacía y continuamos.
                       if (Insertado[(tablero[bf*3 + f][bc*3 + c])]) {
                           return false; // Si el número está usado, el Sudoku no es válido.
                       } else {
                           Insertado[(tablero[bf*3 + f][bc*3 + c])] = true; // Si el número no está usado, se marca como usado.
                       }
                   }
               }
           }
       }
       return true; //El sudoku es válido.
   }
 
   public boolean resolver(){
       int flibre, clibre; // Siguiente fila o culumna a rellenar.
       int []CeldaLibre = new int[2];
       CeldaLibre = nextCeldaLibre();
       if (CeldaLibre[0] < 0 && CeldaLibre[1] < 0){
           return this.Valido(); // No hay más celdas a rellenar y el Sudoku es válido. ¡Sudoku resuelto!
       }
       else {
           flibre=CeldaLibre[0];
           clibre=CeldaLibre[1];
           return resolver(flibre,clibre);
       }
       
   }
   
   private boolean resolver(int fila, int columna){
       int []nextLibre;
       boolean resuelto = false;
       for (int numero=1; numero< 10; numero++){
           this.insertarValor(fila,columna,numero);
           if (this.Valido()){
               nextLibre = nextCeldaLibre();
               if (nextLibre[0] < 0) return true;
               else{
                   count++;
                   resuelto = resolver(nextLibre[0],nextLibre[1]);
                   if (resuelto) return true;
               }
           }

           this.insertarValor(fila,columna,0);
       }
       return false;
   }
   
   private int[] nextCeldaLibre(){
       // La posición [0] del vector devuelve la fila; la posición [1] del vector devuelve la columna.
       int[] nextLibre = new int[2];
       nextLibre[0]=-1;
       nextLibre[1]=-1;
       for (int fila =0; fila < 9; fila++){
           for(int col=0; col < 9; col++){
               if (tablero[fila][col] == 0){
                   nextLibre[0]= fila;
                   nextLibre[1]= col;
                   
               }
           }
       }
       return nextLibre;
   }
   
   public int[][] sacarTablero(){
       return tablero;
   }
   
/************************************************Fin código de resolución de sudokus******************************************************/

/****************************************************Inicio códigos aleatorios************************************************************/

/**
* Crea n números aleatorios.
*
* @param n cantidad de números aleatorios a crear.
* @return un vector con los n números aleatorios.
*/

   public int[] aleatorio (int n) {
       int[] numeros = new int[n];
       for (int i = 0; i < n; i++) {
           numeros[i] = rnd.nextInt(9)+1;
       }return numeros;
   }
   
/**
* Crea 1 número aleatorio del 0 al 8.
*
* @return el núemro aleatorio.
*/

   public int lineasAleatorias () {
       int lineas = rnd.nextInt(9);
       return lineas;
   }
   
/**
* Crea un número aleatorio.
*
* @return un número aleatorio entre 5 y 15.
*/    
   
   public int aleatorio(){
       int aleatorio = rnd.nextInt(11)+5;
       return aleatorio;
   }
   
/**
* Inserta un número de valores aleatorios en celdas aleatorias del sudoku.
*/
   
   public void insertarAleatorio(){
       int n = 5; // Número de valores iniciales a insertar en el sudoku
       valoresAl = this.aleatorio(n);
       while(this.comprobarValores(valoresAl)==false) valoresAl=this.aleatorio(n);
       for (int i = 0; i < n; i++){
           int valor=valoresAl[i];
           this.posicionesAleatorias();
           this.insertarValor(aFila, aCol, valor);
           if(this.Valido()==false){
               insertarValor(aFila, aCol, 0);
               i=i-1;
           }
           
       }
   }
   
   private void posicionesAleatorias(){
       this.aFila = lineasAleatorias();
       this.aCol = lineasAleatorias();
   }
   
   /**
    * Comprueba que no se intente insertar un valor más de 9 veces.
    *
    * @param valores vector con los valores a insertar.
    * @return Devuelve false si se intentan insertar un valor más de 9 veces.
    */
   
   public boolean comprobarValores(int[] valores){
       for (int i=0;i<valores.length-1;i++){
           for (int j=i+1;j<valores.length;j++){
               if (valores[i]==valores[j]){
                   comp[valores[i]]=comp[valores[i]]+1;
                   if(comp[valores[i]]+1==10) return false;
               }
           }
       }
       return true;
   }
   
/**
* Resuelve n sudokus y mira a ver si son válidos o no.
*
* @param n número de susokus a resolver.
* @return el número de sudokus resueltos.
*/  
   
   public int sudokusResueltos(int n){
       int r=0;
       this.limpiar();
       for (int i=0; i<n; i++){
           count=0;
           this.insertarAleatorio();
           if (this.resolver()){
               r=r+1;
           }
           this.limpiar();
           System.out.println(count);
       }
       return r;
   }
   
/**
* Calcula la probabilidad de resolver un sudoku.
*
* @param n número de sudokus a resolver.
* @return vector de dos celdas con la probabilidad de que el sudoku se haya resuelto o que no respectivamente.
*/
   
   public float[] probabilidadSudoku(int n){
       float[] prob = new float[2];
       long ini = System.currentTimeMillis();
       int r = this.sudokusResueltos(n);
       long fin = System.currentTimeMillis();
       elapsed = (fin - ini);
       float resueltos = (r/n);
       float noresueltos = 1-resueltos;
       prob[0] = resueltos;
       prob[1] = noresueltos;
       return prob;
   }
   
/*****************************************************Fin de códigos aleatorios***********************************************************/
   
   //método main
   public static void main(String[]args){
       ProbSudoku prob = new ProbSudoku();
       float[] res = prob.probabilidadSudoku(100);
       System.out.println(res[0]);
       System.out.println(res[1]);
       System.out.println("Tiempo empleado:");
       System.out.println(prob.elapsed+" milisegundos");
   }
}




El caso es que este código funciona a veces sí a veces no. Si por ejemplo le pongo a resolver 3000 sudokus, pues muchas veces (la mayoría por no decir todas) se queda parado en un número cualquiera de sudokus y no pasa de ahí. Este número no es siempre el mismo.
El caso es que no le veo ningún error al código, ni al que bajé (al que llamo "código de resolución de sudokus") ni al que he creado ("códigos aleatorios").
Para evitar problemas con la memoria en "códigos aleatorios" he sacado todas las creaciones de objetos de los bucles y los he puesto en la zona de declaración de variables.
También he suprimido todos los métodos recursivos para que no se me llene la pila y me salte el error StackOverflowError. El problema es que no puedo quitar el método recursivo "resolver(int fila, int columna). No me salta el error que digo, pero si cuento el número de llamadas que se hace a sí mismo (con la variable "count") me sale lo siguiente, por ejemplo:
CODE

319

308

154

431

1368

161

401

579

379

1683

350

173

802

394

169

411

183

205

151

144

215

156

294

135

337

218

194

617

301

273

140

237

114

110

488

439

464

286

161

355

353

203

178

811

110

320

287

403

366

242

199

242

213

140

186

385

195

289

272

576

121

328

390

113

162

413

732

336

164

172

621

379

220

303

198

145

870

121

481

348

121

137

129

123

157

377

136

358

300

184

306

189

493

196

546

338

576

486

1075424

11685

1.0

0.0

Tiempo empleado:

35406 milisegundos



Aquí le he pedido al programa que me recuelva 100 sudokus. Las 4 últimas líneas son las probabilidades que me han dado de resolución (100% de resueltos, algo que también me mosquea, aunque poniendo sólo 5 valores iniciales no deja de ser normal...).
Las otras 100 líneas son las llamadas que se ha hecho así mismo el método en cada uno de los sudokus.

Ahora, si ejecuto este código:
CODE

public class OverflowErrorCount {
  public static int count = 0;    
  public static void main(String args[]) {
      System.out.println(++count);
      main(null);
  }
}

La última cifra debería mostrarme la cantidad de llamadas que puede hacerse así mismo un método. Esa cifra es 10265.
Si os fijáis en las dos últimas líneas de esas 100 de antes, este número es superado, pero sigo sin obtener ningún error y el programa continúa con normalidad notengoidea.gif

El caso es que todo parece indicar que el problema está en que el código no contempla correctamente lo que debe pasar cuando no encuentra una solución al sudoku. Porque creo que es ahí cuando se queda tirado en un bucle infinito. Pero no veo que haya nada mal en el código!! ranting.gif

En fin, quizás el código es un poco largo para andar pidiendo ayuda, pero bueno, si le podéis echar un vistazo o darme alguna pista o algo, pues mejor que mejor...Yo mientras tanto seguiré dejándome los ojos en la pantalla a ver si encuentro el error esta noche yawn.gif

Un saludo y gracias

Mensaje modificado por LordSauron el Dec 9 2006, 03:28 AM


User is offlineProfile CardPM
Go to the top of the page
+Quote Post
LordSauron
post Dec 10 2006, 04:45 PM
Publicado: #2


Señor Oscuro
Group Icon

Grupo: Admin
Mensajes: 4.742
Registrado: 21-October 04
Desde: Un diminuto punto en el Universo
Miembro nº: 27.156



Bueno, pues tras un par de noches en vela he conseguido casi solucionar el problema.

El anterior código no vale porque el problema de que se parara es que la técnica utilizada (backtracking) para resolver los sudokus, se hacía inviable en algunos sudokus (que normalmente no tienen solución) puesto que se tiraba horas para tratar de resolverlo.

Finalmente encontré un código que utilizaba java y que era fácil de usar. Este código utilizaba el método de "Dancing Links" que es muchísimo más rápido (al parecer es el método más rápido para resolver sudokus).

El caso es que he utilizado ese código que encontré para mi aplicación generando sudokus y diciéndole al solucionador que me resuelva cada uno de ellos.

Sin embargo, el código que descargué no debe estar del todo depurado porque hay sudokus que no es capaz de resolver.
Anoche tuve que implementar un código que me descartara esos sudokus y los diera por no resueltos. Es el método "sudokuImposible()", que devuelve "true" si no se puede solucionar.

El código final (con unos fallos que ahora explico) es el siguiente:

CODE

/**
* Esta clase se encarga de crear sudokus aleatorios
* y calcular la probabilidad de que tengan solución.
*/

import java.util.Random;

public class ProbResolSudoku{

   private int[][] tablero = new int[9][9];
   private int aFila;
   private int aCol;
   private long elapsed;
   private Random rnd = new Random();
   private int[] valoresAl;
   private int[] comp = new int[41];
   private boolean[][] Filas;
   private boolean[][] Columnas;
   private boolean[][] Cajas;
   private boolean[][] valorInsertado = new boolean[9][9];

/**
* Método para limpiar el tablero del sudoku y dejarlo sin números dentro.
*/

   public void limpiar() {
       for (int f = 0; f < 9; f++){
           for (int c = 0; c < 9; c++){
               tablero[f][c] = 0;
           }
       }
   }
   
/**
* Insertamos el valor indicado en los parámetros en la posición indicada por los mismo.
*
* @param fila fila en la que insertaremos el valor.
* @param col  columna en la que insertaremos el valor.
* @param valor valor que queremos insertar en la celda determinada por la columna y fila dadas.
*/

   public void insertarValor(int fila, int col, int valor) {
       tablero[fila][col] = valor;
   }

/**
* Crea n números aleatorios.
*
* @param n cantidad de números aleatorios a crear.
* @return un vector con los n números aleatorios.
*/

   public int[] aleatorio (int n) {
       int[] numeros = new int[n];
       for (int i = 0; i < n; i++) {
           numeros[i] = rnd.nextInt(9)+1;
       }return numeros;
   }
   
/**
* Crea 1 número aleatorio del 0 al 8.
*
* @return el núemro aleatorio.
*/

   public int lineasAleatorias () {
       int lineas = rnd.nextInt(9);
       return lineas;
   }
   
/**
* Crea un número aleatorio.
*
* @return un número aleatorio entre 5 y 15.
*/    
   
   public int aleatorio(){
       int aleatorio = rnd.nextInt(11)+5;
       return aleatorio;
   }
   
   public boolean tableroLleno(){
       for (int f = 0; f < 9; f++){
           for (int c = 0; c < 9; c++){
               if (tablero[f][c]==0) return false;
           }
       }
       return true;
   }
   
/**
* Inserta un número de valores aleatorios en celdas aleatorias del sudoku.
*/
   
   public void insertarAleatorio(){
       int n = 15;
       valoresAl = this.aleatorio(n);
       while(this.comprobarValores(valoresAl)==false) valoresAl=this.aleatorio(n);
       //if (tableroLleno()) System.out.println("¡¡Tablero lleno!!");
       for (int i = 0; i < n; i++){
           int valor=valoresAl[i];
           this.posicionesAleatorias();
           if (tablero[aFila][aCol]==0){
               this.insertarValor(aFila, aCol, valor);
               if(this.Valido()==false){
                   insertarValor(aFila, aCol, 0);
                   i=i-1;
               }
           }else i=i-1;
       }
       System.out.println();
       for(int f=0;f<9;f++){
           for(int c=0;c<9;c++){
               System.out.print(tablero[f][c]+"  ");
           }
           System.out.println();
       }
   }
   
   private void posicionesAleatorias(){
       this.aFila = lineasAleatorias();
       this.aCol = lineasAleatorias();
   }
   
   /**
    * Comprueba que no se intente insertar un valor más de 9 veces.
    *
    * @param valores vector con los valores a insertar.
    * @return Devuelve false si se intentan insertar un valor más de 9 veces.
    */
   
   public boolean comprobarValores(int[] valores){
       for (int i=0;i<valores.length-1;i++){
           for (int j=i+1;j<valores.length;j++){
               if (valores[i]==valores[j]){
                   comp[valores[i]]=comp[valores[i]]+1;
                   if(comp[valores[i]]+1==10) return false;
               }
           }
       }
       return true;
   }
   
/**
* Método que comprueba si el número (valor) insertado se encuentra en alguna fila, columna o caja.
*/

   public boolean Valido() {
       // Comprobamos si está en su fila.
       for (int f = 0; f < 9; f++) {
           boolean[] Insertado = new boolean[10]; // Vector que contiene a las celdas de una fila. Vale "false" si el número no está en esa celda y "true" si sí que lo está.
           for (int aux = 0; aux < 10; aux++)
           Insertado[aux] = false;
           for (int c = 0; c < 9; c ++) {
               if ((tablero[f][c]) == 0) continue; // Si la celda tiene valor "0", está vacía y continuamos.
               else {
                   if (Insertado[tablero[f][c]]){
                       // La celda tiene el número que íbamos a poner en otra de la misma fila, por tanto, no se puede poner.
                       return false;
                   }
                   else Insertado[tablero[f][c]] = true; // Marca el número como usado.
               }
               
           }
       }
       // Comprobamos si está en su columna.
       for (int c = 0; c < 9; c++) {
           boolean[] Insertado = new boolean[10]; // Vector que contiene a las celdas de una columna. Vale "false" si el número no está en esa celda y "true" si sí que lo está.
           for (int aux = 0; aux < 10; aux++)
           Insertado[aux] = false;
           for (int f = 0; f < 9; f ++) {
               if ((tablero[f][c]) == 0) continue; // Si la celda tiene valor "0", está vacía y continuamos.
               else {
                   if (Insertado[tablero[f][c]]) {
                       // La celda tiene el número que íbamos a poner en otra de la misma columna, por tanto, no se puede poner.
                       return false;
                   }
                   else Insertado[tablero[f][c]] = true; // Marca el número como usado.
               }
               
           }
       }
       // Comprobamos si está en su caja.
       for (int bf = 0; bf < 3; bf++) {
           for (int bc = 0; bc < 3; bc++) { // Para nueve cajas.
               boolean[] Insertado = new boolean[10]; // Vector que contiene a las celdas de una caja. Vale "false" si el número no está en esa celda y "true" si sí que lo está.
               for (int aux = 0; aux < 10; aux++)
                   Insertado[aux] = false;
               for (int f = 0; f < 3; f++) { // Para cada celda en una caja.
                   for (int c = 0; c < 3; c++) {
                       if ((tablero[bf*3 + f][bc*3 + c]) == 0) continue; // Si la celda tiene valor "0", está vacía y continuamos.
                       if (Insertado[(tablero[bf*3 + f][bc*3 + c])]) {
                           return false; // Si el número está usado, el Sudoku no es válido.
                       } else {
                           Insertado[(tablero[bf*3 + f][bc*3 + c])] = true; // Si el número no está usado, se marca como usado.
                       }
                   }
               }
           }
       }
       return true; //El sudoku es válido.
   }
   
   public boolean resolver(int puzzle[][]){
       int solucion[][];
       DancingLinksSudoku s = new DancingLinksSudoku(puzzle);
       solucion=(s.solveit());
        if ((solucion = s.solveit()) != null){
              System.out.println("Soluciono");
               return true;
         }else{
               System.out.println("No soluciono");
               return false;
           }
   }
   
   public void escaneaValores(){
       //System.out.println("Empiezo escaneo");
       Filas = new boolean[10][10];
       Columnas = new boolean[10][10];
       Cajas = new boolean[10][10];
       for (int aux1 = 0; aux1 < 10; aux1++){
           for (int aux2 = 0; aux2 < 10; aux2++){
               Filas[aux1][aux2] = false;
               Columnas[aux1][aux2]=false;
           }
       }
       for (int f = 0; f < 9; f++) {
           for (int c = 0; c < 9; c ++) {
               if ((tablero[f][c]) == 0) continue;
               else Filas[f][tablero[f][c]] = true;
           }
       }
       for (int c = 0; c < 9; c++) {
           for (int f = 0; f < 9; f ++) {
               if ((tablero[f][c]) == 0) continue;
               else Columnas[tablero[f][c]][c] = true;
           }
       }
       for (int bf = 0; bf < 3; bf++) {
           for (int bc = 0; bc < 3; bc++) {
               for (int f = 0; f < 3; f++) {
                   for (int c = 0; c < 3; c++) {
                       if ((tablero[bf*3 + f][bc*3 + c]) == 0) continue;
                       else Cajas[bf*3+bc][tablero[bf*3 + f][bc*3 + c]] = true;
                   }
               }
           }
       }
   }
   
   public void insertados(){
       //System.out.println("Array insertados");
       for (int f=0;f<9;f++){
           for (int c=0;c<9;c++){
               if(tablero[f][c]==0) valorInsertado[f][c]=false;
               else valorInsertado[f][c]=true;
           }
       }
   }
   
/**
* Comprueba que el sudoku no sea imposible, es decir,
* que si el resto de números nos obligan a poner un
* número en una casilla, no haya otro número que lo impida.
* Esto no queda bien resuelto en la implementación del
* método de Dancing Links.
*/
   
   public boolean sudokuImposible(){
       this.escaneaValores();
       //System.out.println("He escaneado");
       this.insertados();
       int[][] tableroAux = new int[9][9];
       for (int f=0;f<9;f++){
               for (int c=0;c<9;c++){
                   tableroAux[f][c]=tablero[f][c];
               }
           }
       int[][] tableroAuxTras = new int[9][9];
       for (int i=1;i<10;i++){
           for (int f=0;f<9;f++){
               if (Filas[f][i]) continue;
               else{
                   for (int c=0;c<9;c++){
                       if (Columnas[i][c]) continue;
                       else{
                           if (Cajas[((int)(f/3))*3+(int)(c/3)][i]) continue;
                           else{
                               if (valorInsertado[f][c]==false) tableroAux[f][c]=i;
                           }
                       }
                   }
               }
           }
           for (int f=0;f<9;f++) {
               int[] filaAux=tableroAux[f];
               int r=0;
               for (int c=0;c<9;c++){
                   if (filaAux[c]==i) r=r+1;
               }
               if (r==0){
                   System.out.println("-------------------");
                   System.out.println("Salgo por filas y con "+i+"s");
                   return true;
               }
           }
           for (int f=0;f<9;f++){
               for (int c=0;c<9;c++){
                   tableroAuxTras[c][f]=tableroAux[f][c];
               }
           }
           for (int c=0;c<9;c++) {
               int[] colAux=tableroAuxTras[c];
               int r=0;
               for (int f=0;f<9;f++){
                   if (colAux[f]==i) r=r+1;
               }
               if (r==0){
                   System.out.println("-------------------");
                   System.out.println("Salgo por columnas y con "+i+"s");
                   return true;
               }
           }
           for (int bf = 0; bf < 3; bf++) {
               for (int bc = 0; bc < 3; bc++) {
                   int r=0;
                   for (int f = 0; f < 3; f++) {
                       for (int c = 0; c < 3; c++) {
                           if (tableroAux[bf*3 + f][bc*3 + c]==i) r=r+1;
                       }
                   }
                   if (r==0){
                       System.out.println("-------------------");
                       System.out.println("Salgo por Cajas y con "+i+"s");
                       return true;
                   }
               }
           }
       }
       return false;
   }
   
/**
* Resuelve n sudokus y mira a ver si son válidos o no.
*
* @param n número de susokus a resolver.
* @return el número de sudokus resueltos.
*/  
   
   public int sudokusResueltos(int n){
       int r=0;
       this.limpiar();
       for (int i=0; i<n; i++){
           this.insertarAleatorio();
           if (this.sudokuImposible()){
               System.out.println("Es imposible");
               System.out.println("-------------------");
           }else{
               System.out.println();
               if (this.resolver(tablero)){
                   r=r+1;
               }
           }
           this.limpiar();
       }
       return r;
   }
   
/**
* Calcula la probabilidad de resolver un sudoku.
*
* @param n número de sudokus a resolver.
* @return vector de dos celdas con la probabilidad de que el sudoku se haya resuelto o que no respectivamente.
*/
   
   public float[] probabilidadSudoku(int n){
       float[] prob = new float[2];
       long ini = System.currentTimeMillis();
       int r = this.sudokusResueltos(n);
       long fin = System.currentTimeMillis();
       elapsed = (fin - ini);
       float resueltos = (r/n);
       float noresueltos = 1-resueltos;
       prob[0] = resueltos;
       prob[1] = noresueltos;
       return prob;
   }
   
   //método main
   public static void main(String[]args){
       ProbResolSudoku prob = new ProbResolSudoku();
       float[] res = prob.probabilidadSudoku(100);
       System.out.println();
       System.out.println(res[0]);
       System.out.println(res[1]);
       System.out.println("Tiempo empleado:");
       System.out.println(prob.elapsed+" milisegundos");
   }
}




Bien, pues a pesar de todo, sigue habiendo algunos sudokus en los que la máquina ni resuelve ni devuelve que no ha resuelto.

Para depurar esto necesito implementar una manera de medir el tiempo.
Es decir, necesito poner algo en el método "resolver(int[][] puzzle)" que si tras un cierto tiempo no me ha devuelto nada, me devuelva que no lo ha resuelto.

El problema es que no consigo saber cómo hacerlo. No me vale la llamada al método "System.currentTimeMillis()", porque eso sólo me vale para medir el tiempo que ha tardado, no el tiempo que lleva. Es decir, necesito un "timeout" que me interrumpa el código.
A ver si me podéis ayudar con el problema este.

Aclaro que dentro de "resolver(int[][] puzzle)", la declaración de objeto
"DancingLinksSudoku s = new DancingLinksSudoku(puzzle)" hace referencia a un array bidimensional que contiene el sudoku resuelto y que devuelve "null" si no lo ha resuelto.

Un saludo y gracias.


User is offlineProfile CardPM
Go to the top of the page
+Quote Post
LordSauron
post Dec 10 2006, 07:48 PM
Publicado: #3


Señor Oscuro
Group Icon

Grupo: Admin
Mensajes: 4.742
Registrado: 21-October 04
Desde: Un diminuto punto en el Universo
Miembro nº: 27.156



Otra cosa, qué veis mal en este código??
CODE

public int leerSalida() throws IOException{
       int nr=0;
       FileInputStream file=new FileInputStream("SALIDA.txt");
       BufferedReader reader= new BufferedReader(new InputStreamReader(file));
       String linea=null;
       while (null!=(linea=reader.readLine())){
           if (linea.length()<81){
               nsudokus=Integer.parseInt(linea);
           }else{
               char[] chars = new char[81];
               linea.getChars(0,linea.length()-1,chars,0);
               for (int i=0;i<81;i++){
                   if((isISOControl(chars[i])==false)){
                       nr=nr+1;
                       break;
                   }
               }
           }
       }
       return nr;
   }

Me salta un error en la compilación que dice "cannot resolve symbol - method isISOControl(char).
Pero en el javadoc tenemos esto. No entiendo nada llanto.gif

Un saludo


User is offlineProfile CardPM
Go to the top of the page
+Quote Post
LordSauron
post Dec 22 2006, 12:59 PM
Publicado: #4


Señor Oscuro
Group Icon

Grupo: Admin
Mensajes: 4.742
Registrado: 21-October 04
Desde: Un diminuto punto en el Universo
Miembro nº: 27.156



Bueno chicos, sólo decir que al final hice una chapuza y lo solucioné.
Encontré un programa en C++ que tomaba un archivo de texto donde estaban los sudokus a solucionar y generaba uno de salida donde estaban los sudokus solucionados.

Sencillamente me creé dos clases en java: una que escribiera el archivo de texto de entrada y otra que me leyera el archivo de salida y calculara las probabilidades.

Si alguien quiere el código que me envíe un MP.

Un saludo
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

 
Closed TopicTopic OptionsStart new topic

Collapse

> Topicos similares