import threading, time, sys, os, copy
from multiprocessing import Process, 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"""
# 将字符串转换为数组
def str_list(a):
lis = a.split("\n")
lstt_a = []
for i in lis:
# lstt_a.append([int(j) for j in i])
lstt_a.append(list(map(int, i)))
return lstt_a
# 取一行分组
def qiu_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 = key
return yuanzhi[int(h)]
# 取一列分组
def qiu_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)])
return ret_list
# 取宫里面的所有元素
def qiu_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)
# 宫方式取出所有
def list_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 in range(hm, hx):
for j in range(0, 3):
ret_list.append(yuanzhi[i][j])
elif l >= 3 and l <= 5:
for i in range(hm, hx):
for j in range(3, 6):
ret_list.append(yuanzhi[i][j])
elif l >= 6 and l <= 8:
for i in range(hm, hx):
for j in range(6, 9):
ret_list.append(yuanzhi[i][j])
return ret_list
# 检测可能存在的值
def jiance(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 表示解 已经空了,相当于全部填写到空位里面去了但是不正确结束线程
if flg:
if flg != 1:
print("正确了", os.getpid())
print_shuzu(flg)
return flg
else:
print("错误进程结束", os.getpid(), flg)
return flg
# 如果解还有值递归填写
# 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)
def if_End(new1, jie2):
# print("进入判断")
for i in jie2:
if len(jie2[i]) != 0:
return False
else:
fl, i = jiaoyan(new1)
if fl:
return new1
else:
return 1
# 校验
def jiaoyan(yuanzhi_new):
a = "00,13,26,31,44,57,62,75,88"
lsit_a = a.split(",")
for i in lsit_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):
return False, i
# and 所有位中没有0站位的。就放正确
if 0 in gong or 0 in hang or 0 in lie:
return False, i
else:
return True, 0
# 输出数独所有
def print_shuzu(yuanzhi_new):
for i in yuanzhi_new:
print(i)
# 重新赋值
def chongxinfuzhi(jie, yuanzhi_new):
flg = True
for i in jie:
# 分解解中行列标记{'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 = False
else:
# 判断是否存在一个解的情况
# if flg and 0:
if flg:
# 如果都是多种解的情况 是解中没有 可添加的值
return duogejie(yuanzhi_new, jie)
return yuanzhi_new
# 固定值--填进去的值
# 如果是多个解的情况返回两种解的固定值
def duogejie(yuanzhi, jie):
# 复制两份原列表
yuanzhi_new = copy.deepcopy(yuanzhi)
for i in jie:
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()
return yuanzhi_new, yuanzhi, jie
else:
return yuanzhi
# 求所有可能的解
def qiu_jie(jie, yuanzhi):
# print(jie)
for i in jie:
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])
return jie
# 检测是否存在
def jiancefangfa(list_a, wei):
# 大于0
if len(wei) > 0 and wei[0] == 10:
wei = [i for i in range(1, 10)]
res = []
for i in wei:
if i not in list_a:
res.append(i)
return res
def main():
# 字符串转列表
yuanzhi = str_list(a)
# 解集合
jie = kong_jie(yuanzhi)
# 正确的值
print(os.getpid())
yuanzhi_new = jiance(yuanzhi, jie)
# 输出正确的值
if yuanzhi_new:
print_shuzu(yuanzhi_new)
sys.exit()
# 初始化空解
def kong_jie(yuanzhi):
jie = {}
i = 0
while i < len(yuanzhi):
j = 0
while j < len(yuanzhi[i]):
if yuanzhi[i][j] == 0:
# 初始化空解,所以位用10占位
jie[str(i) + str(j)] = [10]
j += 1
i += 1
return jie
import cProfile
if __name__ == '__main__':
cProfile.run("main()")
欢迎讨论 !如果解过于复杂时可能会报错。~~~~~~~~~~~~~~~
来源:https://www.cnblogs.com/hao66/p/9321573.html