matrix python 取元素_用Python解数独[2]:求列值域和九宫格值域

e7bbbf873c7f35437376909947d05c5a.png

目录

  1. 用Python解数独[0]
  2. 用Python解数独[1]:求每个单元格的行值域
  3. 用Python解数独[2]:求列值域和九宫格值域
  4. 用Python解数独[3]:求总值域
  5. 用Python解数独[4]:缩减值域
  6. 用Python解数独[5]:检测唯一值缩减值域
  7. 用Python解数独[6]:递归获得最终答案
  8. 用Python解数独[7]:递归(完结篇)

[2][1] 解决数独问题基本思路

2、求每个单元格的列值域

上回书说到,行值域已经得到,求列值域和九宫格值域的方法和行值域应该是一样的,但问题在于,如何表达列和九宫格,或者说如何用代码把数独里的每一列、每一个九宫格表达出来。

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]

有一种很笨的方法:

第1列是由每一行的第1个元素组成的,用代码表示就是

soduku_col = [[] for i in range(9)]
for i in soduku:
    soduku_col[0].append(i[0])

第n列就是由每一行的第n个元素组成的,我们把上面的代码重复执行9遍就行了:

soduku_col = [[] for i in range(9)] 
for j in range(9):
    for i in soduku:     
        soduku_col[j].append(i[j])

将代码整理为函数:

def col_invert(soduku):
    soduku_col = [[] for i in range(9)] 
    for j in range(9):
        for i in soduku:     
            soduku_col[j].append(i[j])
    return soduku_col

当然其实Python有一个现成的函数——zip(),就是做这件事情的,代码可以修改

soduku_col = list(zip(*soduku))

我们看到zip函数里的参数是"*soduku",这个用法大家可以自行查询下,等价于下面这种写法:

soduku_col = list(zip(soduku[0],soduku[1],soduku[2],soduku[3],soduku[4],soduku[5],soduku[6],soduku[7],soduku[8]))
如果参数是"soduku",相当于输入的参数是soduku,参数数量是1个; 如果参数是"*soduku",相当于将列表soduku中的每一个元素当作参数,参数数量就是9个;

求列值域,有以下几步:

  • 根据当前数独数组,通过zip函数得到由每一列组成的新数独数组;
  • 根据rowValueRange(行值域函数),求新数独数组的“行值域”;
  • 通过zip函数将得到的“行值域数组”进行一次行列转换,从而得到原数独数组的列值域;
def colValueRange(soduku):
    soduku_invert = list(zip(*soduku))
    temp = rowValueRange(soduku_invert)
    s_column_vrange = list(zip(*temp))
    return s_column_vrange

3、求每个单元格的九宫格值域

我们用了列值域的处理经验,求九宫格值域的关键就是这个“九宫格转换函数”,如果把一个数独数组,转化为数独九宫格数组,这个问题看起来有点难,我们先回顾一下数独

d09bbc1913de813e84bded52996c5b4f.png

如果表示第一个九宫格,它由前三行的前三个元素组成,如果用代码表示可以这样写:

soduku_matrix = [[] for i in range(9)]
for i in range(9):
    for j in range(9):
        if i <= 3 and j <= 3:
            soduku_matrix[0].append(soduku[i][j])

如果我们愿意,我们可以用类似的方法得到剩余8个九宫格,但这样的代码好像有些粗暴,有更好的方法吗?我们观察数独棋盘,我们发现九宫格是以3为单位的:

第一个九宫格:前三行的前三个元素;
第二个九宫格:前三行的中间三个元素;
第三个九宫格:前三行的后三个元素;
......

我们可以加入整除操作:

soduku_matrix = [[] for i in range(9)]
for i in range(9):
    for j in range(9):
        k = i//3
        l = j//3

那么如何建立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 = [[] for i in range(9)]
for i in range(9):
    for j in range(9):
        k = i//3
        l = j//3
        m = k*3 + l
        soduku_matrix[m].append(soduku[i][j])

我们整理出九宫格转换函数和九宫格值域函数:

def matrix_invert(lista):
    listb = [[] for i in range(9)]
    for i in range(9):
        for j in range(9):
            k = i//3
            l = j//3
            m = k*3 + l
            listb[m].append(soduku[i][j])
    return listb

def matrixValueRange(soduku):
    matrix = matrix_invert(soduku)
    temp = rowValueRange(matrix)
    matrix_vrange = matrix_invert(temp)
    return matrix_vrange
数独数组a通过九宫格转化为数独数组b,然后数独数组b通过九宫格转化,可以再转化为数独数组a。这个大家可以自己观察数独棋盘体会一下。

现在我们已经获得了一个单元格的行值域、列值域和九宫格值域,可以考虑通过三个值域来获得这个单元格的总值域了。这个问题可以抽象为有lista , listb和listc,求三个列表的交集。

下面我们的项目代码将变得越来越复杂,但其实并没有引入其它复杂的概念,依然是循环、条件判断和列表相关方法,预知后事如何,且听下回分解!


下一篇链接:用Python解数独[3]:求总值域

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值