'''
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}