这疫情期间,宅在家里,闲来无事,也不知道哪根筋搭错了,就去玩数独了,(这不是自找麻烦嘛......)。
结果还玩上瘾了(无语),玩出了一点道道,但是每次自己手动解题总要花费半个小时以上(骨灰级难度,嘻嘻嘻),每次推导错误撤回重来就感觉心肌梗塞了一般,动不动就搞得自己抓狂、抓狂、抓狂!(重要的事情说三遍!)
于是,我就想偷个懒,看看用Python解决数独问题,最后花了两天得出以下公式(Python菜鸡,码字贼慢,轻喷~),里边有说明,公式附上:
import time
import random
def con(a):#用于将数据转化为符合格式的序列
if len(a)==81:
a_con=[[],[],[],[],[],[],[],[],[]]
for i in range(9):
b=a[i*9:i*9+9]
for j in range(9):
a_con[i].append(int(b[j]))
return a_con
return False
def examine_sudoku(sudoku):#检查是否符合数独规则
if len(sudoku)!=9:
return False
for i in range(9):
if len(sudoku[i])!=9 or sudoku[i].count([])>0:
return False
for j in range(1,10):
if sudoku[i].count(j)>1:
return False
return True
def complete(a):#用于检测数独是否完成
for i in range(9):
for j in range(9):
if type(a[i][j])!=int or a[i][j]==0:
return False
return True
def copy(a):#复制数独的值,用于后期假设法运算失败,找回原来的值
d=[[], [], [], [], [], [], [], [], []]
for i in range(9):
for j in range(9):
if type(a[i][j])==int:
d[i].append(a[i][j])
elif type(a[i][j])==list:
d[i].append([])
for k in a[i][j]:
d[i][j].append(k)
return d
def extract_b_c(a):#用9行表示的a,得到9列表示的b,及9宫表示的c,并对每个0所在的位置用[1,2,3,4,5,6,7,8,9]代替,作为笔记
b=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]]
c=[[],[],[],[],[],[],[],[],[]]
for i in range(9):
for j in range(9):
if a[i][j]==0:
a[i][j] = [1,2,3,4,5,6,7,8,9]
b[j][i]=a[i][j]
s=ij_s(i,j)
c[s].append(a[i][j])
return b,c
def ij_s(i,j):#用i和j求得宫所在的位置s
s=i//3*3+j//3
return s
def ij_t(i,j):#用i和j求得所在宫里的位置t
t=i%3*3+j%3
return t
def st_i(s,t):#用s和t求得原i的值
i=s//3*3+t//3
return i
def st_j(s, t):#用s和t求得原j的值
j=s%3*3+t%3
return j
def pr(a):#用于输出方便阅读的结果
for i in range(9):
if i%3==0:
print('\t---------\t\t---------\t\t---------')
for j in range(9):
if j%3==0:
print('|',end='\t')
print(a[i][j],end='\t')
print('|',end='\n')
print('\t---------\t\t---------\t\t---------')
def diff(d):
print('数独难度:',end='')
if d==0:
print('极容易')
if d==1:
print('容易')
if d==2:
print('一般')
if d==3:
print('困难')
if d==4:
print('极困难')
def play_1(a,b,c,i,j,change):#将笔记中同行、同列及同宫的笔记里删除已知数字,并将唯一可能的格子变成已知数字
s=ij_s(i,j)
for num in range(1,10):
for k in range(9):
if type(a[i][k])==list and num in a[i] and num in a[i][k]:
a[i][k].remove(num)
change=True
if len(a[i][k])==1:
n=a[i][k][0]
a[i][k]=n
b[k][i]=n
c[ij_s(i,k)][ij_t(i,k)]=n
change=True
if type(b[j][k])==list and num in b[j] and num in b[j][k]:
b[j][k].remove(num)
change=True
if len(b[j][k])==1:
n=b[j][k][0]
a[k][j]=n
b[j][k]=n
c[ij_s(k,j)][ij_t(k,j)]=n
change=True
if type(c[s][k])==list and num in c[s] and num in c[s][k]:
c[s][k].remove(num)
change=True
if len(c[s][k])==1:
n=c[s][k][0]
a[st_i(s,k)][st_j(s,k)]=n
b[st_j(s,k)][st_i(s,k)]=n
c[s][k]=n
change=True
return a,b,c,change
def play_2(a,b,c,i,j,change):#唯一候选数法
def num_abc():
num_a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
num_b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
num_c = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for k in range(1,10):
if k in a[i]:
num_a.remove(k)
if k in b[j]:
num_b.remove(k)
if k in c[s]:
num_c.remove(k)
return num_a,num_b,num_c
s=ij_s(i,j)
num_a,num_b,num_c=num_abc()
for n in num_a:
t=0
for k in range(9):
if type(a[i][k])==list and n in a[i][k]:
t+=1
if t==1:
for k in range(9):
if type(a[i][k]) == list and n in a[i][k]:
a[i][k] = n
b[k][i] = n
c[ij_s(i, k)][ij_t(i, k)] = n
num_a, num_b, num_c = num_abc()
change=True
for n in num_b:
t=0
for k in range(9):
if type(b[j][k])==list and n in b[j][k]:
t+=1
if t==1:
for k in range(9):
if type(b[j][k])==list and n in b[j][k]:
a[k][j] = n
b[j][k] = n
c[ij_s(k, j)][ij_t(k, j)] = n
num_a, num_b, num_c = num_abc()
change=True
for n in num_c:
t=0
for k in range(9):
if type(c[s][k])==list and n in c[s][k]:
t+=1
if t==1:
for k in range(9):
if type(c[s][k])==list and n in c[s][k]:
a[st_i(s,k)][st_j(s,k)]=n
b[st_j(s,k)][st_i(s,k)]=n
c[s][k]=n
change=True
return a,b,c,change
def play_3(a,b,c,i,j,change):#链数删减法,专业用语是这样的,有2链数、3链数的,此方法扩展到n链数(帮助排除不可能项的)
list_a=[]
list_b=[]
list_c=[]
s=ij_s(i,j)
for k in range(9):
if type(a[i][k]) == list:
list_a.append(a[i][k])
for k in range(9):
if type(b[j][k]) == list:
list_b.append(b[j][k])
for k in range(9):
if type(c[s][k]) == list:
list_c.append(c[s][k])
for k in range(3,len(list_a)+1):
l=[]
n=0
for m in list_a:
if len(m)
发明以上数独的人还说这个是史上最难的数独,然而经过测试,我这个方法解出答案花费0.15秒,而且连续做10000次只花费56秒哦~~
我想这个方法应该是目前最快的方法没有之一了吧~