import datetime
import copy
import random

__TIMES = 0

def crs(A,B):
    return [a+b for a in A for b in B]

_DTS = '123456789'
_RS = 'ABCDEFGHI'
_RU = ('ABC','DEF','GHI')
_CS = _DTS
_CU = ('123','456','789')
_SQS = crs(_RS,_CS)
_UL = [crs(_RS,c) for c in _CS]+[crs(r,_CS) for r in _RS] + [crs(r1,c1) for r1 in _RU for c1 in _CU]
_US = dict((s,[u for u in _UL if s in u]) for s in _SQS)
_PS = dict((s,set(sum(_US[s],[]))-set([s])) for s in _SQS)

def getValue(src):
    cs = [c for c in src if c in _DTS or c in '0. ']
    if(len(cs)!=81):
        print('Wrong Sudoku')
        return False
    valueso = dict(zip(_SQS,cs))
    values = dict((s,_DTS) for s in _SQS)
    for s,d in valueso.items():
        if(d in _DTS and not assignValue(values,s,d)):
            return False
    return values

def assignValue(values,s,d):
    valuesToElim = values[s].replace(d,'')
    if(all(elimValue(values,s,d) for d in valuesToElim)):
        return values
    else:
        return False

def elimValue(values,s,d):
    if(d not in values[s]):
        return values
    values[s] = values[s].replace(d,'')
    if(len(values[s])==0):
        return False
    elif(len(values[s])==1):
        d1 = values[s]
        if(not all(elimValue(values,s1,d1) for s1 in _PS[s])):
            return False
    for u in _US[s]:
        dp = [s2 for s2 in u if d in values[s2]]
        if(len(dp)==0):
            return False
        elif(len(dp)==1):
            if(not assignValue(values,dp[0],d)):
                return False
    return values

def getAnswer(seq):
    for e in seq:
        if(e):
            return e
    return False

def search(values):
    if(values is False):
        return False
    global __TIMES
    __TIMES += 1
    if(all(len(values[s])==1 for s in _SQS)):
        return values
    n,s = min((len(values[s]),s) for s in _SQS if len(values[s])>1)
    return getAnswer(search(assignValue(values.copy(),s,d)) for d in values[s])

def printSudoku(values):
    if(values is False):
        print 'Failed'
        return False
    line = '+'.join(['-' * 3 * 2] * 3)
    for r in _RS:
        print (''.join(values[r+c].center(2) + ('|' if c in '36' else '') for c in _CS))
        if(r in 'CF'):
            print line
    print

grid1 = '800000000003600000070090200050007000000045700000100030001000068008500010090000400'

printSudoku(search(getValue(grid1)))
print('search times:' + str(__TIMES))

 

posted on 2013-05-27 20:52  fenix  阅读(217)  评论(0编辑  收藏  举报