#!/usr/bin/python # TODO: Make solve function faster!!! Have it check for singles, doubles, # triples, and quads both naked and hidden from random import random def rand(lst): "returns a random element in list or integer" if type(lst)==type([]): return lst[int(random()*len(lst))] elif type(lst)==type(0): return int(random()*lst) else: raise Exception,"don't know what do do with type %s!!!"%type(lst) def reorder(lst): "reorders a list to a random order" ret=[] for item in lst: ret.insert(rand(len(ret)),item) return ret def row(row,puzzle): return puzzle[row*9:row*9+9] def col(col,puzzle): ret=[] for i in range(9): ret.append(row(i,puzzle)[col]) return ret def box(box,puzzle): x=box%3 if box<3: y=0 elif box<6: y=1 else: y=2 ret=[] for i in range(3): ret.extend(row(y*3+i,puzzle)[x*3:x*3+3]) return ret def remaining(wcb): ret=[] for i in range(1,10): if not i in wcb: ret.append(i) return reorder(ret) # does not significantly slow program # and allows for generation of random puzzles def coordToBox(x,y): box=0 if x<3: pass elif x<6: box+=1 else: box+=2 if y<3: pass elif y<6: box+=3 else: box+=6 return box def coordToLinear(x,y): return y*9+x def linearToCoord(index): y=8 for i in range(9): if index<i*9: y-=1 x=index%9 return x,y def possible(x,y,puzzle): if not puzzle[coordToLinear(x,y)]==0: return [puzzle[coordToLinear(x,y)]] imp=[] imp.extend(row(y,puzzle)) imp.extend(col(x,puzzle)) imp.extend(box(coordToBox(x,y),puzzle)) return remaining(imp) def printPuzzle(puzzle): string=((((("%s "*3)+"| ")*2+("%s "*3)+"\n")*3+"------|-------|------\n")*3)[:-22]+"\n" text=(string%tuple(puzzle)).replace("0","_") print text, return text def check(x,y,puzzle): for i in range(9): if not i==y and len(possible(x,i,puzzle))==0: return False if not i==x and len(possible(i,y,puzzle))==0: return False box_x,box_y=linearToCoord(coordToBox(x,y)) for i in range(box_x,box_x+3): if i==x: break for j in range(box_y,box_y+3): if j==y: break if len(possible(i,j,puzzle))==0: return False return True def solve(puzzle,start=0): # TODO: Make this function faster!!! if start==81: return [puzzle[:]] ret=[] x,y=linearToCoord(start) possibilities=possible(x,y,puzzle) if len(possibilities)==0: return for possibility in possibilities: p=puzzle[:] p[coordToLinear(x,y)]=possibility x,y=linearToCoord(start) if not check(x,y,puzzle): continue solved=solve(p,start+1) if solved: ret.extend(solved) if 1<len(ret): # there is more than one puzzle return ret # enough already!!! return ret def solve_no_check_for_dups(puzzle,start=0): "This solver function does not check for multiple solutions." if start==81: return puzzle[:] x,y=linearToCoord(start) possibilities=possible(x,y,puzzle) if len(possibilities)==0: return for possibility in possibilities: p=puzzle[:] p[coordToLinear(x,y)]=possibility x,y=linearToCoord(start) if not check(x,y,puzzle): continue solved=solve_no_check_for_dups(p,start+1) if solved: return solved return [] def generate(sym=True,goodness=0): # goodness=0 means evil if sym: RANGE=41 else: RANGE=81 puzzle=[0]*81 soln=solve_no_check_for_dups(puzzle) puzzle=soln[:] spaces=range(RANGE) for i in range(RANGE-goodness): space=spaces.pop(rand(len(spaces))) puzzle[space]=0 if sym: puzzle[80-space]=0 if 1<len(solve(puzzle)): puzzle[space]=soln[space] if sym: puzzle[80-space]=soln[80-space] return puzzle #puzzle=[] #for i in range(9): # puzzle.extend(map(int,raw_input().split())) try: import psyco psyco.full() except ImportError: print "You do not have psyco installed. The program will run slower." if __name__=="__main__": #puzzle=generate() #printPuzzle(puzzle) #soln=solve(puzzle) #printPuzzle(soln[0]) #if 1<len(soln): # print "More than one solution!!!" #puzzle=generate(sym=False) #printPuzzle(puzzle) #soln=solve(puzzle) #printPuzzle(soln[0]) #if 1<len(soln): # print "More than one solution!!!" from time import sleep while True: puzzle=generate(sym=False) text=printPuzzle(puzzle) f=open("./sudoku","a") f.write(text) f.close() sleep(180)