Apuntes_Python/05_diez_proyectos/08-sudoku_solver/sudoku.py
2022-12-24 22:41:20 -03:00

93 lines
2.9 KiB
Python

def encuentra_prox_vacio(puzzle):
"""
Encuentra la próxima fila, columna del puzzle sin llenar
(están representadas como -1)
retorna tupla (indice fila, indice columna) o (None, None)
en caso de no existir.
"""
for f in range(9):
for c in range(9):
if puzzle[f][c] == -1:
return f, c
return None, None
def es_valida(puzzle, intento, fil, col):
"""
Valida el intento en fila/columna
retorna True si es valida, Falso si no.
"""
# comenzar con los valores de fila:
fil_vals = puzzle[fil]
if intento in fil_vals:
return False
# ahora los valores de columna
#col_vals = []
#for i in range(9):
# col_vals.append(puzzle[i][col])
col_vals = [puzzle[i][col] for i in range(9)]
if intento in col_vals:
return False
# ahora el bloque 3x3
# encontrar donde empieza cada bloque, e iterar sobre
# los 3 valores de fila/columna
fil_start = (fil // 3) * 3
col_start = (col // 3) * 3
for f in range(fil_start, fil_start + 3):
for c in range(col_start, col_start +3):
if puzzle[f][c] == intento:
return False
# Al llegar aquí el intento es válido
return True
def resolver_sodoku(puzzle):
"""
Resuelve sodoku usando 'backtracking'.
El puzzle es una lista de listas, donde cada
lista interna es una fila en el puzzle.
retorna exista solución o no.
"""
# paso 1: Escoger un lugar en el puzzle para intetar solución
fil, col = encuentra_prox_vacio(puzzle)
# paso 1.1: Validación
if fil is None:
return True
# paso 2: Si hay lugar para poner un número, entonces hace un intento (1-9)
for intento in range(1, 10):
# paso 3: validar posición
if es_valida(puzzle, intento, fil, col):
# paso 3.1: intento validado, proceder con la jugada
puzzle[fil][col] = intento
# paso 4: llamado recursivo a funcion resolver_sodoku()
if resolver_sodoku(puzzle):
return True
# paso 5: si el intento no es válido o no resuelve el puzzle
# entoncens retroceder un paso y haver nuevo intento
puzzle[fil][col] = -1 # resetea el intento
# paso 6: si ningún intento funcion entonves el puzzle no tiene solución
return False
if __name__ == '__main__':
tablero_ejemplo = [
[3, 9, -1, -1, 5, -1, -1, -1, -1],
[-1, -1, -1, 2, -1, -1, -1, -1, 5],
[-1, -1, -1, 7, 1, 9, -1, 8, -1],
[-1, 5, -1, -1, 6, 8, -1, -1, -1],
[2, -1, 6, -1, -1, 3, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, 4],
[5, -1, -1, -1, -1, -1, -1, -1, -1],
[6, 7, -1, 1, -1, 5, -1, 4, -1],
[1, -1, 9, -1, -1, -1, 2, -1, -1]
]
print(resolver_sodoku(tablero_ejemplo))
print(tablero_ejemplo)