把数独写成如下形式,保存成s.txt,放在同目录下
010000087
005074000
000006040
009063050
000400200
640050300
030005071
000900400
507100003
以下是代码部分
---------------------------------------------------------------------------------------------------------------------------------
# sudoku auto solver by RomanGoliard
import copy
#---------------------------------------------------------------------------------------------------------------------------------
full_set = set([1,2,3,4,5,6,7,8,9])
threshold = 3
SUCCESS = 1
REDUCED = 2
NOT_REDUCED = 3
ERROR = 4
#---------------------------------------------------------------------------------------------------------------------------------
# Read sudoku from the file
def get( L ):
f = open("s.txt", 'r')
s = f.read(1)
while s != '':
L.append( int(s) )
s = f.read(1)
if s == '\n':
s = f.read(1)
# get the brick's row from the num of brick
def get_row ( num ):
return num / 9
# get the brick's col from the num of brick
def get_col ( num ):
return num % 9
# get the brick's block from the num of brick
# blocks are defined as follow:
# 0 1 2
# 3 4 5
# 6 7 8
def get_block ( num ):
return get_row(num) / 3 * 3 + get_col(num) / 3
#---------------------------------------------------------------------------------------------------------------------------------
# print the sudoku
def output_sudoku( L ):
for i in range(0, 9):
for j in range(0, 9):
print L[i*9 + j],
print
print
def print_set( col, row, block, sudoku, brick ):
for i in range(9):
if len( col[i] ) < threshold and len( col[i] ) > 0:
print "col:", i, col[i]
if len( row[i] ) < threshold and len( row[i] ) > 0:
print "row:", i, row[i]
if len( block[i] ) < threshold and len( block[i] ) > 0:
print "block:", i, block[i]
for i in range(81):
if sudoku[i] == 0:
if len( brick[i]) < threshold:
print i, brick[i]
#---------------------------------------------------------------------------------------------------------------------------------
def clean_list( col, row, block ):
if len( col ) != 0:
del col[0 : len(col)]
if len( row ) != 0:
del row[0 : len(row)]
if len( block ) != 0:
del block[0 : len(block)]
def reset_all( col, row, block ):
clean_list( col, row, block )
for i in range(9):
col.append( set([]) )
row.append( set([]) )
block.append( set([]) )
# search and inverse the set
def inverse_set( col, row, block, sudoku ):
for i in range(81):
if sudoku[i] != 0:
col[ get_col(i) ].add( sudoku[i] )
row[ get_row(i) ].add( sudoku[i] )
block[ get_block(i) ].add( sudoku[i] )
for i in range(9):
col[i] = full_set - col[i]
row[i] = full_set - row[i]
block[i] = full_set - block[i]
# search the bricks and find those who has only one element
def uni( col, row, block, sudoku ):
for i in range(81):
if sudoku[i] == 0:
temp = col[ get_col(i) ] & row[ get_row(i) ] & block[ get_block(i) ]
if len( temp ) == 1:
sudoku[i] = temp.pop()
col[ get_col(i) ].remove(sudoku[i])
row[ get_row(i) ].remove(sudoku[i])
block[ get_block(i) ].remove(sudoku[i])
# print i, sudoku[i]
# run and solve the sudoko
def search_sudoku( col, row, block, sudoku, brick ):
reset_all( col, row, block )
inverse_set( col, row, block, sudoku )
uni( col, row, block, sudoku )
#---------------------------------------------------------------------------------------------------------------------------------
def check_set( col, row, block, sudoku, brick ):
flag = SUCCESS
for i in range(81):
if sudoku[i] == 0:
flag = NOT_REDUCED
if flag == SUCCESS:
return flag
for i in range(81):
if sudoku[i] == 0:
temp = col[get_col(i)] & row[get_row(i)] & block[get_block(i)]
if len( brick[i] ) > len( temp ):
brick[i] = temp
flag = REDUCED
if len( brick[i] ) == 0:
return ERROR
return flag
def loop_search( col, row, block, sudoku, brick ):
search_sudoku( col, row, block, sudoku, brick )
value = check_set( col, row, block, sudoku, brick )
while value == REDUCED:
search_sudoku( col, row, block, sudoku, brick )
value = check_set( col, row, block, sudoku, brick )
return value
#---------------------------------------------------------------------------------------------------------------------------------
# sandbox test
def sandbox( col, row, block, sudoku, brick ):
for i in range( 81 ):
for j in range( 81 ):
if sudoku[i] == 0 and sudoku[j] == 0:
if len( brick[i] ) > 0 and len( brick[j] ) > 0:
remain_i, remain_j = set([]), set([])
for e in brick[i]:
for f in brick[j]:
sudoku[i], sudoku[j] = e, f
value = loop_search( copy.deepcopy( col ), copy.deepcopy( row ), copy.deepcopy( block ), copy.deepcopy( sudoku ), copy.deepcopy( brick ) )
sudoku[i], sudoku[j] = 0, 0
if value != ERROR:
remain_i.add( e )
remain_j.add( f )
if len ( remain_i ) < len( brick[i] ) and len( remain_i ) > 0:
brick[i] = remain_i
if len ( remain_j ) < len( brick[j] ) and len( remain_j ) > 0:
brick[j] = remain_j
if len( brick[i] ) == 1:
for e in brick[i]:
sudoku[i] = e
loop_search( col, row, block, sudoku, brick )
if len( brick[j] ) == 1:
for e in brick[j]:
sudoku[j] = e
loop_search( col, row, block, sudoku, brick )
# main -------------------------------------------------------------------------------------------
cols = []
rows = []
blocks = []
bricks = []
sudokus = []
get(sudokus)
for i in range(81):
bricks.append(full_set)
if loop_search( cols, rows, blocks, sudokus, bricks ) == SUCCESS:
print "Found solution!"
else:
sandbox( cols, rows, blocks, sudokus, bricks )
output_sudoku( sudokus )
# write back to file
# ......
# write back to file