组内出题:
判定一个数独是否有效,正确。
该数独只填充了部分数字,其中缺少的数字用 .表示。
一个合法的数独是否有效(部分填充)并不一定是可解的.仅需要使填充的空格有效即可.
备注:
数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
仅限python.
我的代码:
import time
def make_dic_key(A, B): #生成['A1', 'A2', 'A3',... 'I1', 'I2', 'I3',]字典key列表
return [a+b for a in A for b in B]
def nine_list(cols, rows):
list_cols = [make_dic_key(rows, c) for c in cols] # 生成列字典key
list_rows = [make_dic_key(r, cols) for r in rows] # 生成行字典key
list_nine_squares = [make_dic_key(r, c) for r in ('ABC', 'DEF', 'GHI') for c in('123', '456', '789')] #生成九宫格字典key
return list_cols + list_rows + list_nine_squares
cols = '123456789'
rows = 'ABCDEFGHI'
squares_no = make_dic_key(rows, cols) # 编号:['A1', 'A2',... 'A9', ... , 'I8', 'I9']
nine_units = nine_list(cols,rows) # 所有单元列表(9行,9列,9宫格)
cor_unit = dict((s, [u for u in nine_units if s in u]) for s in squares_no) # cor_unit表示 某个元素编号相关的3个单元列表
# 表示某个元素编号:与之相关的20个元素编号
cor_no = dict((s, set(sum(cor_unit[s], []))-set([s])) for s in squares_no)
def dowork_data(data): # 处理数据
values = dict((s, cols) for s in squares_no) #{'A1': '123456789', 'A2': '123456789',....}
dict_data = dict(zip(squares_no, data)) # {'A1': '4', 'A2': '.', ... , 'I8': '.', 'I9': '.'}
for key, value in dict_data.items():
#print(key, value)
#print('aaaaaaaaaa')
if value in cols and not replace_ele(values, key, value):
return False
return values
def replace_ele(values, key, value): # values[key]删除除了value以外的值
other_values = values[key].replace(value, '') #把values中value删除
#print('&&&')
#print(other_values)
#print('&&&')
if all(delete_num(values, key, num) for num in other_values):
return values
else:
return False
def delete_num(values, key, num): # values[key]中删除值num
if num not in values[key]:
return values
values[key] = values[key].replace(num, '')
# 如果一个位置只有一个可能值,这个值从对应的相关位置的可能值中去除
if len(values[key]) == 0:
return False
elif len(values[key]) == 1:
only_value = values[key]
# 相关的20个元素中删除only_value
if not all(delete_num(values, s, only_value) for s in cor_no[key]):
return False
# 如果一个unit只有一个可能位置来放某个值,把值放那
for ele_list in cor_unit[key]:
dplaces = [s for s in ele_list if num in values[s]] # 找到可能存放的位置
if len(dplaces) == 0:
return False
elif len(dplaces) == 1:
only_key = dplaces[0]
if not replace_ele(values, only_key, num):
return False
return values
def search_data(values): #递归循环
if values is False:
return False
if all(len(values[s]) == 1 for s in squares_no):
return values
n, key = min((len(values[key]), key) for key in squares_no if len(values[key]) > 1)
resultlist=[]
for num in values[key]: # 用可能取值最小的优先遍历
resultlist.append(search_data(replace_ele(values.copy(), key, num)))
return find_result(resultlist)
def find_result(values):
for result in values:
if result:
return result
return False
def show_data(data):
if not data:
print('此数独无解')
return
temp = []
for key, value in data.items():
temp.append(value)
j = 0
for i in range(0,9):
print(temp[j:j+9])
j = j+9
return
if __name__ == '__main__':
data1 = [5, 3, 0, 0, 7, 0, 0, 0, 0,
6, 0, 0, 1, 9, 5, 0, 0, 0,
0, 9, 8, 0, 0, 0, 0, 6, 0,
8, 0, 0, 0, 6, 0, 0, 0, 3,
4, 0, 0, 8, 0, 3, 0, 0, 1,
7, 0, 0, 0, 2, 0, 0, 0, 6,
0, 6, 0, 0, 0, 0, 2, 8, 0,
0, 0, 0, 4, 1, 9, 0, 0, 5,
0, 0, 0, 0, 8, 0, 0, 7, 9]
data2 = (str(s) for s in data1)
start = time.clock()
values = dict((s, cols) for s in squares_no)
result = search_data(dowork_data(data2))
end = time.clock()
show_data(result)
print("时间: %f" % (end - start))
运行结果:
['5', '3', '4', '6', '7', '8', '9', '1', '2']
['6', '7', '2', '1', '9', '5', '3', '4', '8']
['1', '9', '8', '3', '4', '2', '5', '6', '7']
['8', '5', '9', '7', '6', '1', '4', '2', '3']
['4', '2', '6', '8', '5', '3', '7', '9', '1']
['7', '1', '3', '9', '2', '4', '8', '5', '6']
['9', '6', '1', '5', '3', '7', '2', '8', '4']
['2', '8', '7', '4', '1', '9', '6', '3', '5']
['3', '4', '5', '2', '8', '6', '1', '7', '9']
时间: 0.003033