![aec9eecc539c604959d6b2bf98eedcfa.png](https://img-blog.csdnimg.cn/img_convert/aec9eecc539c604959d6b2bf98eedcfa.png)
目录
- 用Python解数独[0]
- 用Python解数独[1]:求每个单元格的行值域
- 用Python解数独[2]:求列值域和九宫格值域
- 用Python解数独[3]:求总值域
- 用Python解数独[4]:缩减值域
- 用Python解数独[5]:检测唯一值缩减值域
- 用Python解数独[6]:递归获得最终答案
- 用Python解数独[7]:递归(完结篇)
[2][1] 解决数独问题基本思路
2、求每个单元格的列值域
上回书说到,行值域已经得到,求列值域和九宫格值域的方法和行值域应该是一样的,但问题在于,如何表达列和九宫格,或者说如何用代码把数独里的每一列、每一个九宫格表达出来。
soduku
有一种很笨的方法:
第1列是由每一行的第1个元素组成的,用代码表示就是
soduku_col
第n列就是由每一行的第n个元素组成的,我们把上面的代码重复执行9遍就行了:
soduku_col
将代码整理为函数:
def
当然其实Python有一个现成的函数——zip(),就是做这件事情的,代码可以修改
soduku_col
我们看到zip函数里的参数是"*soduku",这个用法大家可以自行查询下,等价于下面这种写法:
soduku_col
如果参数是"soduku",相当于输入的参数是soduku,参数数量是1个; 如果参数是"*soduku",相当于将列表soduku中的每一个元素当作参数,参数数量就是9个;
求列值域,有以下几步:
- 根据当前数独数组,通过zip函数得到由每一列组成的新数独数组;
- 根据rowValueRange(行值域函数),求新数独数组的“行值域”;
- 通过zip函数将得到的“行值域数组”进行一次行列转换,从而得到原数独数组的列值域;
def
3、求每个单元格的九宫格值域
我们用了列值域的处理经验,求九宫格值域的关键就是这个“九宫格转换函数”,如果把一个数独数组,转化为数独九宫格数组,这个问题看起来有点难,我们先回顾一下数独
![424e75c8337a38d2c533ef737a14067c.png](https://img-blog.csdnimg.cn/img_convert/424e75c8337a38d2c533ef737a14067c.png)
如果表示第一个九宫格,它由前三行的前三个元素组成,如果用代码表示可以这样写:
soduku_matrix
如果我们愿意,我们可以用类似的方法得到剩余8个九宫格,但这样的代码好像有些粗暴,有更好的方法吗?我们观察数独棋盘,我们发现九宫格是以3为单位的:
第一个九宫格:前三行的前三个元素;
第二个九宫格:前三行的中间三个元素;
第三个九宫格:前三行的后三个元素;
......
我们可以加入整除操作:
soduku_matrix
那么如何建立k , l 与九宫格下标的关系呢:
k = 0, l = 0 ,下标 m = 0
k = 0, l = 1 ,下标 m = 1
k = 0, l = 2 ,下标 m = 2
k = 1, l = 0 ,下标 m = 3
k = 1, l = 1 ,下标 m = 4
k = 1, l = 2 ,下标 m = 5
k = 2, l = 0 ,下标 m = 6
k = 2, l = 1 ,下标 m = 7
k = 2, l = 2 ,下标 m = 8
m与k , l应该是一种线性关系,因此列方程:m = ak + bl,得到 m = 3k + l
所以代码可以改为:
soduku_matrix
我们整理出九宫格转换函数和九宫格值域函数:
def
数独数组a通过九宫格转化为数独数组b,然后数独数组b通过九宫格转化,可以再转化为数独数组a。这个大家可以自己观察数独棋盘体会一下。
现在我们已经获得了一个单元格的行值域、列值域和九宫格值域,可以考虑通过三个值域来获得这个单元格的总值域了。这个问题可以抽象为有lista , listb和listc,求三个列表的交集。
下面我们的项目代码将变得越来越复杂,但其实并没有引入其它复杂的概念,依然是循环、条件判断和列表相关方法,预知后事如何,且听下回分解!
下一篇链接:用Python解数独[3]:求总值域