python 数独实现

'''
Created on 2013-12-5

@author: ezonghu
'''
SDStr =  ["005000600080701040700060003090205060008040900060109080500090002040308010006000700",
          "800000000003600000070090200050007000000045700000100030001000068008500010090000400",
          "003279000020501009000080003000060500690003000005000000000000064700600080060920007",
          "142000387003040201080132005090000106000520704000004000608200009020000000001070000",
          "041020000000000007080005200610080000000010460000490050006000000437009106102000090",
          "000000100096200800800000600100082003000140060760050000600400901004020000950001000"] 
class Position(object):
    def __init__(self, *Pos):
        if len(Pos) == 1:
            self.pos = Pos[0]
            self.x = self.pos % 9
            self.y = self.pos // 9 
        elif len(Pos) == 2:
            self.x = Pos[0]
            self.y = Pos[1]
            self.pos = self.x + self.y * 9
        else:
            raise TypeError("only accept the number of the arguments <=2")
        self.areaX = self.x // 3
        self.areaY = self.y // 3
        self.area = self.areaX + self.areaY * 3

class Area(object):
    def __init__(self, ShuduList, *Pos):
        if len(Pos) == 1:
            self.areaPos = Pos[0]
            self.areaX = self.areaPos % 3
            self.areaY = self.areaPos // 3 
        elif len(Pos) == 2:
            self.areaX = Pos[0]
            self.areaY = Pos[1]
            self.areaPos = self.areaX + self.areaY * 3
        else:
            raise TypeError("only accept the number of the arguments <=2")    
        
        self.area = set()
        self.areaStart = (self.areaX*3, self.areaY*3)
        self.areaStop = (self.areaX*3+2, self.areaY*3+2)
        for Row in range(self.areaY*3, (self.areaY+1)*3):
            for Col in range(self.areaX*3, (self.areaX+1)*3):
                p = Position(Col, Row)
                if ShuduList[p.pos] != 0:
                    self.area.add(ShuduList[p.pos])
class Column(object):
    def __init__(self, ShuduList, Col):
        self.column = set()
        for i in range(9):
            p = Position(Col, i)
            if ShuduList[p.pos] != 0:
                self.column.add(ShuduList[p.pos])
    
class Row(object):
    def __init__(self, ShuduList, R):
        self.row = set()
        for i in range(9):
            p = Position(i, R)
            if ShuduList[p.pos] != 0:
                self.row.add(ShuduList[p.pos])
                
class Shudu(object):
    defaultRange = set(range(1,10))
    def __init__(self, SDL):
        self.sdList = [int(i) for i in SDL]
        
    def getColumn(self, C):
        return Column(self.sdList, C)
    
    def getRow(self, R):
        return Row(self.sdList, R)
    
    def getArea(self, A):
        return Area(self.sdList, A)
    
    def exclusion(self, P):
        pos = Position(P)
        r_s = self.getRow(pos.y).row
        c_s = self.getColumn(pos.x).column
        a_s = self.getArea(pos.area).area
        tmp = self.defaultRange - (r_s|c_s|a_s)
        return tmp

             
    
    def scanSDLOnce(self):
        changeFlag = False
        sdListRightOrNot = True
        for i in xrange(81):
            tmp = self.sdList[i]
            if 0 == tmp:
                res = self.exclusion(i)
                if 0 == len(res):
                    sdListRightOrNot = False
                    return changeFlag, sdListRightOrNot
                
                if 1 == len(res):
                    self.sdList[i] = res.pop()
                    changeFlag = True
            
        return changeFlag, sdListRightOrNot
    
    #return -1: Can't find the value that can change
    #return -2: the current Shudu List is wrong
    #return 0: get the final result
    def scanSDLWithGuess(self):
        while (0 in self.sdList):
            changeFlag, sdListRightOrNot = self.scanSDLOnce()
            
            if False == changeFlag:
                return -1
            
            if False == sdListRightOrNot:
                return -2
        
        return 0                  
    
    def scanSDL(self):
#         print self.sdList
        res = self.scanSDLWithGuess()
        if -1 == res:
            tmpSDL = list(self.sdList)
            minSet = self.defaultRange
            pos = -1
            #do assumption
            for i in xrange(81):
                if 0 == self.sdList[i]:
                    tmp = self.exclusion(i)
                    if 0 == len(tmp):
                        return -2
                    if len(minSet)>len(tmp):
                        minSet = tmp
                        pos = i
                        
            for assumption in minSet:
                self.sdList[pos]=assumption
                if self.scanSDL() < 0 :
                    self.sdList = tmpSDL
                else:
                    return 0
                
        
        if -2 == res:
            #return False
            return res
        
        return res                
                        
def evaluatePerformance():
    import cProfile
    global SDStr
    cProfile.run("Shudu(\"%s\").scanSDL()" % SDStr[1])        
           
def evaluateRunTime():
    global SDStr
    from timeit import Timer
    for SDL in SDStr:     
        print SDL
        t1 = Timer("print Shudu(\"%s\").scanSDL() == 0" % SDL, "from __main__ import Shudu")
        print sum(t1.repeat(10, 1))/10
    
if __name__ == '__main__' :
    evaluatePerformance()     

        


执行结果:

         2327043 function calls (2326791 primitive calls) in 6.578 seconds


   Ordered by: standard name


   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    6.578    6.578 <string>:1(<module>)
      253    0.003    0.000    4.977    0.020 shudu.py:109(scanSDLWithGuess)
    253/1    0.028    0.000    6.578    6.578 shudu.py:121(scanSDL)
   591780    3.413    0.000    3.623    0.000 shudu.py:13(__init__)
    21135    0.900    0.000    2.194    0.000 shudu.py:29(__init__)
    21135    0.625    0.000    1.830    0.000 shudu.py:50(__init__)
    21135    0.616    0.000    1.823    0.000 shudu.py:58(__init__)
        1    0.000    0.000    0.000    0.000 shudu.py:67(__init__)
    21135    0.062    0.000    1.892    0.000 shudu.py:70(getColumn)
    21135    0.063    0.000    1.886    0.000 shudu.py:73(getRow)
    21135    0.066    0.000    2.260    0.000 shudu.py:76(getArea)
    21135    0.288    0.000    6.458    0.000 shudu.py:79(exclusion)
      509    0.079    0.000    4.974    0.010 shudu.py:89(scanSDLOnce)
  1230853    0.224    0.000    0.224    0.000 {len}
   227308    0.084    0.000    0.084    0.000 {method 'add' of 'set' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     1329    0.001    0.000    0.001    0.000 {method 'pop' of 'set' objects}
   126810    0.127    0.000    0.127    0.000 {range}

'''
Created on 2013-12-28

@author: ezonghu
'''
'''
Created on 2013-12-5

@author: ezonghu
'''
SDStr =  ["005000600080701040700060003090205060008040900060109080500090002040308010006000700",
          "800000000003600000070090200050007000000045700000100030001000068008500010090000400",
          "003279000020501009000080003000060500690003000005000000000000064700600080060920007",
          "142000387003040201080132005090000106000520704000004000608200009020000000001070000",
          "041020000000000007080005200610080000000010460000490050006000000437009106102000090",
          "000000100096200800800000600100082003000140060760050000600400901004020000950001000"]                 
class Shudu(object):
    defaultRange = set(range(1,10))
    defaultPositions = [(i % 9, i //9)for i in xrange(81)]
    
    def __init__(self, SDL):
        self.sdList = [int(i) for i in SDL]
        
    def getColumn(self, C):
        ColSet = set()
        for i in xrange(9):
            element = self.sdList[i*9+C]
            if 0 != element:
                ColSet.add(element)
        return ColSet
    
    def getRow(self, R):
        RowSet = set()
        for i in xrange(9):
            element = self.sdList[R*9+i]
            if 0 != element:
                RowSet.add(element)
        return RowSet
    
    def getArea(self, X, Y):
        AreaSet = set()
        X1 = X // 3 * 3
        X2 = (X // 3+1) * 3
        Y1 = Y // 3 * 3
        Y2 = (Y // 3 + 1) * 3
        for i in xrange(Y1, Y2):
            for j in xrange(X1, X2):
                element = self.sdList[i * 9 + j]
                if 0 != element:
                    AreaSet.add(element)
        return AreaSet
    
    def exclusion(self, P):
        (posX, posY) = self.defaultPositions[P]
        r_s = self.getRow(posY)
        c_s = self.getColumn(posX)
        a_s = self.getArea(posX, posY)
        tmp = self.defaultRange - (r_s|c_s|a_s)
        return tmp

             
    
    def scanSDLOnce(self):
        changeFlag = False
        sdListRightOrNot = True
        for i in xrange(81):
            tmp = self.sdList[i]
            if 0 == tmp:
                res = self.exclusion(i)
                if 0 == len(res):
                    sdListRightOrNot = False
                    return changeFlag, sdListRightOrNot
                
                if 1 == len(res):
                    self.sdList[i] = res.pop()
                    changeFlag = True
            
        return changeFlag, sdListRightOrNot
    
    #return -1: Can't find the value that can change
    #return -2: the current Shudu List is wrong
    #return 0: get the final result
    def scanSDLWithGuess(self):
        while (0 in self.sdList):
            changeFlag, sdListRightOrNot = self.scanSDLOnce()
            
            if False == changeFlag:
                return -1
            
            if False == sdListRightOrNot:
                return -2
        
        return 0                  
    
    def scanSDL(self):
#         print self.sdList
        res = self.scanSDLWithGuess()
        if -1 == res:
            tmpSDL = list(self.sdList)
            minSet = self.defaultRange
            pos = -1
            #do assumption
            for i in xrange(81):
                if 0 == self.sdList[i]:
                    tmp = self.exclusion(i)
                    if 0 == len(tmp):
                        return -2
                    if len(minSet)>len(tmp):
                        minSet = tmp
                        pos = i
                        
            for assumption in minSet:
                self.sdList[pos]=assumption
                if self.scanSDL() < 0 :
                    self.sdList = tmpSDL
                else:
                    return 0
                
        
        if -2 == res:
            #return False
            return res
        
        return res                
                        
def evaluatePerformance():
    import cProfile
    global SDStr
    cProfile.run("Shudu(\"%s\").scanSDL()" % SDStr[1])        
           
def evaluateRunTime():
    global SDStr
    from timeit import Timer
    for SDL in SDStr:     
        print SDL
        t1 = Timer("print Shudu(\"%s\").scanSDL() == 0" % SDL, "from __main__ import Shudu")
        print sum(t1.repeat(10, 1))/10
    
if __name__ == '__main__' :
    evaluatePerformance()
   

        



优化代码之后的结果:

         361488 function calls (361236 primitive calls) in 1.086 seconds


   Ordered by: standard name


   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.086    1.086 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 shudu2.py:21(__init__)
    21135    0.195    0.000    0.221    0.000 shudu2.py:24(getColumn)
    21135    0.200    0.000    0.221    0.000 shudu2.py:32(getRow)
    21135    0.312    0.000    0.334    0.000 shudu2.py:40(getArea)
    21135    0.200    0.000    0.975    0.000 shudu2.py:53(exclusion)
      509    0.070    0.000    0.822    0.002 shudu2.py:63(scanSDLOnce)
      253    0.003    0.000    0.825    0.003 shudu2.py:83(scanSDLWithGuess)
    253/1    0.027    0.000    1.086    1.086 shudu2.py:95(scanSDL)
    47293    0.011    0.000    0.011    0.000 {len}
   227308    0.068    0.000    0.068    0.000 {method 'add' of 'set' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     1329    0.000    0.000    0.000    0.000 {method 'pop' of 'set' objects}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值