Advertisement
Guest User

kaoD

a guest
Jan 27th, 2009
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.62 KB | None | 0 0
  1. /* sudoku.txt de ejemplo:
  2.  
  3. 002|006|000
  4. 035|020|680
  5. 000|000|002
  6. ---+---+---
  7. 003|400|170
  8. 507|000|309
  9. 091|008|200
  10. ---+---+---
  11. 600|000|000
  12. 054|080|920
  13. 000|900|400
  14.  
  15. sudoku de bLaKnI (mas complejo y con solucion unica)
  16.  
  17. 000000010
  18. 400000000
  19. 020000000
  20. 000050407
  21. 008000300
  22. 001090000
  23. 300400200
  24. 050100000
  25. 000806000
  26.  
  27. */
  28.  
  29. #include <stdio.h>
  30. #include <string.h>
  31.  
  32. #define VERBOSE     1
  33. #define NO_VERBOSE  0
  34.  
  35. FILE *fSolucion;
  36. int solucion=0;
  37.  
  38. void imprimeSudoku(const char sudoku[9][9])
  39. {
  40.     int i, j;
  41.  
  42.     for (i=0; i<9; i++)
  43.     {
  44.         if (i == 0)
  45.             fprintf (fSolucion, "+- Solucion %-5d-+\n", solucion);
  46.  
  47.         for (j=0; j<9; j++)
  48.         {
  49.             if (j == 0)
  50.                 fprintf (fSolucion, "|");
  51.  
  52.             fprintf (fSolucion, "%d", sudoku[i][j]);
  53.             if (j%3 == 2)
  54.                 fprintf (fSolucion, "|");
  55.             else
  56.                 fprintf (fSolucion, " ");
  57.         }
  58.         fprintf (fSolucion, "\n");
  59.  
  60.         if (i%3 == 2)
  61.             fprintf (fSolucion, "+-----+-----+-----+\n");
  62.     }
  63.     fprintf (fSolucion, "\n");
  64.  
  65.     return;
  66. }
  67.  
  68. int compruebaSudoku(const char sudoku[9][9], const int verbose)
  69. {
  70.     int i, j, x, y, retval=0;
  71.     /* Apariciones es un mapa de bits que recoge si un numero aparece o no
  72.        La correspondencia con los bits es:
  73.            987654321
  74.        Ej: 000010010 significa que el 5 y el 2 aparecen */
  75.     unsigned int apariciones;
  76.  
  77.     for (i=0; i<9; i++) // Por cada fila
  78.     {
  79.         apariciones = 0;
  80.         for (j=0; j<9; j++) // Por cada elemento de esa fila
  81.         {
  82.             if (sudoku[i][j] != 0)
  83.             {
  84.                 if ((apariciones & (1 << (sudoku[i][j]-1))) == 0)
  85.                     apariciones |= (1 << (sudoku[i][j]-1));
  86.                 else
  87.                 {
  88.                     if (verbose) printf ("ERROR: En la fila %d\n", i+1);
  89.                     return -1;
  90.                 }
  91.             }
  92.         }
  93.  
  94.         if (apariciones != 511) // Hay algun numero no seteado
  95.             retval = 1;
  96.     }
  97.  
  98.     for (i=0; i<9; i++) // Por cada columna
  99.     {
  100.         apariciones = 0;
  101.         for (j=0; j<9; j++) // Por cada elemento de esa columna
  102.         {
  103.             if (sudoku[j][i] != 0)
  104.             {
  105.                 if ((apariciones & (1 << (sudoku[j][i]-1))) == 0)
  106.                     apariciones |= (1 << (sudoku[j][i]-1));
  107.                 else
  108.                 {
  109.                     if (verbose) printf ("ERROR: En la columna %d\n", i+1);
  110.                     return -1;
  111.                 }
  112.             }
  113.         }
  114.     }
  115.  
  116.     for (i=0; i<9; i++) // Por cada casillero
  117.     {
  118.         apariciones = 0;
  119.         for (j=0; j<9; j++) // Por cada elemento de ese casillero
  120.         {
  121.             // i/3*3+j/3 donde i es el casillero y j el elemento del casillero es la posicion X en el sudoku
  122.             x = i/3*3+j/3;
  123.             // i%3*3+j%3 es la posicion Y en el sudoku
  124.             y = i%3*3+j%3;
  125.             if (sudoku[x][y] != 0)
  126.             {
  127.                 if ((apariciones & (1 << (sudoku[x][y]-1))) == 0 )
  128.                     apariciones |= (1 << (sudoku[x][y]-1));
  129.                 else
  130.                 {
  131.                     if (verbose) printf ("ERROR: En el casillero %d\n", i+1);
  132.                     return -1;
  133.                 }
  134.             }
  135.         }
  136.     }
  137.  
  138.     return retval;
  139. }
  140.  
  141. int generaPosibles (const char sudoku[9][9], int x, int y) // Usado para el metodo de recuento cruzado
  142. {
  143.     unsigned int posibles = 0;
  144.     int i;
  145.  
  146.     for (i=0; i<9; i++) // Por cada elemento de esa fila
  147.     {
  148.         if (sudoku[i][y] != 0)
  149.             posibles |= (1 << (sudoku[i][y]-1));
  150.     }
  151.  
  152.     for (i=0; i<9; i++) // Por cada elemento de esa columna
  153.     {
  154.         if (sudoku[x][i] != 0)
  155.             posibles |= (1 << (sudoku[x][i]-1));
  156.     }
  157.  
  158.     int casillero = (x/3*3) + (y/3);
  159.  
  160.     for (i=0; i<9; i++) // Por cada elemento del casillero
  161.     {
  162.         if (sudoku[casillero/3*3+i/3][casillero%3*3+i%3] != 0)
  163.             posibles |= (1 << (sudoku[casillero/3*3+i/3][casillero%3*3+i%3]-1));
  164.     }
  165.  
  166.     return posibles ^ 511; // XOR 111111111 para que los posibles sean 1
  167. }
  168.  
  169. void generaSudoku(const char sudoku[9][9])
  170. {
  171.     int x, y, i;
  172.     unsigned int posibles;
  173.  
  174.     char sudoku_copia[9][9];
  175.  
  176.     i = compruebaSudoku(sudoku, NO_VERBOSE);
  177.     if (i == 1) // El Sudoku esta incompleto
  178.     {
  179.         for (x=0; x<9; x++) // Buscamos en las casillas...
  180.         {
  181.             for (y=0; y<9; y++)
  182.             {
  183.                 if (sudoku[x][y] == 0) // ...hasta encontrar un 0
  184.                 {
  185.                     memcpy(sudoku_copia, sudoku, sizeof(sudoku_copia));
  186.  
  187.                     posibles = generaPosibles(sudoku, x, y);
  188.  
  189.                     for (i=1; i<=9; i++) // Probamos las 9 combinaciones...
  190.                     {
  191.                         if ((1 << (i-1)) & posibles) // ...siempre que sean validas
  192.                         {
  193.                             sudoku_copia[x][y] = i;
  194.                             generaSudoku(sudoku_copia);
  195.                             memcpy(sudoku_copia, sudoku, sizeof(sudoku_copia));
  196.                         }
  197.                     }
  198.                     return;
  199.                 }
  200.             }
  201.         }
  202.     }
  203.     else if (i == 0) // El Sudoku esta completo y es valido
  204.     {
  205.         solucion++;
  206.         imprimeSudoku(sudoku);
  207.     }
  208.  
  209.     return;
  210. }
  211.  
  212. int main(void)
  213. {
  214.     char sudoku[9][9];
  215.     FILE *fSudoku;
  216.  
  217.     char buffer;
  218.     char casilla = 0;
  219.  
  220.     memset(sudoku, -1, sizeof(sudoku));
  221.  
  222.     if ((fSudoku = fopen("sudoku.txt", "r")) == NULL)
  223.     {
  224.         printf ("ERROR: Abriendo el sudoku\n");
  225.         return -1;
  226.     }
  227.     if ((fSolucion = fopen("sudoku_sol.txt", "w")) == NULL)
  228.     {
  229.         printf ("ERROR: Creando el fichero de soluciones\n");
  230.         return -1;
  231.     }
  232.  
  233.     while (fread(&buffer, sizeof(char), 1, fSudoku)) // Leer el sudoku atendiendo solo a numeros 0-9
  234.     {
  235.         if (buffer >= 48 && buffer <= 57) // 48 = 0, 57 = 9
  236.         {
  237.             sudoku[casilla/9][casilla%9] = buffer - 48;
  238.             casilla++;
  239.         }
  240.  
  241.         if (casilla == 82)
  242.         {
  243.             printf ("ERROR: Demasiadas casillas\n");
  244.             return -1;
  245.         }
  246.     }
  247.  
  248.     if (sudoku[8][8] == -1)
  249.     {
  250.         printf ("ERROR: Faltan casillas\n");
  251.         return -1;
  252.     }
  253.  
  254.     int i = compruebaSudoku(sudoku, VERBOSE);
  255.     if (i < 0)
  256.         printf ("ERROR: Sudoku inicial con errores\n");
  257.     else if (i == 0)
  258.         printf ("ERROR?: Sudoku inicial completo\n");
  259.  
  260.     generaSudoku(sudoku);
  261.  
  262.     printf ("%d soluciones generadas en \"sudoku_sol.txt\"\n", solucion);
  263.  
  264.     return 0;
  265. }
  266.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement