9x9数独算法

news/2025/3/19 4:19:04/
下面给出了源代码
sdks文件里面含有120个数独
请各位大大纠正

这个算法也可以用来做生成数独,然后取出几个
比如你给定数独为

000000000000000000000000000000000000000000000000000000000000000000000000000000001
# 嘿嘿,这解可多了,机器别跑死了。



# -*- coding:utf-8 -*-
'''
首先生成9x9x9的三维数组,每个值为[1,2,3,4,5,6,7,8,9]
1,然后确定有独一的值,清除行,列,块当中的值 clean(data)函数
继续1
然后找到唯一值,即行、列或块当中只出现一次的值,设置当前值,然后执行1,clean_help(data)函数
最后如果没有唯一值那就找最少候选的那个格子先尝试这个格子的其中一个候选,再尝试剩余的候选数字
'''

#1. 先遍历一遍,找出所有“只有一个候选数字”的格子, 清除行,列,块数据
#2. 填满这些数字,重复第一步
#3. 如果没有“只有一个候选数字”的格子,那就找最少候选的那个格子
#  先尝试这个格子的其中一个候选,再尝试剩余的候选数字
from copy import deepcopy
# 移除数组中指定的值
def rm(s, n):
i = 0
try:
s.remove(n)
i = i + 1
except:
pass
return i
# 根据行,列坐标,返回行,列,块数组
def find(fbs, i, j):
block = []
br = i / 3 * 3
bc = j / 3 * 3
for l in range(0, 3):
r = br + l
for k in range(0, 3):
c = bc + k
block.append(fbs[r][c])
return {"row":fbs[i], "column":[fbs[a][j] for a in range(0, 9)], "block":block}
# 打印
def pnt(dbss):
print "============"
for i in range(0, 9):
print dbss[i], "\n"
# 生成9×9×9的三维数组
base = [[[i for i in range(1, 10)] for a in range(1, 10)] for b in range(1, 10)]
sudo1 = [
[0,8,1, 0,9,0, 0,0,0],
[0,0,0, 1,0,7, 0,5,0],
[0,7,5, 0,4,0, 0,0,1],
[0,0,0, 0,3,4, 2,0,0],
[5,0,0, 7,0,1, 0,0,0],
[0,0,0, 0,0,2, 1,0,9],
[0,0,6, 0,8,0, 0,0,4],
[8,0,7, 6,0,0, 5,0,0],
[0,0,3, 0,0,0, 6,0,8]
]
# 此数独没有解出来。
sudo2 = [
[ 8, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 3, 6, 0, 0, 0, 0, 0 ],
[ 0, 7, 0, 0, 9, 0, 2, 0, 0 ],
[ 0, 5, 0, 0, 0, 7, 0, 0, 0 ],
[ 0, 0, 0, 0, 4, 5, 7, 0, 0 ],
[ 0, 0, 0, 1, 0, 6, 0, 3, 0 ],
[ 0, 0, 1, 0, 0, 0, 0, 6, 8 ],
[ 0, 0, 8, 5, 0, 0, 0, 1, 0 ],
[ 0, 9, 0, 0, 0, 0, 4, 0, 0 ]
]

# 此数独有解,但死循环
sudo3 = [
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 3, 0, 0, 0],
[0, 0, 4, 0, 0, 0, 5, 0, 0],
[0, 6, 0, 0, 0, 0, 0, 7, 0],
[8, 0, 0, 0, 5, 0, 0, 0, 9],
[0, 7, 0, 0, 0, 0, 0, 6, 0],
[0, 0, 5, 0, 0, 0, 4, 0, 0],
[0, 0, 0, 3, 0, 2, 0, 0, 0],
[0, 0, 0, 0, 9, 0, 0, 0, 0]
]
sudo4 = [
[0, 0, 0, 0, 1, 0, 8, 7, 0],
[0, 2, 0, 0, 9, 0, 0, 0, 0],
[0, 0, 0, 5, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 6, 8, 0, 9, 0],
[0, 0, 8, 0, 7, 0, 3, 0, 0],
[0, 9, 7, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 4, 6, 3, 0],
[0, 8, 0, 0, 5, 0, 0, 0, 0],
[0, 7, 1, 3, 0, 0, 9, 0, 0]
]

sudo5 = [
[0,0,2,4,5,0,7,0,0]
,[0,4,0,0,0,8,0,3,0]
,[8,0,1,0,0,3,5,0,6]
,[0,5,3,0,0,0,0,0,4]
,[7,0,0,0,0,0,0,0,2]
,[2,0,0,0,0,0,6,7,0]
,[3,0,6,5,0,0,1,0,7]
,[0,2,0,1,0,0,0,5,0]
,[0,0,7,0,2,9,4,0,0]
]

# 初始化填充base
def inits(b, s):
for i in range(0, 9):
sudo = s[i]
for j in range(0, 9):
num = sudo[j]
if num != 0:
b[i][j] = [num]
finds = find(b, i, j)
for f in finds:
ff = finds[f]
for fff in ff:
if len(fff) > 1:
rm(fff, num)
return b

# 根据独一值,清除行,列,块值
def clean(clean_data):
flag = True
while flag:
# 退出条件
rms = 0
for i in range(0, 9):
for j in range(0, 9):
num = clean_data[i][j]
if len(num) == 1:
# 根据独一值清除行,列,块
finds = find(clean_data, i, j)
for f1 in finds:
f2 = finds[f1]
for f3 in f2:
if len(f3) > 1:
rms += rm(f3, num[0])
if rms == 0:
flag = False
return clean_data
# 找到唯一值,并清除行列块
def clean_help(data):
while True:
# 退出条件
flag = True
for i in range(0, 9):
for j in range(0, 9):
brk = 0
cur = data[i][j]
if len(cur) > 1:
finds = find(data, i, j)
for f in finds:
a = [0] * 9
f1 = finds[f]
for f2 in f1:
for f3 in f2:
a[f3 - 1] += 1
for m in cur:
# 找到了唯一值,并进行设置,清除数独,退出当前循环
if a[m - 1] == 1:
flag = False
brk = 1
data[i][j] = [m]
clean(data)
break
if brk == 1:
break
# 当没有唯一值是退出循环
if flag:
break
return data

# 读取数独源
def readSdks(i):
sudokus = open("sdks", "r")
if i < 0 or i > 125:
print "Not found sudoku data"
return
sdk = sudokus.readlines()[i].replace("\n","")
sdks = [sdk[j:j + 9] for j in range(0, 81, 9)]
#print sdks
ret = [[int(sk[l]) for l in range(0, 9)] for sk in sdks]
sudokus.close()

return ret

# 验证数独
def isOk(data):
for i in range(0, 9):
for j in range(0, 9):
finds = find(data, i, j)
for f in finds:
a = [0] * 9
ff = finds[f]
for fff in ff:
if len(fff) > 1:
return False
a[fff[0] - 1] += 1
for ia in a:
if ia > 1 or ia == 0:
return False
print "ok"
return True

# 找到数独当中最小候选对象元祖
#([], x, y) 数组为候选可能值,x为行坐标,y为列坐标
def small(data):
ret_sm = ([0] * 9, -1, -1)
for i in range(0, 9):
for j in range(0, 9):
if len(data[i][j]) > 1 and len(data[i][j]) < len(ret_sm[0]):
ret_sm = (data[i][j], i, j)
return ret_sm

# 最后数独完成操作 设置候选值
def done(data):
if isOk(data):
pnt(data)
return
sm_tuple = small(data)
#print sm_tuple
if sm_tuple[1] == -1:
#print "no solve"
return
# 设置候选值
for sm in sm_tuple[0]:
#pnt(data)
# 复制数独源,上次的结果不然还存在,就不能求多解了
copy_data = deepcopy(data)
# 设置候选值
copy_data[sm_tuple[1]][sm_tuple[2]] = [sm]
# 然后执行清除操作
copy_data = clean_help(clean(copy_data))
if isOk(copy_data):
#print "in done"
pnt(copy_data)
return
# 如果没有完成,继续设置候选值
done(copy_data)


def main():
for i in range(0, 120):
print "The %d index" % i
#readSdks(1)
sudokuData = readSdks(i)
base = [[[j for j in range(1, 10)] for a in range(1, 10)] for b in range(1, 10)]
init_data = inits(base, sudokuData)
#print "init:"
#pnt(init_data)
clean_data = clean(init_data)
#print "clean:"
#pnt(clean_data)
only_data = clean_help(clean_data)
#print "only:"
#pnt(only_data)
done(only_data)

if __name__ == "__main__":
main()


http://www.ppmy.cn/news/235550.html

相关文章

java 字节替换_java 替换四个字节的字符 '\xF0\x9F\x98\x84\xF0\x9F)的解决方案

/** * 替换四个字节的字符 \xF0\x9F\x98\x84\xF0\x9F)的解决方案 &#x1f601; * author ChenGuiYong * data 2015年8月11日 上午10:31:50 * param content * return */ public static String removeFourChar(String content) { byte[] conbyte content.getBytes(); for (int…

【SemiDrive源码分析】【X9 Audio音频模块分析】16 - 音频模块框图及硬件原理图分析

【SemiDrive源码分析】【X9 Audio音频模块分析】16 - 音频模块框图及硬件原理图分析 一、X9HP 音频模块框图及硬件原理图分析1.1 音频接口 I2S 介绍1.2 X9 平台音频模块框图1.3 X9 平台各 Domain 用的 I2S接口 及 CLK 介绍1.3.1 `Safety OS Domain` 的 `I2S1` 接口:送数据入DS…

EndNote X9 教程入门到进阶 win mac

数据库创建 打开EndNote&#xff08;激活版下载&#xff09;&#xff0c;界面如下&#xff1a; 首先需要新建文献数据库文件&#xff0c;File- New- 选择文件夹&#xff1a; 选择保存路径后点击确定即完成数据库文件创建&#xff0c;创建后生成两个文件&#xff1a;MyEndNote L…

【SemiDrive源码分析】【X9芯片启动流程】30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析(一)

【SemiDrive源码分析】【X9芯片启动流程】30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析&#xff08;一&#xff09; 一、Android Kernel 启动流程分析1.1 入口汇编代码 arch\arm64\kernel\head.S &#xff1a; 跳转start_kernel() 入口函数1.2 入口函数 start_…

mysql 字符串值不正确,不正确的字符串值:“ \ xF0 \ x9F \ x8E \ xB6 \ xF0 \ x9F…” MySQL...

我正在尝试在我的MYSQL表中存储一条推文。的鸣叫是&#xff1a; quiero que me escuches&#xff0c;no te burles no te rias&#xff0c;anoche tuve unsueoque te fuiste de mi vida&#x1f3b6;&#x1f3b6; tweet_text我表格中的字段编码为utf8mb4。但是&#xff0c;当我…

【SemiDrive源码分析】【X9芯片启动流程】11 - freertos_safetyos目录Cortex-R5 DIL2.bin 引导程序源代码分析

【SemiDrive源码分析】【X9芯片启动流程】11 - freertos_safetyos目录Cortex-R5 DIL2.bin 引导程序源代码分析 一、freertos_safetyos目录结构分析二、DIL2 抓取编译log三、DIL2 代码流程分析3.1 start.S 入口汇编代码,初始化环境后跳转lk_main()3.2 lk_main() 创建并执行 boo…

EndNote X9 快捷键 官方大全

EndNote X9 快捷键 大全 没有baidu到靠谱的EndNote快捷键&#xff0c;故找到官方手册并节选出来以飨读者。 本文摘自EndNote X9官方用户手册 P463-468 将就看看呗&#xff0c;当中只有加号的地方省略了 ctrl Pages from EndNote Keyboard Commands Editing Keyboard Commands…

c语言程序设计数字电位器,X9C103数字电位器中文.pdf

==2000:09:11== P&S武汉力源电子股份有限公 司 == 10-1== X9C102 103 104 503 2 TM E POT 非易失性数控电位器,端电压5V ,100个抽头 一、概述 1.1 一般说明 X9C102/ 103/ 104/503是固态非易失性电位器,把它用作数字控制的微调电阻器是理想的。它的功能 方框图如图1所示。…