Skip to content

Instantly share code, notes, and snippets.

@matt-bernhardt
Last active January 4, 2016 07:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matt-bernhardt/8592179 to your computer and use it in GitHub Desktop.
Save matt-bernhardt/8592179 to your computer and use it in GitHub Desktop.
A sudoku solver, as I teach myself Python
#
# Translating the sudoku solver from VBScript to Python
#
# Libraries
from xlrd import open_workbook
from tempfile import TemporaryFile
from xlwt import Workbook
import datetime
from array import *
# global variables
log = ''
arrPuzzle = array('I',[0,])
arrPotential = array('I',[0,])
intFound = 0
intProgress = 0
def init():
global log
# Start up logging
timestamp = datetime.datetime.now().strftime("%Y_%m_%d_%H%M%S")
# log = open(str(timestamp)+'.txt','w')
log = open('logfile.txt','w')
log.write('Sudoku solver output\n\n')
initPuzzle()
initPotential()
def initPotential():
global log
global arrPotential
log.write('Initializing potentials array...\n')
arrPotential = [[[0 for x in xrange(9)] for x in xrange(9)] for x in xrange(9)]
for row in range(9):
for col in range(9):
for val in range(9):
arrPotential[row][col][val] = val+1
log.write('...potentials initialized\n')
log.write('\n')
def initPuzzle():
global log
global arrPuzzle
log.write('Initializing puzzle array...\n')
arrPuzzle = [[0 for x in xrange(9)] for x in xrange(9)]
log.write('...puzzle initialized\n')
log.write('\n')
printPuzzleState()
def checkCells():
global log
global arrPuzzle
global arrPotential
log.write('Checking cells for unique values\n')
for row in range(9):
for col in range(9):
log.write(' Cell '+str(row)+','+str(col)+' (')
printPuzzleLocation(row,col)
log.write(') ')
intFound = 0
intAvailable = 0
for val in range(1,10):
printPotentialLocation(row,col,val-1)
if(arrPotential[row][col][val-1]=='#'):
intFound = 1
elif(arrPotential[row][col][val-1]!=0):
intAvailable += 1
intCandidate = val
if(intFound==1):
log.write(' Already Found')
else:
log.write(' '+str(intAvailable)+' candidates')
if(intAvailable==1):
foundNumber(row,col,intCandidate)
log.write('\n')
log.write('\n')
def checkCols():
global log
global arrPuzzle
global arrPotential
log.write('Checking columns for unique values\n')
for col in range(9):
log.write('Column '+str(col)+': ')
# print column status for easier following in the log
for row in range(9):
printPuzzleLocation(row,col)
log.write("\n")
# iterate through each value, looking for any that can only exist in one location in the column
for val in range(1,10):
log.write(' Potentials for '+str(val)+': ')
intFound = 0
intAvailable = 0
for row in range(9):
printPotentialLocation(row,col,val-1)
if(arrPotential[row][col][val-1]=="#"):
intFound = 1
if(arrPotential[row][col][val-1]!=0):
intAvailable += 1
intCandidate = row
if(intFound==1):
log.write(" Already Found")
else:
log.write(" "+str(intAvailable)+" available")
if(intAvailable==1):
foundNumber(intCandidate,col,val)
log.write("\n")
log.write('\n')
def checkGroups():
global log
global arrPuzzle
global arrPotential
log.write('Checking groups\n')
# iterate through each of the 3x3 local groups rowG,rowC
for rowG in range(3):
for colG in range(3):
log.write(' Group '+str(rowG)+','+str(colG)+'\n')
# for each number
for val in range(1,10):
log.write(' Potential locations for '+str(val)+' ')
intFound = 0
intAvailable = 0
for row in range(3):
for col in range(3):
testRow = (rowG*3)+row
testCol = (colG*3)+col
printPotentialLocation( testRow , testCol , val-1 )
if(arrPotential[testRow][testCol][val-1]=='#'):
intFound = 1
elif(arrPotential[testRow][testCol][val-1]!=0):
intAvailable += 1
intCandidateRow = testRow
intCandidateCol = testCol
log.write(' ')
if(intFound==1):
log.write(' found')
else:
log.write(' '+str(intAvailable)+' available')
if(intAvailable==1):
foundNumber(intCandidateRow,intCandidateCol,val)
log.write('\n')
log.write('\n')
log.write('\n')
def checkRows():
global log
global arrPuzzle
global arrPotential
log.write('Checking rows for unique values\n')
for row in range(9):
log.write('Row '+str(row)+': ')
# print row status for easier following in the log
for col in range(9):
printPuzzleLocation(row,col)
log.write("\n")
# iterate through each value, looking for any that can only exist in one location in the row
for val in range(1,10):
log.write(' Potentials for '+str(val)+': ')
intFound = 0
intAvailable = 0
for col in range(9):
printPotentialLocation(row,col,val-1)
if(arrPotential[row][col][val-1]=="#"):
intFound = 1
if(arrPotential[row][col][val-1]!=0):
intAvailable += 1
intCandidate = col
if(intFound==1):
log.write(" found")
else:
log.write(" "+str(intAvailable)+" available")
if(intAvailable==1):
foundNumber(row,intCandidate,val)
log.write("\n")
log.write('...done checking rows\n\n')
def foundNumber(row,col,val):
global log
global arrPuzzle
global arrPotential
global intFound
global intProgress
log.write("Found "+str(val)+" at "+str(row)+","+str(col)+'\n')
intProgress = 1
intFound = intFound + 1
log.write(str(intFound)+" numbers have been found\n")
arrPuzzle[row][col] = val
printPuzzleState()
for x in range(9):
arrPotential[x][col][val-1] = 0
arrPotential[row][x][val-1] = 0
arrPotential[row][col][x] = 0
# Need to sort out the local group potential
gX = (row//3)*3
gY = (col//3)*3
for gRow in range(3):
for gCol in range(3):
arrPotential[gX+gRow][gY+gCol][val-1] = 0
# Re-assert arrPotential for this value
arrPotential[row][col][val-1] = "#"
# printPotentialState()
log.write('\n')
def loadPuzzle():
global log
global arrPuzzle
# Load puzzle into array
log.write('Loading puzzle...\n')
wb = open_workbook('sudoku.xls')
sheet = wb.sheet_by_index(0)
for row in range(sheet.nrows):
for col in range(sheet.ncols):
intValue = sheet.cell(row,col).value
if(intValue!=''):
foundNumber(row,col,int(intValue))
log.write('...puzzle loaded\n\n')
# printPuzzleState()
def printPuzzleLocation(row,col):
global log
global arrPuzzle
# log.write('('+str(row)+','+str(col)+')')
if(arrPuzzle[row][col]!=0):
log.write(str(arrPuzzle[row][col]))
else:
log.write('_')
# log.write(' ')
def printPotentialLocation(row,col,val):
global log
global arrPotential
if(arrPotential[row][col][val]!=0):
log.write(str(arrPotential[row][col][val]))
else:
log.write('_')
def printPuzzleState():
global log
global arrPuzzle
log.write('Puzzle state...\n')
for row in range(len(arrPuzzle)):
for col in range(len(arrPuzzle[row])):
printPuzzleLocation(row,col)
# intValue = '_' if arrPuzzle[row][col]==0 else arrPuzzle[row][col]
# log.write(str(intValue))
log.write('\n')
log.write('\n')
def printPotentialState():
global log
global arrPotential
global arrPuzzle
log.write('Potential state...\n')
for row in range(len(arrPotential)):
for col in range(len(arrPotential[row])):
log.write(str(row)+','+str(col)+': ')
printPuzzleLocation(row,col)
log.write(' ')
for val in range(len(arrPotential[row][col])):
printPotentialLocation(row,col,val)
log.write('\n')
log.write('\n')
log.write('\n')
for val in range(1,10):
log.write("#"+str(val)+"\n")
for row in range(9):
for col in range(9):
printPotentialLocation(row,col,val-1)
log.write("\n")
log.write("\n")
def main():
global log
global intProgress
init()
loadPuzzle()
printPotentialState()
while intProgress > 0:
log.write('\n')
log.write('###########################################################\n')
log.write('Starting Check Run\n')
printPuzzleState()
intProgress = 0
checkRows()
checkCols()
checkCells()
checkGroups()
log.write('\n')
log.write('###########################################################\n')
log.write('###########################################################\n')
log.write('Puzzle Terminating\n')
printPotentialState()
printPuzzleState()
if __name__ == "__main__":
main()
# End the script
print('Finished!')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment