python破解数独_使用 Python 解 数独

本文介绍了如何使用Python解决数独问题。通过定义各种辅助函数,如取行、列、宫格的元素,以及判断和填充数独的方法,实现了一个递归的数独求解算法。示例代码展示了如何处理不同难度的数独题目。
摘要由CSDN通过智能技术生成

importthreading, time, sys, os, copyfrom multiprocessing importProcess, Pool"""# 每一宫分组

a[0-2][0-2] a[0-2][3-5] a[0-2][6-8]

a[3-5][0-2] a[3-5][3-5] a[3-5][6-8]

a[6-8][0-2] a[6-8][3-5] a[6-8][6-8]

# 每一列分组

a[0-8][0] a[0-8][1] a[0-8][2] a[0-8][3] a[0-8][4] a[0-8][5] a[0-8][6] a[0-8][7] a[0-8][08]

# 每一行分组

a[0][0-9]

a[1][0-9]

a[2][0-9]

a[3][0-9]

a[4][0-9]

a[5][0-9]

a[6][0-9]

a[7][0-9]

a[8][0-9]"""

"""中解"""

#a="""904030200#600000048#001004000#400003029#090000010#820600003#000100700#240000001#009070304"""

"""小解"""

#a="""000200049#000007500#001000302#002401090#054309680#080705200#603000900#007500000#490008000"""#"""中解"""#a="""000000010#003024005#520003000#016002470#009070600#072600590#000500027#200380900#060000000"""#"""小解"""#a="""400800270#005200098#300000000#000092086#001000000#620040000#009000004#160005800#053008001"""#"""小解"""

a="""108730000

090000010

024160700

007000005

800501004

500000600

003095870

080000020

000012309"""

"""非常难解(不是好机器不要使用!!!!)"""

#a="""800000000#003600000#070090200#050007000#000045700#000100030#001000068#008500010#090000400"""#''' 解#[8, 1, 2, 7, 5, 3, 6, 4, 9]#[9, 4, 3, 6, 8, 2, 1, 7, 5]#[6, 7, 5, 4, 9, 1, 2, 8, 3]#[1, 5, 4, 2, 3, 7, 8, 9, 6]#[3, 6, 9, 8, 4, 5, 7, 2, 1]#[2, 8, 7, 1, 6, 9, 5, 3, 4]#[5, 2, 1, 9, 7, 4, 3, 6, 8]#[4, 3, 8, 5, 2, 6, 9, 1, 7]#[7, 9, 6, 3, 1, 8, 4, 5, 2]#'''

#a = """200007000#003400900#040200005#030000040#000631000#080000090#700005010#001004800#000900003"""

#将字符串转换为数组

defstr_list(a):

lis= a.split("\n")

lstt_a=[]for i inlis:#lstt_a.append([int(j) for j in i])

lstt_a.append(list(map(int, i)))returnlstt_a#取一行分组

defqiu_hang(yuanzhi, key):"""a[0][0-9]

a[1][0-9]

a[2][0-9]

a[3][0-9]

a[4][0-9]

a[5][0-9]

a[6][0-9]

a[7][0-9]

a[8][0-9]

:param yuanzhi: 原列表

:param key: 位置参数用到 行‘h'参数

:return: 横向的列表"""h, l=keyreturnyuanzhi[int(h)]#取一列分组

defqiu_lie(yuanzhi, key):"""a[0-8][0] a[0-8][1] a[0-8][2] a[0-8][3] a[0-8][4] a[0-8][5] a[0-8][6] a[0-8][7] a[0-8][08]

:param yuanzhi: 原列表

:param key: 位置参数 用到列‘l’参数

:return: 纵向的列表"""h, l=key

ret_list=[]for i in range(0, 9):

ret_list.append(yuanzhi[int(i)][int(l)])returnret_list#取宫里面的所有元素

defqiu_gong(yuanzhi, key):""":param yuanzhi:原9宫格列表

:param key: 位置参数

:return: 1个宫格列表"""h, l=key

h=int(h)#先判断行数

if h >= 0 and h <= 2:#再取宫格

return list_hang(yuanzhi, l, 0, 3)elif h >= 3 and h <= 5:return list_hang(yuanzhi, l, 3, 6)elif h >= 6 and h <= 8:return list_hang(yuanzhi, l, 6, 9)#宫方式取出所有

deflist_hang(yuanzhi, l, hm, hx):""":param yuanzhi:原列表

:param l: 列信息

:param hm: 最小行值 通过key信息hang确定(固定值)

:param hx: 最大行值 通过key信息hang确定(固定值)

:return: 1个宫格列表"""ret_list=[]

l=int(l)#根据列 ’l‘信息判定列范围,从而确定 是哪一个宫

if l >= 0 and l <= 2:for i inrange(hm, hx):for j in range(0, 3):

ret_list.append(yuanzhi[i][j])elif l >= 3 and l <= 5:for i inrange(hm, hx):for j in range(3, 6):

ret_list.append(yuanzhi[i][j])elif l >= 6 and l <= 8:for i inrange(hm, hx):for j in range(6, 9):

ret_list.append(yuanzhi[i][j])returnret_list#检测可能存在的值

defjiance(yuanzhi, jie):#判断结束

yuanzhi_new =copy.deepcopy(yuanzhi)#第一次求出所有可能解

jie2 =qiu_jie(jie, yuanzhi)#给空白位置赋值

x =chongxinfuzhi(jie2, yuanzhi_new)#x有两种返回值

#一种是返回一个填好的列表,

#一种返回一个元祖,元祖中有(两种解的列表 和 解列表)

#判定是否为一个填好列表,

if len(x) == 9:

flg=if_End(x, jie2)#这个flg 有3种返回值

#False 表示 解还没填写完。

#正确 填写完毕的 列表

#1 表示解 已经空了,相当于全部填写到空位里面去了但是不正确结束线程

ifflg:if flg != 1:print("正确了", os.getpid())

print_shuzu(flg)returnflgelse:print("错误进程结束", os.getpid(), flg)returnflg#如果解还有值递归填写

#jiance(x, jie2)

t = Process(target=jiance, args=(x, jie2))

t.start()else:#拆包两解情况,开启两个进程 分别去处理两种解。

#无限进行递归,

#把所有可能遍历一遍。

#很像一个动图 围棋遍历那个动图,看过的应该知道。。1生2 2生4 4生8 那种 8生16 .....

"""爆炸似增长,非常难解的那个a不是好机器不要去解。很可能电脑卡死

#

#

# #

#

#

#

#

#

# #

#

#

#"""new1, new2, jie2=x#多进程实现

t1 = Process(target=jiance, args=(new1, jie2))

t2= Process(target=jiance, args=(new2, jie2))

t1.start()

t2.start()return

#递归实现 深度过大时会报错,简单解的还可以,难解的不可用

#jie3=copy.deepcopy(jie2)

#jiance(new1, jie2)

#jiance(new2, jie3)

defif_End(new1, jie2):#print("进入判断")

for i injie2:if len(jie2[i]) !=0:returnFalseelse:

fl, i=jiaoyan(new1)iffl:returnnew1else:return 1

#校验

defjiaoyan(yuanzhi_new):

a= "00,13,26,31,44,57,62,75,88"lsit_a= a.split(",")for i inlsit_a:

gong=qiu_gong(yuanzhi_new, i)

hang=qiu_hang(yuanzhi_new, i)

lie=qiu_lie(yuanzhi_new, i)#按照特殊位 'a' 去取出行列宫所有种类的列表去判断。如果去重后长度都为9

if not (len(set(gong)) == 9) or not (len(set(hang)) == 9) or not (len(set(lie)) == 9):returnFalse, i#and 所有位中没有0站位的。就放正确

if 0 in gong or 0 in hang or 0 inlie:returnFalse, ielse:returnTrue, 0#输出数独所有

defprint_shuzu(yuanzhi_new):for i inyuanzhi_new:print(i)#重新赋值

defchongxinfuzhi(jie, yuanzhi_new):

flg=Truefor i injie:#分解解中行列标记{'00': [4, 6, 7, 8, 9], '01': [4, 8, 9], '02': [4, 7, 8], '03': [7, 8, 9], '04': [5, 6, 9], '05': [5, 6, 7, 8, 9], '06': [2, 3, 7, 8], '08': [2, 3, 4, 6, 8, 9], '10': [1, 6, 7, 8, 9], '11': [8, 9], '13': [1, 7, 8, 9], '16': [7, 8], '17': [6, 8], '22': [1, 4, 7, 8], '23': [1, 7, 8, 9], '24': [1, 6, 9], '26': [7, 8], '27': [4, 6, 8], '28': [4, 6, 8, 9], '30': [3, 8], '33': [8, 9], '34': [3, 5, 9], '38': [3, 8], '40': [3, 4, 8], '41': [3, 4, 5, 8], '43': [1, 4, 8], '45': [1, 5, 8], '47': [3, 8], '48': [1, 2, 3, 8], '50': [3, 4, 8], '54': [1, 3, 4], '55': [1, 8], '58': [1, 3, 8], '60': [1, 3, 4, 8, 9], '61': [3, 4, 8, 9], '62': [1, 4, 8], '64': [1, 4, 6, 9], '65': [1, 6, 9], '66': [1, 3, 8], '71': [4, 5], '72': [1, 4, 5, 7], '75': [1, 6, 7], '77': [4, 5, 6], '78': [1, 4, 6], '80': [1, 3, 4, 7, 8, 9], '82': [1, 4, 5, 7, 8], '83': [1, 2, 4, 7, 9], '84': [1, 4, 9], '85': [1, 7, 9], '86': [1, 3, 8], '87': [3, 4, 5, 8], '88': [1, 3, 4, 8]}

h, l =i#h=0,i=0

#这里判断 例如{'00': [4],} 则说明00位置只有一个解 就是 4,则赋值给原列表

if len(jie[i]) == 1:

yuanzhi_new[int(h)][int(l)]=jie[i][0]#如果有解重新赋值到了原列表中则 否定 有多解情况

flg =Falseelse:#判断是否存在一个解的情况

#if flg and 0:

ifflg:#如果都是多种解的情况 是解中没有 可添加的值

returnduogejie(yuanzhi_new, jie)returnyuanzhi_new#固定值--填进去的值#如果是多个解的情况返回两种解的固定值

defduogejie(yuanzhi, jie):#复制两份原列表

yuanzhi_new =copy.deepcopy(yuanzhi)for i injie:

h, l=i#循环‘解’字典,

if len(jie[i]) == 2:

h1, h2=jie[i]print(h1,h2)

yuanzhi_new[int(h)][int(l)]=h1

yuanzhi[int(h)][int(l)]=h2

jie[i].pop()

jie[i].pop()returnyuanzhi_new, yuanzhi, jieelse:returnyuanzhi#求所有可能的解

defqiu_jie(jie, yuanzhi):#print(jie)

for i injie:

gong_lis=qiu_gong(yuanzhi, i)

jie[i]=jiancefangfa(gong_lis, jie[i])

hang_lis=qiu_hang(yuanzhi, i)

jie[i]=jiancefangfa(hang_lis, jie[i])

lie_lis=qiu_lie(yuanzhi, i)

jie[i]=jiancefangfa(lie_lis, jie[i])returnjie#检测是否存在

defjiancefangfa(list_a, wei):#大于0

if len(wei) > 0 and wei[0] == 10:

wei= [i for i in range(1, 10)]

res=[]for i inwei:if i not inlist_a:

res.append(i)returnresdefmain():#字符串转列表

yuanzhi =str_list(a)#解集合

jie =kong_jie(yuanzhi)#正确的值

print(os.getpid())

yuanzhi_new=jiance(yuanzhi, jie)#输出正确的值

ifyuanzhi_new:

print_shuzu(yuanzhi_new)

sys.exit()#初始化空解

defkong_jie(yuanzhi):

jie={}

i=0while i

j=0while j

jie[str(i) + str(j)] = [10]

j+= 1i+= 1

returnjieimportcProfileif __name__ == '__main__':

cProfile.run("main()")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值