import numpy as np
import time
time1 = time.time()
'''整体灵感就是1 求出每个数字为0的位置可以填的数,并将其位置和能填的数分别以key和value的方式存储到字典里面2 将字典里的数据按照所能填写的数据的多少进行排序,先在能填的数少的里面选取一个进行填写3 将填写的过程记录到列表里面,这个地方暂时想到的就是用列表记录填写过程4 更新1、2步,若出现某一步可填写的数据为空,说明之前某一步的选择有问题,回溯回去,更换数值,然后回到步骤15 当所有的数都填完后,退出循环
'''def nine(data):nine_block = np.zeros([3,3,3,3], dtype = int)for i in range(3):for j in range(3):nine_block[i,j] = data[3*i:3*(i+1),3*j:3*(j+1)]return nine_blockdef num_set(data, nine_block):pick_set = {}for i in range(9):for j in range(9):if data[i,j] == 0:pick_set[str(i)+str(j)] = set(np.array(range(10))) - \(set(data[i,:]) | set(data[:,j]) | \set(nine_block[i//3,j//3].ravel()))return pick_setdef try_insert(data):    insert_step = []while True:pick_set = num_set(data, nine(data))if len(pick_set) == 0: breakpick_sort = sorted(pick_set.items(), key = lambda x:len(x[1]))item_min = pick_sort[0]key = item_min[0]value = list(item_min[1])insert_step.append((key, value))if len(value) != 0:data[int(key[0]), int(key[1])] = value[0]else:insert_step.pop()for i in range(len(insert_step)):huishuo = insert_step.pop()key = huishuo[0]insert_num = huishuo[1]if len(insert_num) == 1:data[int(key[0]), int(key[1])] = 0else:data[int(key[0]), int(key[1])] = insert_num[1]insert_step.append((key, insert_num[1:]))breaktiem2 = time.time()print('\nFinished! using time:', tiem2-time1, 's')print(data)    if __name__ == '__main__':data =  "0 0 0 0 0 0 0 6 0 \0 0 0 0 0 4 7 0 5 \5 0 0 0 0 0 1 0 4 \1 0 0 0 0 2 4 0 0 \0 0 8 0 7 0 0 0 0 \0 3 0 6 0 0 0 0 0 \2 0 0 0 0 9 0 0 1 \0 0 6 0 8 0 0 0 0 \0 7 0 3 0 0 0 0 0 "data = np.array(data.split(), dtype = int).reshape((9, 9))print(data)try_insert(data)

别不多说,代码先行,运行结果如下

用时1.91秒,还算能看,其实很早就想做点什么,但碍于能力有限,一直拖着,没有实践。刚开始考虑用excel实现求解数独来着,奈何同样涉及到VBA,而在下对VBA只是略懂皮毛,只能作罢。

至于学习Python的过程,其实在很早的时候,就听同窗加挚友洪同学提及过Python,当时第一感觉和帕金森音略同,故而与之戏称帕金森云云,真正开始学习Python其实要追溯到17年12月份,到写此文时也有近6个月的时间,不知不觉,小半年了。进度之缓慢,说来实在惭愧。

好了,回到正文,其实基本的思想在代码里面也有所提及,下面就着重讲解下各部分代码在干嘛吧!

numpy这个东西很好用,里面提供了数组的各种花样操作,对于初学者来说,降低了入门难度,故而我很喜欢^_^。而time模块在这里其实只起到了计算程序运行时间的作用,就不再说了。

首先,定义函数nine(data),这个函数的主要功能是将9×9的数据,变成3×3的块,于是在事先,就先利用了numpy模块生成了这样的块,这也就是下面这行代码所干的事。

nine_block = np.zeros([3,3,3,3], dtype = int)

紧接着,将原来的数据按块填进已生成的nine_block中,就是两个for循环,就实现了这个需求。

for i in range(3):for j in range(3):nine_block[i,j] = data[3*i:3*(i+1),3*j:3*(j+1)]

至于这里的赋值为什么是这样来赋值,其实很容易理解,拿所要填的第一块来说,也就是nine_block[0,0],是不是希望将data里面的前三行前三列数据填过来,这个时候那就是data[0:3, 0:3]; 再看水平方向的第二块,是不是就是data[0:3, 3:6],以此类推。那么跟nine_block的索引i, j结合起来就不难看出这个赋值表达式意义了。

接着,定义函数num_set(data, nine_block),此函数的作用为,将data中所有为0的位置的可填数找到,并存储到一个字典里面,其中这个字典的key为0值的行索引和列索引,这里用str(i)+str(j)实现,而该位置可填的数究竟怎么确定的,其实,这就要回到数独的玩法上了,因为在填数时玩家必须保证该位置所属的行、列以及块里面没有这个数的时候,否则就违反了游戏规则,那么这里的可填数就使用了这个规则,就是在(1 ~ 9)的数字集合删去已经在相关位置出现的数,那么这样就找到了该位置可填的数的集合。在这里主要用到了集合的子、交、并、补概念。

pick_set = {}
for i in range(9):for j in range(9):if data[i,j] == 0:pick_set[str(i)+str(j)] = set(np.array(range(10))) - \(set(data[i,:]) | set(data[:,j]) | \set(nine_block[i//3,j//3].ravel()))

可能你会注意到在这里的相应的所属块取出来后,可能无法直接用set(nine_block[i//3,j//3]),但我把这个块状的数据ravel()后,就是拉平后,可以使用了,至于内在原因,还在摸索当中。

这个函数的返回值是长这样的^_^

比如说'00':{3,4,7,8,9},这就表明此时在data中位于第1行,第1列的位置,其可填的数为3,4,7,8和9。其他的也是如此。

最后定义的函数为try_insert(data),实现了数据的插入,步骤分为两步,即插和改。由于对递归实现的方法不甚理解,所以就不班门弄斧了,这里使用的是利用列表来记录每一次的插入。插入一个值,同时在插入下一个值之前,就更新了我们的可选字典,这样以便快速验证插入数值的正确性。那么究竟怎么判断我首次插入的值是否准确呢,其实这个地方就是深度优先的概念了,就是说,一条路走到黑,直到走不通为止,因为但凡我前面的数填的不对,走到后面就会发现,在某一个位置就会出现没有可填数的情况,但怎么告诉程序说前面填错了呢?思考三分钟...

这个时候我们的记录插入情况的列表就派上用场了,可以根据插入情况进行回溯,怎么个回溯法呢?简单来说就是由后往前找,在第一个分叉的地方,换另外的数,并把之前走不通的数舍去,下面就一个例子进行说明,假如下面是我的某一次的插入过程

在程序里面默认的插入方法是:当有多个选择时,先插入可选数集合中的第1个数。在如上的这个插入过程当中,发现,在进行对索引值为'55'位置的数进行插入时,竟然发现此处没有可插入数,那么,问题来了,必然是前面出错了,可是错误出在哪呢?无从得知,只知道错误出现了,那么就此例而言,错误会出现在索引值为'45', '75', '01'这些可填值只有1个的位置上吗,显然不是,因为可填数只有1个,那我只能填这个了,暂且称之为被动正确(临时想到的),那么这个错误很有可能是出在诸如索引值为'00', '21'这样的可填数不唯一的地方,可是怎么回去呢,思考三分钟...

一言以蔽之 改,如何改,不卖关子了,就是把'70', '10', '62'这些被动正确的地方数重新变为0,然后在'00'这个位置把插入数不选9,选3,然后往下走,如果选3之后后面走通了,那么皆大欢喜,但是,万一走不通怎么办,如果又走不通,说明不是'00'处的问题,而是问题还在前面,如'21', '40'这样的位置,但如何回溯到更前一步呢?即然在前面情况不变下,'00'处选9走不通,那何不在首次回溯时,就暂时在'00'处的可选值中将9丢弃,这样在'00'处选3的情况下,如果还走不通,那么我们再次进行回溯时,就不会还是找'00'了,而是会找到'21'的位置。如此循环,直到所有的值都填上为止。

代码就不再贴了,前面可能没有说,在选值进行插入时,我提前将可选集合按照可填数的多少进行了排序,先填可选数少的,这样可以大大提高程序运行效率。^_^

利用python,求解数独相关推荐

  1. python 物理学中的应用_利用python求解物理学中的双弹簧质能系统详解

    前言 本文主要给大家介绍了关于利用python求解物理学中双弹簧质能系统的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 物理的模型如下: 在这个系统里有两个物体,它们的质 ...

  2. python代码物理_利用python求解物理学中的双弹簧质能系统详解

    前言 本文主要给大家介绍了关于利用python求解物理学中双弹簧质能系统的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 物理的模型如下: 在这个系统里有两个物体,它们的质 ...

  3. 利用python求解节点介数和边介数

    利用python求解节点介数和边介数 利用networkx里面的函数betweenness_centrality(G)来求解节点介数和函数edge_betweenness_centrality(G)来 ...

  4. 【Numpy】用Python求解数独

    目录 [题目]列出如下数独问题的2种数学模型,分析两种模型的优缺点,并用Excel求解,将结果填上.这里用Python进行求解: 一.代码 model1 二.代码 model2 三.求解结果 [题目] ...

  5. 利用python求解规划问题

    规划问题分为两个大类:线性规划和非线性规划以及下面分支的小类,我们观看这个树状图来粗略的了解一下. 首先我们讲解最简单的线性规划模型,通常线性规划均属于凸规划,通常都是用python中的cvxpy进行 ...

  6. [转载] 【数学问题】利用python求解表达式

    参考链接: Python 变量 |表达式 |条件和函数 有时候我们会遇到一些很复杂的表达式,或者想要求解某个表达式,但是手动计算的话不但耗时还费精力,我们能不能利用计算机来帮助我们进行计算呢? 1.问 ...

  7. 【数学问题】利用python求解表达式

    有时候我们会遇到一些很复杂的表达式,或者想要求解某个表达式,但是手动计算的话不但耗时还费精力,我们能不能利用计算机来帮助我们进行计算呢? 1.问题描述 我们昨天提出了四足机器人的初始姿态的问题,里面给 ...

  8. 利用Python求解八数码难题

    实验目的 实验内容 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题 ...

  9. 利用python求解度中心性

    利用networkx里面的函数degree_centrality(G)来求解图的度中心性. 代码如下: # -*- coding: utf-8 -*- """ Creat ...

  10. 期末微积分考试试题求解 :利用python求解

    在 今年期末微积分考试试题:看看你能够在两个小时内做对几道题? 搜集到了一份期末微积分考试试题.为了对其内容进行进一步分析,对其内容进行整理如下. §01 填空题 每个空3分,共10题 1. 求解常微 ...

最新文章

  1. 熟练Linux ,先从这 26 个命令开始吧
  2. 创建一个类 new 与 不加new 有什么区别?
  3. Java 8 获取某天最大(23:59:59)最小(00:00:00)时间
  4. scala集合fold实例:将两个Map合并
  5. WinSock完成端口I/O模型
  6. Django从理论到实战(part48)--Django表单
  7. Java BufferedReader reset()方法及示例
  8. php对某目录设置ip权限,apache - .htaccess如何单独给某个请求设置IP白名单权限?...
  9. 位、字、字节的区别 | 汇编伪指令db,dw,dd
  10. CVPR 2017精彩论文解读:综合使用多形态核磁共振数据的3D生物医学图像分割方法...
  11. 最小二乘法概念和代码示例
  12. 学习blus老师js(1)--基础
  13. 报错: EBUSY: resource busy or locked, lstat ‘C:\hiberfil.sys‘
  14. Matlab-四杆桁架结构的有限元分析(有限元分析基础-曾攀)
  15. AtCoder Beginner Contest 285 青大蒟蒻训练日常(A-F) 上分场(可惜unr)
  16. MySQL怎么用x28改变颜色_MySQL SELECT练习题*28
  17. 老虎证券社招java工程师
  18. JavaScript 简单学习
  19. 软件中间件,你知道哪些?
  20. 网络工程大一课程c语言,网络工程专业主要开哪些课程?

热门文章

  1. sharemouse切窗口就锁定了什么原因_使各大网课软件监控功能和锁定功能“失效”...
  2. java map 队列_JavaSE-List/Map/Queue
  3. Python——组合数据类型的应用_1.英文句子中的词频统计
  4. 曝大S汪小菲婚宴初定汪小菲三亚顶级酒店
  5. [项目]——文件搜索工具Java-Everything
  6. 计算机数学与高中数学衔接,高中数学的断层与衔接研究论文
  7. JavaScript几种原生函数
  8. MATLAB 立体绘图
  9. java多态app_【Java基础】Java中的多态
  10. abb式c语言,ABB机器人是用什么语言编程的? ——ABB机器人