'''Simple text based Sudoku solver.'''__author__='Justin Shaw'importcopydefuniqueInsert(l,v):''' Add v to list if it is not already there, else raise ValueError '''ifvisnotNone:ifvinl:raiseValueError('list already contains value %s'%v)assert0<v<10,'Only 1-9 allowed, got %s'%vl.append(v)classSudoku:defsubmat(self,i,j):''' Return i, j 3x3 submatrix of self. '''mat=self.matout=[]forsrow_iinrange(3):row=[]forscol_iinrange(3):v=mat[i*3+srow_i][j*3+scol_i]row.append(v)out.append(row)returnoutdefcopy(self):returnSudoku(copy.deepcopy(self.mat))defadd(self,v,i,j):''' Fill in an entry in self.mat '''self.mat[i][j]=vuniqueInsert(self.rows[i],v)uniqueInsert(self.cols[j],v)sub_i=i//3*3+j//3uniqueInsert(self.subs[sub_i],v)def__init__(self,mat):''' Create a new Sudoku instance. mat -- 9x9 array of digits 1-9 or None if no value is known for that spot '''self.mat=mat# keep track of all values used in each row, column and sub-matrix.rows=[[]foriinrange(9)]cols=[[]foriinrange(9)]subs=[[]foriinrange(9)]forrow_iinrange(9):forcol_iinrange(9):v=self.mat[row_i][col_i]uniqueInsert(rows[row_i],v)uniqueInsert(cols[col_i],v)forsrow_iinrange(3):forscol_iinrange(3):sub=self.submat(srow_i,scol_i)foriinrange(3):forjinrange(3):v=sub[i][j]sub_i=srow_i*3+scol_iuniqueInsert(subs[sub_i],v)self.rows=rowsself.cols=colsself.subs=subsdef__repr__(self):out=''foriinrange(9):ifi%3==0:out+='+-------+-------+-------+\n'forjinrange(9):ifj%3==0:out+='| 'v=self.mat[i][j]ifvisnotNone:out+='%1d '%velse:out+=' 'out+='|\n'out+='+-------+-------+-------+\n'returnoutdefsolve(self):''' Solve for the unknown positions of the puzzle '''min_poss=9# Minimum possible number of choices for a celldone=Trueforiinrange(9):forjinrange(9):sub_i=i//3*3+j//3# sub-matrix indexv=self.mat[i][j]ifv:passelse:# not all values filled out so we are not done yetdone=Falseall=set(range(1,10))# determine all possible values for this cellpossible=(all.difference(self.rows[i]).difference(self.cols[j]).difference(self.subs[sub_i]))# see if we have run into a brick walliflen(possible)==0:raiseValueError('Sudoku not solvable')eliflen(possible)<min_poss:# keep track of cell with smallest number of choicesmin_poss=len(possible)best=possiblemin_i=imin_j=jifdone:out=selfelse:# Try these possibilities and recurseforbinbest:printmin_i,min_j,btrial=self.copy()trial.add(b,min_i,min_j)printtrialtry:soln=trial.solve()breakexceptValueError:soln=NoneifsolnisNone:printselfraiseValueError('Sudoku not solvable')out=solnreturnoutN=Noneeasy=[[7,N,N,1,5,N,N,N,8],[N,N,4,N,N,2,N,N,N],[N,N,N,N,N,4,5,6,N],[6,N,N,N,N,N,N,2,9],[5,N,2,N,N,N,8,N,4],[3,4,N,N,N,N,N,N,1],[N,3,8,6,N,N,N,N,N],[N,N,N,2,N,N,9,N,N],[1,N,N,N,8,N,N,N,3]]hard=[[N,4,N,N,N,7,9,N,N],[N,N,8,5,3,9,N,N,N],[N,6,N,N,N,N,2,N,3],[N,N,N,N,N,2,5,N,N],[N,8,6,N,N,N,1,4,N],[N,N,9,8,N,N,N,N,N],[6,N,3,N,N,N,N,9,N],[N,N,N,9,8,6,3,N,N],[N,N,1,4,N,N,N,6,N]]evil=[[4,2,N,N,N,N,N,1,N],[N,N,N,5,4,N,N,3,N],[N,N,6,N,N,7,N,N,N],[N,N,N,N,N,N,2,7,9],[N,1,N,N,N,N,N,6,N],[3,4,2,N,N,N,N,N,N],[N,N,N,9,N,N,3,N,N],[N,6,N,N,3,8,N,N,N],[N,8,N,N,N,N,N,5,7]]blank=[[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N],[N,N,N,N,N,N,N,N,N]]importtimeeasy=Sudoku(easy)hard=Sudoku(hard)evil=Sudoku(evil)printprint'easy'printeasytime.sleep(2)easy.solve()printprint'hard'printhardtime.sleep(2)hard.solve()printprint'evil'printevilprinttime.sleep(2)evil.solve()

Hey, if you can't sleep because of Sudoku, may as well solve the general problem!