日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

如何用python计算数独_用python解决数独

發(fā)布時(shí)間:2023/12/10 python 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何用python计算数独_用python解决数独 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

看到了,季以安:用Python解數(shù)獨(dú)[0],寫得很詳細(xì),我沒(méi)有全部看完,借用他的思路,我也來(lái)試試,回頭再去看他怎么弄,特別是遞歸的實(shí)現(xiàn)方式。

先上思路:

'''1.解9*9數(shù)獨(dú)的思路:(1)一個(gè)單元格的推理:根據(jù)行、列、小矩陣得出該單元格有可能填入的數(shù)值的三個(gè)列表;求并集,縮小范圍,簡(jiǎn)單的題目好多單元格都能得到唯一值。(2)重復(fù)上面這個(gè)過(guò)程2.實(shí)現(xiàn):(1)復(fù)制生成三個(gè)新數(shù)獨(dú)(按行、按列、按小矩陣)(2)把上述三個(gè)數(shù)獨(dú)每個(gè)空單元格內(nèi)填滿’有可能‘的數(shù)值(用列表填入)(3)遍歷每個(gè)空單元格,去找這個(gè)單元格分別是三個(gè)新數(shù)獨(dú)的哪個(gè)位置(是三個(gè)列表-求交集)(4)更新原數(shù)獨(dú),遞歸更新后的數(shù)獨(dú)(5)我也知道這個(gè)程序思路,只能做比較簡(jiǎn)單的數(shù)獨(dú),就是練練,寫得好會(huì)考慮怎么解高等級(jí)數(shù)獨(dú)。'''圖一:數(shù)獨(dú)就是一個(gè)二維列表,用過(guò)xlwings操作過(guò)excel的很好理解 以下考慮算法的時(shí)候就看著這張圖就行了

思路確定后,來(lái)定一下程序大致的框架:

soduku1 #待求解的數(shù)獨(dú)

soduku2 #復(fù)制soduku1,然后遍歷空單元格,按行來(lái)確定該單元格可能填入哪些值(一個(gè)列表),

全算出來(lái)后就是一個(gè)新數(shù)獨(dú)(思路不斷在二維列表和圖一之間切換)

soduku3 #和上面一樣,按列,基本相同,

soduku4 #按小矩陣,實(shí)現(xiàn)需要計(jì)算思考

A:def 復(fù)制待解數(shù)獨(dú)(soduku1):

# 1.因?yàn)閟oduku1是有用的,不要去修改,所以復(fù)制

# 2.soduku2,soduku3的結(jié)構(gòu)是一樣的,所有寫在一起

# 3.按行生成soduku2很簡(jiǎn)單,就是單純的復(fù)制soduku1,只不過(guò)因?yàn)槭嵌S列表,

要用copy.deepcopy(soduku1)才有用,不能soduku2=soduku1[:],更不能

soduku2=soduku1這么粗暴

# 4.按列生成soduku3,復(fù)雜一點(diǎn),這里是框架,先不說(shuō)

return newsodu

B:def 按待解數(shù)獨(dú)生成小矩陣數(shù)獨(dú)(soduku1):

#這個(gè)需要一點(diǎn)觀察,還需要一點(diǎn)小學(xué)水平算法

return newsodu

C:def 把新生成的三個(gè)數(shù)組空格全填滿(sodu):

#看圖方式:cells(0,0)(看圖一,這個(gè)表示第0行,第0列,即第一個(gè)

單元格,后面都采取這樣的方式看圖)

# soduku2的cells(0,0)會(huì)被填入[2,4,5,6],表示按行第一個(gè)單元格可能是2,4,5,6

# 全填滿無(wú)非是循環(huán)

# 分別傳入?yún)?shù)soduku2,soduku3,soduku4,就會(huì)得到三個(gè)填滿的新數(shù)獨(dú)

return 填滿的三個(gè)新數(shù)獨(dú)

def 重復(fù)算():

調(diào)用C:分別傳入soduku2,soduku3,soduku4

爛尾了,本來(lái)想一步步寫思路,沒(méi)耐心寫了,好像也不太有人看,看別人代碼有時(shí)是很難受的,直接上代碼,基本思路注釋里還是有的。

'''1.解9*9數(shù)獨(dú)的思路:(1)一個(gè)單元格的推理:根據(jù)行、列、小矩陣得出該單元格有可能填入的數(shù)值的三個(gè)列表;求并集,縮小范圍,簡(jiǎn)單的題目好多單元格都能得到唯一值。(2)重復(fù)上面這個(gè)過(guò)程2.實(shí)現(xiàn):(1)復(fù)制生成三個(gè)新數(shù)獨(dú)(按行、按列、按小矩陣)(2)把上述三個(gè)數(shù)獨(dú)每個(gè)空單元格內(nèi)填滿’有可能‘的數(shù)值(用列表填入)(3)遍歷每個(gè)空單元格,去找這個(gè)單元格分別是三個(gè)新數(shù)獨(dú)的哪個(gè)位置(是三個(gè)列表-求交集),簡(jiǎn)單的題目這一步就能得到一個(gè)唯一值(4)更新原數(shù)獨(dú),遞歸更新后的數(shù)獨(dú)(5)我也知道這個(gè)程序思路,只能做比較簡(jiǎn)單的數(shù)獨(dú),就是練練,寫得好會(huì)考慮怎么解高等級(jí)數(shù)獨(dú)。'''

import copy

import numpy as np

import xlwings as xw

soduku = [[] for i in range(9)]

soduku[0] = ['',8,9,1,'',3,'','','']

soduku[1] = ['',2,7,4,'','',8,'','']

soduku[2] = ['','','',5,2,'','','','']

soduku[3] = ['',7,6,9,'','',5,'',8]

soduku[4] = [8,'',3,6,'',1,2,'','']

soduku[5] = ['',4,5,3,8,7,1,6,'']

soduku[6] = [7,'',8,2,1,4,3,9,5]

soduku[7] = [9,3,1,7,6,5,4,'',2]

soduku[8] = [4,'',2,'','',9,'','',6]

#復(fù)制待解數(shù)組

#按行直接復(fù)制

#按列用要用zip合并轉(zhuǎn)換

def tran_sodu(sodu,col=None):

if col==None:

return copy.deepcopy(soduku)

else:

new_sodu=list(zip(*copy.deepcopy(soduku)))

new_sodu=[list(i) for i in new_sodu]

return new_sodu

#填滿空單元格,并為了格式統(tǒng)一好處理,把已知的值,由數(shù)值轉(zhuǎn)為列表

def input_none(sodu):

for row in sodu:

row_none = [i for i in range(1,10) if i not in row]

for x in range(len(row)):

if row[x]=="":

row[x]=row_none

else:

row[x]=[row[x]]

return sodu

'''1.按小矩陣復(fù)制待解數(shù)組,9個(gè)小矩陣組成新數(shù)獨(dú)2.用了numpy知識(shí),很好用,但在單個(gè)元素的數(shù)據(jù)類型上有很多坑3.思路:把待解數(shù)組reshape成27組,每組3個(gè)元素的矩陣A,那么第一個(gè)小矩陣就取矩陣A的第1、4、7個(gè)元素,依次類推'''

def jvzheng(soduku):

arr = np.array(soduku)

# arr=[list(i) for i in arr.reshape(27,3)]

arr = arr.reshape(27,3).tolist()

for a in arr:

for b in range(3):

if a[b]!="":

a[b]=int(a[b])

newSodu=[[] for i in range(9)]

j=0

for i in range(9):

newSodu[i]=arr[j]+arr[j+3]+arr[j+6]

j=j+1

if j>=3 and j%3==0:

j=j+6

return newSodu

'''1、開始解數(shù)獨(dú)后,遍歷每個(gè)空單元格,去找該單元格對(duì)應(yīng)到三個(gè)新數(shù)獨(dú)的單元格時(shí):(1)如果待解數(shù)獨(dú)的單元格是soduku-cells(j,k),那么對(duì)應(yīng)過(guò)去,按行的當(dāng)然也是:按行-cells(j,k),按列的也很簡(jiǎn)單,相反,是:按列-cells(k,j)(2)按小矩陣的難解一點(diǎn),就是下面的函數(shù),和jvzheng()的主要代碼一樣,就是再轉(zhuǎn)置一次,就轉(zhuǎn)回去了,效果是:按小矩陣-cells(j,k)(3)按行-cells(j,k),按列-cells(k,j),按小矩陣-cells(j,k)這三個(gè)列表就能求交集了,最希望得到的是一個(gè)唯一值'''

def jvzheng2(soduku):

arr = np.array(soduku)

# arr=[list(i) for i in arr.reshape(27,3)]

arr=arr.reshape(27,3).tolist()

newSodu=[[] for i in range(9)]

j=0

for i in range(9):

newSodu[i]=arr[j]+arr[j+3]+arr[j+6]

j=j+1

if j>=3 and j%3==0:

j=j+6

return newSodu

import sys

sys.setrecursionlimit(50000) #這里設(shè)置大一些

'''1.遞歸函數(shù),重復(fù)2.基本原理在jvzheng2()上面寫了'''

def fin(s):

global cc,rr,jz,jz2

rr=input_none(tran_sodu(soduku)) # 按行填滿各空格有可能的缺失值

cc=input_none(tran_sodu(soduku,1)) #按列

jz=input_none(jvzheng(soduku)) #按小矩陣

jz2=jvzheng2(jz)

'''規(guī)則一:行、列、小矩陣求交集遍歷待解數(shù)獨(dú)的每個(gè)空單元格,找到該單元格在rr,cc,jz2中的位置,并求交集當(dāng)這個(gè)交集只有一個(gè)值時(shí),就填入待解數(shù)獨(dú)中'''

for j in range(9):

for k in range(9):

if s[j][k]=="":

'''下面的判斷是numpy數(shù)據(jù)類型的一個(gè)坑,numpy會(huì)將[9]這樣的單個(gè)數(shù)值的列表直接處理成數(shù)字9,這在算到最后一步時(shí),代碼就會(huì)跳錯(cuò)識(shí)了,因此加了判斷,核心代碼是else下面的那名就夠了。'''

if isinstance(jz2[j][k],int):

target=set(rr[j][k])&set(cc[k][j])

else:

target=set(rr[j][k])&set(cc[k][j])&set(jz2[j][k])

if len(target)==1:

s[j][k]=list(target)[0]

'''規(guī)則二:如[8,4,[3,7,9],6,[1,5],[1,3,5],[1,5,9],[1,3,9],2]第三個(gè)[3,7,9],雖然有三個(gè)可能值,但觀察一行,‘7’,在其他位置都沒(méi)有出現(xiàn)過(guò),因此第三位置肯定是‘7’'''

'''規(guī)則三……規(guī)則越多,能解的難題越多,達(dá)到通用,就不會(huì)出現(xiàn)“遞歸深度不夠”,”棧溢出“等問(wèn)題,數(shù)獨(dú)知識(shí)有限,寫不下去了,只能解簡(jiǎn)單數(shù)獨(dú)。'''

#每遞歸一次,待解數(shù)獨(dú)就會(huì)更新

#把待解數(shù)獨(dú)攤開,如果沒(méi)有一個(gè)空值,那說(shuō)明解完了

if "" not in np.array(s).reshape(1,81)[0].tolist():

# if "" not in s[3]:

return s

else:

fin(s)

return s

def main():

fin(soduku)

print(soduku)

xw.Range("K1").value = soduku

if __name__ == '__main__':

main()

解出來(lái)了,因?yàn)槔訉?shí)在太簡(jiǎn)單了,稍微復(fù)雜一點(diǎn)就出現(xiàn)“棧溢出”了。

因?yàn)橐?guī)則只有一條,無(wú)論怎么遞歸都得不到答案。

總結(jié)

以上是生活随笔為你收集整理的如何用python计算数独_用python解决数独的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。