按照两个规则进行
#1 如果某个格X只能填入i,则X=i
#2 如果某个数字i只能填入格X,则X=i
后来发现只要#2就能够求出解了。
代码如下,接受一个包含81个数字的字符串,对应数独的81格,未知的格用0表示。
如果没有参数则自动生成一个测试用例。
#1 如果某个格X只能填入i,则X=i
#2 如果某个数字i只能填入格X,则X=i
后来发现只要#2就能够求出解了。
代码如下,接受一个包含81个数字的字符串,对应数独的81格,未知的格用0表示。
如果没有参数则自动生成一个测试用例。
- import sys
- import os
- import random
- from array import array
- testcase = "164973528257816943389452167471235896538649271692781435716524389845397612923168754"
- keeprate = float(35)
- def init_groups():
- groups = [[] for i in range(27)]
- for i in range(81):
- x = i % 9
- y = i / 9
- groups[y].append(i)
- groups[9 + x].append(i)
- groups[18 + x / 3 + y - y % 3].append(i)
- return tuple(tuple(l) for l in groups)
- def set_table(table, groups):
- for group in groups:
- num = set(table[i] for i in group if type(table[i]) == int)
- for s in group:
- if type(table[s]) == set:
- table[s] -= num
- def count_table(table):
- return len([item for item in table if type(item) == int])
- def print_table(table):
- str_tab = ["" for i in range(9)]
- for y in range(9):
- for x in range(9):
- if x != 0 and x % 3 == 0:
- str_tab[y] += " "
- if type(table[x + y * 9]) == int:
- str_tab[y] += "%d " % table[x + y * 9]
- else:
- str_tab[y] += "%d'" % len(table[x + y * 9])
- str_tab.insert(6, "")
- str_tab.insert(3, "")
- print "counter = %d" % count_table(table)
- print "/n".join(str_tab)
- print "-------------------"
- def set_value(table, groups, index, value):
- table[index] = value
- tmp = tuple(group for group in groups if index in group)
- group = set()
- for g in tmp:
- group |= set(g)
- for item in group:
- if type(item) == set:
- item.discard(value)
- def sudoku(table):
- for i in range(81):
- if type(table[i]) == int and table[i] == 0:
- table[i] = set(range(1,10))
- groups = init_groups()
- set_table(table, groups)
- count = 0
- stack = []
- print_table(table)
- while True:
- if count_table(table) == 81:
- break
- flag = True
- # tmp = sorted(table, key = lambda x : 10 if type(x) == int else len(x))
- # for i in tmp:
- # if type(i) != set or len(i) != 1:
- # break
- # if len(i) == 0:
- # table = stack.pop()
- # print "pop stack"
- # table[table.index(i)] = i.pop()
- # set_table(table, groups)
- # flag = False
- # #set_value(table, groups, table.index(i), i.pop())
- for group in groups:
- num = set()
- total = set()
- for s in group:
- if type(table[s]) == set:
- num ^= table[s] - total
- total |= table[s] - num
- for s in group:
- if type(table[s]) == set:
- temp = num & table[s]
- if len(temp) == 0:
- continue
- if len(temp) == 1:
- table[s] = temp.pop()
- set_table(table, groups)
- flag = False
- else:
- table = stack.pop()
- if flag:
- tmp = sorted(table, key = lambda x : 10 if type(x) == int else len(x))
- if len(tmp[0]) == 0:
- continue
- v = tmp[0].pop()
- newtable = table[:]
- for i in range(len(newtable)):
- if type(newtable[i]) == set:
- newtable[i] = newtable[i].copy()
- stack.append(newtable)
- table[table.index(tmp[0])] = v
- set_table(table, groups)
- print_table(table)
- if __name__ == "__main__":
- if len(sys.argv) > 1:
- if len(sys.argv[1]) == 81:
- init = array("c", sys.argv[1])
- else:
- print "Argument error!"
- sys.exit(-1)
- else:
- init = array("c", testcase)
- if init.tostring() == testcase:
- for i in range(len(init)):
- if random.random() >= keeprate / 100:
- init[i] = "0"
- table = [int(s) for s in init]
- #set_table()
- #print_table(table)
- sudoku(table)