四年前,我写了一个Sudoku拼图求解器,现在我试图了解它是如何工作的,以便我可以重用零件它是一个KenKen难题求解器。我认为我更好地将循环压缩到列表解析中,并为变量选择更多自解释名称。一个在Python 2.5中表现不同的案例(我认为......)
有一个Puz类包含输入难题作为(81)数字列表; 1到9,其中单元格的值是已知的,0表示不是。
Puz类还包含一个拼图的工作版本,除了这里列表中的每个(81)项是一个集合;其中一个单元格的答案是已知的,该集合包含一个从1到9的值,例如set([4]),并且在答案未知的情况下,该集合包含剩余的可能性,例如set([3,5 ,7,9])。 当Puz._init __(self,puz)被调用时,工作列表中的那些“可能”集被设置为([1,2,3,4,5,6,7,8,9]),并且找到解决方案的第一步是在单元格的行,列和3x3块中删除显示为答案的所有值。
最初,使用for循环填充工作列表:对于0到80,如果它是答案,则将答案作为集合放入,否则放入集合(范围(1,10))。我无法弄清楚如何将这种条件转化为列表理解,因此我将其分解为一个单独的“填充函数”,其中3个版本如下所示。该fill_funcs在他们的“不的回答分支”有所不同:
return set(range(1,(self.dim+1)))
return set(self.r_dim_1_based)
return self.set_dim_1_based
正如你看到的,处理的越来越多的功能外搬回到小变量初始化。
问题是,前两个变体滑入Sudoku求解器中,并按原始代码的方式工作。但是---第三种变化中断了,说工作列表中的第六个集合是(或变成)空的。 YET ---由这三种不同的制作组名单评估作为平等:
p.W1 == == p.W2 p.W3 - >真
我难倒。
下面是制作的集列出了一些代码:
#!/usr/bin/env python
import copy
from math import sqrt
'''
Puzzle #15, from The Guardian: 050624: #41: rated difficult
'''
puz = [
0,0,1, 9,0,0, 3,0,0,
0,0,0, 0,0,0, 2,0,0,
7,6,0, 0,2,0, 0,0,9,
3,0,0, 0,6,0, 0,0,5,
0,0,2, 1,0,3, 4,0,0,
4,0,0, 0,9,0, 0,0,3,
1,0,0, 0,3,0, 0,9,7,
0,0,4, 0,0,0, 0,0,0,
0,0,5, 0,0,8, 6,0,0
]
class GroupInfo: pass
class Puz(GroupInfo):
def __init__(self, puz):
self.A = copy.deepcopy(puz)
self.ncells = len(self.A)
self.r_ncells = range(0,self.ncells)
self.dim = int(sqrt(self.ncells))
assert (self.dim ** 2) == self.ncells, "puz is not square"
self.r_dim_0_based = range(0,self.dim)
self.r_dim_1_based = range(1, self.dim + 1)
self.set_dim_1_based = set(self.r_dim_1_based) ## <<---- causes to fail!
##### with 'empty set at W[5]' !?!?!?
def W1_fill_func(val):
if (val == 0):
return set(range(1,(self.dim+1)))
else:
return set([val])
self.W1 = [ W1_fill_func(self.A[cid])
for cid in self.r_ncells ]
def W2_fill_func(val):
if (val == 0):
return set(self.r_dim_1_based)
else:
return set([val])
self.W2 = [ W2_fill_func(self.A[cid])
for cid in self.r_ncells ]
def W3_fill_func(val):
if (val == 0):
return self.set_dim_1_based
else:
return set([val])
self.W3 = [ W3_fill_func(self.A[cid])
for cid in self.r_ncells ]
return
#def Puz.__init__()
#class Puz
p = Puz(puz)
print p.W1 == p.W2 == p.W3
这很快,亚历克斯!我还在编辑标题! 因此,尝试从“返回”行中消除所有处理的方式毫无意义;无论如何,我将不得不打电话给set()。但是,一组集合仍然是一个集合,而不是某种“嵌套集合”。 Raffiniert,sehr raffiniert。我不认为我会在一段漫长的时间里解释这个解释。 – behindthefall 2009-11-02 01:44:37
也似乎是绝对愚蠢的运气,这个'对任何对象的引用的变化改变对象'(当然,当我这样写出来,我认识到,但是当它被埋在一个初始化中,我没有看到这种情况)还没有起来,并且在我之前咬过我。就像在那个数独解算器的其他地方一样。 – behindthefall 2009-11-02 01:54:25
对,'set(someset)'只是一个浅拷贝(就像'someset.copy()'一样,但我更喜欢用统一的和好的习惯用法来“调用类型来制作一个(浅)复制”的习语。 - )。无论如何,总是乐于帮忙! – 2009-11-02 02:09:42