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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

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

發布時間:2023/12/10 python 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何用python计算数独_用python解决数独 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

看到了,季以安:用Python解數獨[0],寫得很詳細,我沒有全部看完,借用他的思路,我也來試試,回頭再去看他怎么弄,特別是遞歸的實現方式。

先上思路:

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

思路確定后,來定一下程序大致的框架:

soduku1 #待求解的數獨

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

全算出來后就是一個新數獨(思路不斷在二維列表和圖一之間切換)

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

soduku4 #按小矩陣,實現需要計算思考

A:def 復制待解數獨(soduku1):

# 1.因為soduku1是有用的,不要去修改,所以復制

# 2.soduku2,soduku3的結構是一樣的,所有寫在一起

# 3.按行生成soduku2很簡單,就是單純的復制soduku1,只不過因為是二維列表,

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

soduku2=soduku1這么粗暴

# 4.按列生成soduku3,復雜一點,這里是框架,先不說

return newsodu

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

#這個需要一點觀察,還需要一點小學水平算法

return newsodu

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

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

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

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

# 全填滿無非是循環

# 分別傳入參數soduku2,soduku3,soduku4,就會得到三個填滿的新數獨

return 填滿的三個新數獨

def 重復算():

調用C:分別傳入soduku2,soduku3,soduku4

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

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

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]

#復制待解數組

#按行直接復制

#按列用要用zip合并轉換

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

#填滿空單元格,并為了格式統一好處理,把已知的值,由數值轉為列表

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.按小矩陣復制待解數組,9個小矩陣組成新數獨2.用了numpy知識,很好用,但在單個元素的數據類型上有很多坑3.思路:把待解數組reshape成27組,每組3個元素的矩陣A,那么第一個小矩陣就取矩陣A的第1、4、7個元素,依次類推'''

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、開始解數獨后,遍歷每個空單元格,去找該單元格對應到三個新數獨的單元格時:(1)如果待解數獨的單元格是soduku-cells(j,k),那么對應過去,按行的當然也是:按行-cells(j,k),按列的也很簡單,相反,是:按列-cells(k,j)(2)按小矩陣的難解一點,就是下面的函數,和jvzheng()的主要代碼一樣,就是再轉置一次,就轉回去了,效果是:按小矩陣-cells(j,k)(3)按行-cells(j,k),按列-cells(k,j),按小矩陣-cells(j,k)這三個列表就能求交集了,最希望得到的是一個唯一值'''

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) #這里設置大一些

'''1.遞歸函數,重復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)

'''規則一:行、列、小矩陣求交集遍歷待解數獨的每個空單元格,找到該單元格在rr,cc,jz2中的位置,并求交集當這個交集只有一個值時,就填入待解數獨中'''

for j in range(9):

for k in range(9):

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

'''下面的判斷是numpy數據類型的一個坑,numpy會將[9]這樣的單個數值的列表直接處理成數字9,這在算到最后一步時,代碼就會跳錯識了,因此加了判斷,核心代碼是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]

'''規則二:如[8,4,[3,7,9],6,[1,5],[1,3,5],[1,5,9],[1,3,9],2]第三個[3,7,9],雖然有三個可能值,但觀察一行,‘7’,在其他位置都沒有出現過,因此第三位置肯定是‘7’'''

'''規則三……規則越多,能解的難題越多,達到通用,就不會出現“遞歸深度不夠”,”棧溢出“等問題,數獨知識有限,寫不下去了,只能解簡單數獨。'''

#每遞歸一次,待解數獨就會更新

#把待解數獨攤開,如果沒有一個空值,那說明解完了

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()

解出來了,因為例子實在太簡單了,稍微復雜一點就出現“棧溢出”了。

因為規則只有一條,無論怎么遞歸都得不到答案。

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。