Hi,

I am reading a python program now but I just cannot understand how the

values of class attributes are assigned and changed. Here is the original

code url:

http://agolb.blogspot.com/2006/01/su...in-python.html
Here I am concerned is how attribute matrix.rows is changed. Through pdb

debugging, I can see in line 97, once "self.solutions = set((val,))" is

executed, cell.row and matrix.rows will be updated. But I did not see any

assignment codes here. How could this change happen then? Thanks a lot!

John

#

http://agolb.blogspot.com/2006/01/su...in-python.html
#!/usr/bin/env python

#

# sudoku-solver version 3

#

# Some ideas ripped-off from:

#

http://www.linuxjournal.com/article/8729
#

http://aspn.activestate.com/ASPN/Coo.../Recipe/440542
# Pavol solver in

#

http://groups.google.com/group/comp....87890f4c5e770d
#

# Copyright 2005 Ago,

# But you are free to copy, reuse, modify and distribute the code as you see

fit

from copy import deepcopy

class DeadEnd(Exception): pass

class Matrix:

def __init__(self, input):

self.rows = [[] for i in range(9)]

self.cols = [[] for i in range(9)]

self.submatrices = [[] for i in range(9)]

self.cells = [Cell(i,self) for i in range(81)]

self.subdiagonals = [self.rows[i][j+i%3] for i in range(9) for j in

[0,3,6]]

input = [s not in '-*' and int(s) or 0 for s in input if s in

'0123456789-*']

for cell,val in zip(self.cells, input):

if val: cell.setSolution(val)

def solve(self): #Brute-force solver

self.solveByReduction()

lensols=[(len(c.solutions),c.index) for c in self.cells if not

c.solved]

if not lensols: return True

unsolved = min(lensols)[1]

solutions = list(self.cells[unsolved].solutions)

for s in solutions:

tmpmatrix = deepcopy(self)

try:

tmpmatrix.cells[unsolved].setSolution(s)

if tmpmatrix.solve():

self.update(tmpmatrix)

return True

except DeadEnd: pass

def solveByReduction(self):

while True:

self.changed = False

for c in self.cells: c.solve()

for c in self.subdiagonals: c.skim()

if not self.changed: break

def update(self, m):

self.rows, self.cols, self.submatrices, self.cells,

self.subdiagonals=\

m.rows, m.cols, m.submatrices, m.cells, m.subdiagonals

def __str__(self):

return "\n".join(str([c for c in row ])[1:-1] for row in self.rows)

class Cell:

def __init__(self, index, matrix):

self.solved = False

self.matrix = matrix

self.index = index

self.row = matrix.rows[index/9]

self.col = matrix.cols[index%9]

self.submatrix = matrix.submatrices[((index/9)/3)*3+(index%9)/3]

self.row.append(self)

self.col.append(self)

self.submatrix.append(self)

self.solutions = set(range(1,10))

def solve(self):

if self.solved: return

if len(self.solutions) == 1:

self.setSolution(self.solutions.pop())

else:

sol = set()

for cells in [self.row, self.col, self.submatrix]:

otherSolutions = self.cells2sols(cells, self)

sol |= (self.solutions - otherSolutions)

if len(sol) 1: raise DeadEnd()

if sol: self.setSolution(sol.pop())

def skim(self):

submatrix = set(self.submatrix)

for r in (set(self.row), set(self.col)):

subset1 = submatrix - r

subset2 = r - submatrix

solsNotIn1 = set(range(1,10)) - self.cells2sols(subset2)

solsNotIn2 = set(range(1,10)) - self.cells2sols(subset1)

for c in subset1: c.delSolutions(solsNotIn1)

for c in subset2: c.delSolutions(solsNotIn2)

def setSolution(self, val):

self.solved = True

self.solutions = set((val,))

self.matrix.changed = True

for other in self.row+self.col+self.submatrix:

if other is self: continue

if other.solutions == self.solutions: raise DeadEnd()

other.delSolutions(self.solutions)

def delSolutions(self, val):

if not self.solved and val & self.solutions:

self.solutions -= val

self.matrix.changed = True

if not self.solutions: raise DeadEnd()

def __repr__(self):

return str(self.solved and list(self.solutions)[0] or

list(self.solutions))

@staticmethod

def cells2sols(cells, exclude=None):

return set(s for c in cells for s in c.solutions if c is not

exclude)

if __name__ == "__main__":

input ='''

1,0,0,0,0,0,0,0,2

0,9,0,4,0,0,0,5,0

0,0,6,0,0,0,7,0,0

0,5,0,9,0,3,0,0,0

0,0,0,0,7,0,0,0,0

0,0,0,8,5,0,0,4,0

7,0,0,0,0,0,6,0,0

0,3,0,0,0,9,0,8,0

0,0,2,0,0,0,0,0,1

'''

matrix = Matrix(input)

matrix.solve()

print matrix