PI-ITBA / 2024_01

8 stars 0 forks source link

TP06_EJ20 #62

Closed juliapriolo closed 3 months ago

juliapriolo commented 6 months ago

Buenas! Queria saber si esta bien o como podria mejorarlo. Gracias

#include <stdio.h>
#include <assert.h>
#define DIM 9
#define DIM_SUB 3

int sudokuSolver(char m[][DIM]);
int verificaNum(int num);
int verificaSub(const char m[][DIM],int fila, int columna);
int verificaFila(const char fila[]);
int verificaCol(const char m[][DIM], unsigned int col);

int main(void) {
  // Una matriz vacía no es solución
  char sudoku[DIM][DIM] = {{0}};

  assert(sudokuSolver(sudoku)==0);

  char sudoku2[DIM][DIM] = {
        {3,8,1,9,7,6,5,4,2}, 
        {2,4,7,5,3,8,1,9,6},
        {5,6,9,2,1,4,8,7,3},
        {6,7,4,8,5,2,3,1,9},
        {1,3,5,7,4,9,6,2,8},
        {9,2,8,1,6,3,7,5,4},
        {4,1,2,6,8,5,9,3,7},
        {7,9,6,3,2,1,4,8,5},
        {8,5,3,4,9,7,2,6,1}
  };

  assert(sudokuSolver(sudoku2)==1);

  char sudoku3[DIM][DIM] = {
        {2,8,1,9,7,6,5,4,2}, 
        {3,4,7,5,3,8,1,9,6},
        {5,6,9,2,1,4,8,7,3},
        {6,7,4,8,5,2,3,1,9},
        {1,3,5,7,4,9,6,2,8},
        {9,2,8,1,6,3,7,5,4},
        {4,1,2,6,8,5,9,3,7},
        {7,9,6,3,2,1,4,8,5},
        {8,5,3,4,9,7,2,6,1}
  };

  assert(sudokuSolver(sudoku3)==0);

  // Cuando se tomó este ejercicio en un parcial, en una de las respuestas
  // sólo chequeaban que la suma de cada fila, columna y cuadrado fuera 45
  char sudoku4[DIM][DIM] = {
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}, 
        {5,5,5,5,5,5,5,5,5}
  };

  assert(sudokuSolver(sudoku4)==0);

  char sudoku5[DIM][DIM] = {
        {3,8,1,9,7,6,5,4,12}, 
        {2,4,7,5,3,8,1,9,6},
        {5,6,9,2,1,4,8,7,3},
        {6,7,4,8,5,2,3,1,9},
        {1,3,5,7,4,9,6,2,8},
        {9,2,8,1,6,3,7,5,4},
        {4,1,2,6,8,5,9,3,7},
        {7,9,6,3,2,1,4,8,5},
        {8,5,3,4,9,7,2,6,1}
  };

  assert(sudokuSolver(sudoku5)==0);

  printf("OK\n");

  return 0;
}

int sudokuSolver(char m[][DIM]){

   //chequeo subcuadrados
    for(int i=0; i < DIM; i+= DIM_SUB){
        for(int j=0; j < DIM; j+= DIM_SUB){
            if (!verificaSub(m, i, j)){
                return 0;
            }
        }
    }

   //chequeo filas
    for(int k=0; k<DIM; k++){
        if(!verificaFila(m[k])){
            return 0;
        }
    }

    //chequeo columnas
    for(int n = 0; n<DIM; n++){
        if(!verificaCol(m, n)){
            return 0;
        }
    }

return 1; 
}

int verificaNum(int num){
    if(num < 0 || num > 9){
        return 0;
    }
return 1;
}

int verificaSub(const char m[][DIM], int fila, int columna){
    char aux[DIM] = {0};
    int indice;
    for(int i=fila; i<fila + DIM_SUB; i++){
        for(int j=columna; j<columna+ DIM_SUB; j++){
            if(!verificaNum(m[i][j])){
                return 0;
            }
            indice = m[i][j] - 1;
            if(aux[indice] == 0){
                aux[indice]++;
            }
            else{
                return 0;
            }
        }
    }
return 1;
}

int verificaFila(const char fila[]){
    char aux[DIM] = {0};
    int indice;
    for(int i=0; i < DIM; i++){
        if(!verificaNum(fila[i])){
            return 0;
        }
        indice = fila[i] - 1;
        if(aux[indice] == 0){
            aux[indice]++;
        }
        else{
            return 0;
        }
    }
return 1;
}

int verificaCol(const char m[][DIM], unsigned int col){
    char aux[DIM] = {0};
    int indice;
    for(int i=0; i<DIM; i++){
        if(!verificaNum(m[i][col])){
            return 0;
        }
        indice = m[i][col] - 1;
        if(aux[indice] == 0){
            aux[indice]++;
        }
        else{
            return 0;
        }
    }
return 1;
}
marcelogarberoglio commented 6 months ago

En cuanto a estilo (hay ejemplos en las teóricas, en las guías y en el apunte sobre estilo), cambiaría esto

int verificaNum(int num){
    if(num < 0 || num > 9){
        return 0;
    }
return 1;
}

por esto

int verificaNum(int num){
    return num > 0 && num <= 9;
}

o haría la verificación directamente, sin usar una función auxiliar, en la función verificaSub. En las que verifican filas y columnas ya no sería necesario pues se verificó en la otra función antes (si bien el código quedaría un poco acoplado al orden en que se ejecutan las funciones, yo sacrificaría eso por eficiencia, y no hacer tres veces la misma verificación)

Como verás, son correcciones menores, así que podríamos decir que está muy bien.