把数独写成如下形式,保存成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