python数组间隔取值_⽤Python解数独[0]
⽬录
1. ⽤Python解数独[0]
2. ⽤Python解数独[1]:求每个单元格的⾏值域
3. ⽤Python解数独[2]:求列值域和九宫格值域
4. ⽤Python解数独[3]:求总值域
5. ⽤Python解数独[4]:缩减值域
6. ⽤Python解数独[5]:检测唯⼀值缩减值域
7. ⽤Python解数独[6]:递归获得最终答案
8. ⽤Python解数独[7]:递归(完结篇)
[0] 前⾔
⾸先声明阅读本⽂需要哪些Python基础知识:
for循环
if条件判断
列表(list)的基本⽅法:list.append(), ve(), unt(), d(), len(list)
函数基本概念
具备这些知识就⾜够了,我们将使⽤这些“基础知识”,做⼀个⾜够“复杂”的项⽬。
然后需要解释下为什么要⽤数独项⽬帮助新⼿⼊门:
个⼈原因,我⾃⼰很喜欢数独这个游戏,以前也花了很多时间去玩;
数独这个游戏⾜够纯粹,⽤⼀个⼆维数组就能表⽰出来,不需要其它任何属性;
解决⼀个数独问题,过程⾜够复杂,⽽⽤到的Python知识⼜⾮常基础;
因此我个⼈认为数独项⽬⾮常适合刚刚掌握Python基础知识的新⼿,⼤胆上⼿练习,仔细学习思考,能帮你建⽴信⼼并帮助成长。现在,我们正式开始吧。
[1] 数独问题
数独的规则很简单,在⼀个9*9的棋盘上,已经出现了若⼲个数字(1-9),要求根据已有数字遵照规则求出所有空⽩地⽅的数字,规则如下:
数字范围是1-9;
每⼀⾏数字不能重复;
每⼀列数字不能重复;
粗实线划分出的9个九宫格,每个九宫格内数字不能重复;
那么我们在解决数独问题时,会遇到如下两种情况:
1. 可以根据规则,直接得出某个单元格的答案
第9⾏第4列的单元格,因为第4列已经有8个数字,因此可以直接确定该单元格数字为8
第6⾏第1列的单元格,第6⾏只剩下数字2和9未出现,⽽第1列已经出现数字9,因此该单元格数字为2
2. 根据规则⽆法直接得出答案,只能得到取值范围
第1⾏第1列,根据⾏判断可能的取值是[2,4,5,6,7],根据列判断可能的取值是[1,2,3,5,6],根据九宫格判断可能的取值是[1,3,4,5,6],综合三个取值,最终取值范围是[5,6]
[2] 数独模型和解决数独⽅法
[2][0] ⽤⼆维数组表⽰数独
数独可以很直观地⽤⼆维数组来表⽰,所谓⼆维数组可以简单理解为,数组中的每⼀个元素依然是⼀个数组
我们可以⽤空字符串 '' 来表⽰空⽩单元格,有数字的单元格在对应位置填上数字即可,类似于这样
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]
python新手代码练习如果看不懂
soduku = [[] for i in range(9)]
其实就是
soduku = []
for i in range(9):
soduku.append([])
或者是
soduku = [[],[],[],[],[],[],[],[],[]]
[2][1] 解决数独问题基本思路
经过简单的分析,我们其实已经总结出解决数独问题的⽅法:
1. 根据单元格所处的⾏、列、九宫格,分别计算出单元格的⾏值域、列值域和九宫格值域;(所谓值域,就是指该单元格的取值范围)
2. 3个值域求交集,得到单元格最终的值域;
那么如何⽤代码实现以上的基本思路呢,不要着急,我们梳理⼀下需要做哪些事情:
1. 求每个单元格的⾏值域
只有该⾏的数字会影响到单元格的⾏值域,因此求数独每个单元格的⾏值域,可以简化为求每⼀⾏每个单元格的⾏值域,也就是把相同的事情重复做9次就好了。
如何求⼀⾏每个单元格的⾏值域呢,⽐如第⼀⾏是
soduku[0] = ['',8,9,1,'',3,'','','']
直观地去看,其实第⼀⾏空⽩单元格的⾏值域,就是这⼀⾏未出现数字的集合,即[2,4,5,6,7],每个单元格的⾏值域都是[2,4,5,6,7]。代码实现思路也就很明显了,数字全集是[1,2,3,4,5,6,7,8,9],这⼀⾏⾥出现了哪些数字,我们就从全集⾥去除这些数字,最后剩下数字组成的数组就是这⼀⾏每个单元格的⾏值域。
row = ['',8,9,1,'',3,'','','']
row_value_range = list(range(1,10)) # range(1,10)并不是列表类型,因此需要⽤list()⽅法转化为列表
for i in row:
if i == '': # 不要忘记数组中还有空单元格
continue
else:
row_ve(i)
改写为函数
row = ['',8,9,1,'',3,'','','']
def valueRange(row):
row_value_range = list(range(1,10))
for i in row:
if i == '':
continue
else:
row_ve(i)
return row_value_range
print(valueRange(row))
PS D:python0624-soduku> python test7.py
[2, 4, 5, 6, 7]
但是有⼀个问题,其实我们希望得到的输出是
[[2, 4, 5, 6, 7],8,9,1,[2, 4, 5, 6, 7],3,[2, 4, 5, 6, 7],[2, 4, 5, 6, 7],[2, 4, 5, 6, 7]]
为了保持元素的统⼀,即数组内元素都是数组(⽽不是数组和数字掺杂),应该得到如下输出
[[2, 4, 5, 6, 7],[8],[9],[1],[2, 4, 5, 6, 7],[3],[2, 4, 5, 6, 7],[2, 4, 5, 6, 7],[2, 4, 5, 6, 7]]
那么我们的⾏值域函数还需要继续改进
row = ['',8,9,1,'',3,'','','']
def valueRange(row):
temp = copy.deepcopy(row)
row_value_range = list(range(1,10))
for i in row:
if i == '':
continue
else:
row_ve(i)
for j in temp:
if j == '':
j = row_value_range
else:
j = [j]
return temp
看起来代码逻辑很合理,然后执⾏之后发现
PS D:python0624-soduku> python test5.py
['', 8, 9, 1, '', 3, '', '', '']
哦?为什么没有任何变化
预知后事如何,且听下回分解
[1]⾃学能⼒强的同学可以直接到github看完整代码
[2]本⽂中数独题⽬来⾃8⽉2⽇⼊门级别题⽬(⽹站链接见最下⽅),⽹站很好⽤,⼤家可以去玩玩
下⼀篇链接:⽤Python解数独[1]:求每个单元格的⾏值域
参考
1. ^Python解数独完整项⽬代码 github/smellsee/Python_Soduku_Cheats
2. ^本⽂中的数独题⽬来源 /

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。