Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import random
- import math
- import time
- import keyboard
- import pickle
- matriz = [8,0,0,0,0,3,0,0,0,0,0,0,0,0,8,6,0,7,0,0,0,0,6,0,0,0,0,5,0,0,0,0,0,0,0,0,9,7,0,5,0,1,4,0,0,0,0,0,0,0,0,1,0,3,0,6,5,0,4,0,0,3,0,3,0,0,0,0,0,9,1,0,2,0,0,1,0,0,0,0,0]
- matriz2 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
- matriz4 = [0, 6, 7, 8, 0, 2, 3, 4, 1, 0, 15, 16, 9, 14, 11, 12, 1, 2, 11, 12, 5, 6, 7, 8, 9, 14, 3, 0, 0, 0, 15, 16, 9, 10, 3, 4, 1, 14, 15, 16, 13, 2, 11, 12, 5, 6, 7, 8, 13, 14, 15, 16, 9, 0, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15, 6, 5, 8, 7, 2, 1, 4, 3, 14, 13, 16, 15, 10, 9, 12, 11, 10, 9, 12, 11, 14, 13, 16, 15, 2, 1, 4, 3, 6, 5, 8, 7, 14, 13, 16, 15, 10, 9, 12, 11, 6, 5, 8, 7, 2, 1, 4, 3, 3, 4, 1, 2, 7, 8, 5, 6, 11, 12, 9, 10, 15, 16, 13, 14, 7, 8, 5, 6, 3, 4, 1, 2, 15, 16, 13, 14, 11, 12, 9, 10, 11, 12, 9, 10, 15, 16, 13, 14, 3, 4, 1, 2, 7, 8, 5, 6, 15, 16, 13, 14, 11, 12, 9, 10, 7, 8, 5, 6, 3, 4, 1, 2, 4, 3, 2, 1, 8, 7, 6, 5, 0, 0, 10, 9, 16, 15, 0, 13, 8, 7, 6, 0, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 0, 0, 12, 11, 10, 9, 16, 15, 0, 13, 4, 3, 2, 1, 8, 7, 6, 5, 16, 15, 14, 13, 12, 11, 0, 9, 8, 0, 6, 5, 4, 3, 2, 0]
- def cantidadDeUnMismoCaracter(str, char):
- total = 0
- for i in range(0, len(str) - 1):
- if str[i] == char:
- total += 1
- return total
- def verificarSiArchivoContieneCeros(file):
- with open(file, 'rb') as input:
- try:
- strTemp = input.read()
- if strTemp.find(b'0') != -1:
- input.close()
- return True
- except EOFError:
- pass
- except:
- raise
- input.close()
- return False
- def save_object(obj, filename):
- with open(filename, 'wb') as output: # Overwrites any existing file.
- try:
- pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
- except:
- print("Error in save_object")
- output.close()
- def load_object(obj, filename):
- with open(filename, 'rb') as input:
- try:
- obj = pickle.load(input)
- except EOFError:
- pass
- except:
- raise
- input.close()
- return obj
- class Sudoku:
- def __init__(self, file, N=0): #agregar un sub_i para decirle en qué pos debería estar.
- self.file = file
- if N > 0:
- self.createANxNEmpty(N)
- return
- self.cells = []
- self.stackSolver = []
- self.key_down_c = False
- self.key_up_c = False
- f = open(file, 'r')
- str = f.readline()
- self.n = cantidadDeUnMismoCaracter(str, ',')
- self.nsq = int(math.sqrt(self.n));
- self.nn = self.n * self.n;
- self.precalcA = self.n * self.nsq;
- self.solutionCounter = 0
- self.saliendo = False
- for i in range(self.n):
- str = str.replace(" ", "")
- columna = 0
- while (str != '\n' and str != ''):
- separatorPos = str.find(',')
- strTemp = str[0:separatorPos]
- str = str[separatorPos + 1:len(str)]
- self.cells.insert(i * self.n + columna, int(strTemp))
- columna = columna + 1
- str = f.readline()
- f.close()
- self.firstEmptyPos = self.searchFirstEmpty()
- self.lastEmptyPos = self.searchLastEmpty()
- def saveSudoku(self):
- strTemp = ""
- for i in range(self.nn):
- strTemp += str(self.cells[i]) + ","
- if i % self.n:
- strTemp += "\n"
- os.remove(self.file)
- with open(self.file, 'wb') as output:
- try:
- return
- except:
- print("Error in saveSudoku")
- output.close()
- def createANxNEmpty(self, N):
- self.cells = []
- self.stackSolver = []
- self.n = N
- self.nsq = int(math.sqrt(self.n));
- self.nn = self.n * self.n;
- self.precalcA = self.n * self.nsq;
- self.solutionCounter = 0
- self.saliendo = False
- self.key_down_c = False
- self.key_up_c = False
- for i in range(self.nn):
- self.cells.insert(i, 0)
- self.firstEmptyPos = self.searchFirstEmpty()
- self.lastEmptyPos = self.searchLastEmpty()
- def filaValida(self, index, value):
- filaActualIndex = int(index / self.n) * self.n
- for i in range(self.n):
- if self.cells[filaActualIndex + i] == value:
- return False
- return True
- def columnaValida(self, index, value):
- columnaActual = index % self.n
- for i in range(self.n):
- if self.cells[columnaActual + (i * self.n)] == value:
- return False
- return True
- def cuadranteValido(self, index, value):
- cuadranteLeftIndex = int((index / self.nsq) % self.nsq) * self.nsq
- cuadranteTopIndex = int(index / self.precalcA) * self.precalcA
- for i in range (self.n):
- offsetLeft = int(i / self.nsq)
- offsetTop = i % self.nsq
- if self.cells[cuadranteTopIndex + cuadranteLeftIndex + (offsetTop * self.n) + offsetLeft] == value:
- return False
- return True
- def posicionEsValida(self, index, value):
- return (self.filaValida(index, value) and self.columnaValida(index, value) and self.cuadranteValido(index, value))
- def showSolution(self):
- tempStr = " " + "_" * (self.n * (self.nsq - 1) - 1) + "\n"
- counterTop = 0
- for i in range(self.nn):
- left = i % self.nsq
- if not left:
- tempStr += "| "
- tempStr += str(self.cells[i]) + " "
- if ((i + 1) % self.n) == 0:
- counterTop += 1
- if counterTop == self.nsq:
- tempStr += " |\n|" + "_" * (self.n * (self.nsq - 1) - 1) + "| \n"
- counterTop = 0
- else:
- tempStr += " |\n"
- print(tempStr)
- def searchFirstEmpty(self):
- for i in range(0, self.nn, 1):
- if self.cells[i] == 0:
- return i
- return self.nn
- def searchLastEmpty(self):
- for i in range(self.nn - 1, -1, -1):
- if self.cells[i] == 0:
- return i
- return self.nn
- def next(self):
- for i in range(self.lastEmptyPos, self.firstEmptyPos - 1, - 1):
- if self.cells[i] == 0:
- self.lastEmptyPos = i
- return i
- return self.firstEmptyPos
- def keyeventsManager(self):
- if self.saliendo:
- return
- if keyboard.is_pressed('c'):
- self.key_down_c = True
- return
- if not keyboard.is_pressed('c') and self.key_down_c:
- self.key_up_c = True
- if self.key_up_c:
- self.key_up_c = False
- self.key_down_c = False
- path = input("Ingresa el directorio para el archivo temporal, con extensión '.bk': ")
- save_object(self, path)
- self.saliendo = True
- return
- def solve(self, p = 0):
- if not (self.cells[self.firstEmptyPos] == 0):
- self.showSolution()
- return True
- self.keyeventsManager()
- if self.saliendo:
- return False
- pos = self.next()
- for i in range(1, self.n + 1):
- if self.posicionEsValida(pos, i):
- self.cells[pos] = i
- self.stackSolver.append(pos)
- if self.solve():
- return True
- self.cells[pos] = 0
- self.lastEmptyPos = pos
- if self.saliendo:
- return False
- return False
- def solveAllSolutions(self):
- if not (self.cells[self.firstEmptyPos] == 0):
- self.showSolution()
- self.solutionCounter += 1
- if self.solutionCounter >= 10:
- return
- pos = self.next()
- for i in range(1, self.n + 1):
- if self.posicionEsValida(pos, i):
- self.cells[pos] = i
- self.solveAllSolutions()
- self.cells[pos] = 0
- self.lastEmptyPos = pos
- def solve_all_stack(self):
- pos = self.next()
- self.stackSolver.append(1)
- while len(self.stackSolver) > 0:
- i = self.stackSolver.pop()
- if i == 1:
- self.keyeventsManager()
- if self.saliendo or self.solutionCounter >= 10:
- return
- pos = self.next()
- if i > self.n:
- i = self.stackSolver.pop()
- pos = self.stackSolver.pop()
- self.cells[pos] = 0
- self.lastEmptyPos = pos
- self.stackSolver.append(i + 1)
- elif self.posicionEsValida(pos, i):
- self.cells[pos] = i
- self.stackSolver.append(pos)
- self.stackSolver.append(i)
- self.stackSolver.append(1)
- else:
- self.stackSolver.append(i + 1)
- if not (self.cells[self.firstEmptyPos] == 0):
- self.showSolution()
- self.solutionCounter += 1
- return False
- def solve_stack(self):
- pos = self.next()
- self.stackSolver.append(1)
- #(*)
- #if len(self.stackSolver) > 2:
- #self.stackSolver.pop()#deleteamos el stack de arriba sólo si es una re-entrada al solve, así seguimos trabajando sobre el stack anterior.
- while len(self.stackSolver) > 0:
- i = self.stackSolver.pop()
- if i == 1:#cuando i==1, recién entra en el solve.
- self.keyeventsManager() #Lo meto acá, sino me consume todo el CPU.
- if self.saliendo:
- #self.stackSolver.append(i) #No lo agrego, ya que, como será append(1), concuerda con el stack inicial del programa. (*)
- return False
- pos = self.next()
- if i > self.n: #acá hubo return False
- i = self.stackSolver.pop()
- pos = self.stackSolver.pop()
- self.cells[pos] = 0
- self.lastEmptyPos = pos
- self.stackSolver.append(i + 1) #acá ya hubo el return, por lo que está cargando los i que faltaban. Si estaba en i=6, sigue por el 7 hasta el N.
- elif self.posicionEsValida(pos, i): #acá llama al solve() y hace push en la pila.
- self.cells[pos] = i
- self.stackSolver.append(pos) #stack previo
- self.stackSolver.append(i) #stack previo
- #call solve()
- self.stackSolver.append(1)
- else:
- self.stackSolver.append(i + 1)
- if not (self.cells[self.firstEmptyPos] == 0):
- self.showSolution()
- return True
- return False
- def __str__(self):
- return "Info. Sudoku: " + str(self.cells) + " first: " + str(self.firstEmptyPos) + " last: " + str(self.lastEmptyPos)
- def modo_solver():
- path = input("Ingrese el directorio junto con el nombre del archivo a analizar y resolver: ")
- test = Sudoku
- if path[len(path) - 2 : len(path)] == "bk":
- test = load_object(test, path)
- else:
- test = Sudoku(path)
- print(test.cells)
- tstart = time.time()
- test.solve_stack()
- totaltime = time.time() - tstart
- nstr = str(test.n) + "x" + str(test.n)
- print("Resolución de Sudoku:", nstr, "Tiempo transcurrido =", totaltime)
- def modo_creator():
- for i in range(3, 10):
- test = Sudoku("", i*i)
- test.solutionCounter = 0
- tstart = time.time()
- #test.solveAllSolutions()
- test.solve_all_stack()
- totaltime = time.time() - tstart
- print("NxN / N =", i*i, "=> Tiempo transcurrido =", totaltime)
- if __name__ == "__main__":
- print(verificarSiArchivoContieneCeros("C:\\Users\\Fernando\\Desktop\\uno.txt"))
- print(verificarSiArchivoContieneCeros("C:\\Users\\Fernando\\Desktop\\cero.txt"))
- print("Si desea entrar en modo solver (resolver sudokus desde un archivo dado), presione 1.")
- print("Si desea entrar en modo creator (crear 10 sudokus posibles NxN desde 0), presione 2.")
- print("Recuerde que si desea guardar la solución en progreso, puede presionar Ctrl + C, y guardará en un archivo temporal para luego cargarlo y seguir solucionando el problema.")
- while (True):
- if keyboard.is_pressed('1'):
- modo_solver()
- break
- elif keyboard.is_pressed('2'):
- modo_creator()
- break
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement