python插补值用临近值_用Python解数独[5]:检测唯一值缩减值域

v2-4ff3f6235f89d6bb47ea8f112b7790b2_1440w.jpg?source=172ae18b

目录

  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] 解决数独问题基本思路

6、检测唯一值缩减值域

我们执行代码后,并没有得到最终答案,确切的说,离最终答案还远得很...

PS D:python0624-soduku> python zhihutest.py
[[5, 6, 7], [1], [4], [5, 7, 8], [9], [5, 6, 8], [3], [2], [7, 8]]
[[6, 7, 9], [2, 7, 9], [2, 6, 7, 9], [1, 7, 8], [3], [1, 4, 6, 8], [1, 4, 9], [1, 4, 7, 8, 9], [5]]
[[3], [8], [7, 9], [1, 5, 7], [1, 4, 5, 7], [2], [1, 4, 9], [6], [1, 4, 7]]
[[8], [4], [3, 7, 9], [6], [1, 5], [1, 3, 5], [1, 5, 9], [1, 3, 9], [2]]
[[1], [3, 9], [5], [2], [4, 8], [3, 4, 8], [7], [3, 4, 9], [3, 4, 6]]
[[6, 9], [2, 3, 9], [2, 3, 6, 9], [1, 3, 5, 9], [1, 4, 5], [7], [8], [1, 3, 4, 9], [1, 3, 4, 6]]
[[2], [3, 5, 7], [1, 3, 7, 8], [4], [1, 5, 6, 7, 8], [1, 3, 5, 6, 8], [1, 6], [1, 3, 7, 8], [9]]
[[4, 7], [6], [1, 3, 7, 8], [1, 3, 7, 8], [1, 2, 7, 8], [9], [1, 2, 4], [5], [1, 3, 4, 7, 8]]
[[4, 5, 7, 9], [3, 5, 7, 9], [1, 3, 7, 8, 9], [1, 3, 5, 7, 8], [1, 2, 5, 6, 7, 8], [1, 3, 5, 6, 8], [1, 2, 4, 6], [1, 3, 4, 7, 8], [1, 3, 4, 6, 7, 8]]
代码执行完毕,用时0.0秒

15740945adf90b522de24415452f08a7.png

经过一番操作,我们实际上只得到了一个解(第1行第7列),那么我们现在需要思考在现有条件下,还能进一步缩减值域,从而获得新的解吗?

答案是有的!请关注第4行和第7列:

  • 第4行,我们发现5个未确定的单元格,只有第3个单元格里有值7,那么我们可以确定,第4行第3列的值就是7!!!
  • 第7列,我们发现6个未确定的单元格,只有第3个单元格里有值5,那么我们可以确定,第4行第7列的值就是5!!!

下面我们要做的事情就是把这个“发现”转化为代码,我们先把场景限定为在一行中找“唯一值”:

# 寻找一行中唯一的值,若该值仅在行值域列表中出现了一次,则其所在单元格取值为该值
def checkUnique(list):
    listb = copy.deepcopy(list)
    templist = []
    for i in listb:
        templist.extend(i)
    for i in range(len(list)):
        for j in list[i]:
            if templist.count(j) == 1:
                listb[i] = [j]
    list = listb
    return list

这段代码的含义就是:

  • 先创建一个list的拷贝listb,然后把listb里每一个子列表合并为一个大列表templist
  • 然后去看list子列表中的每一个值,在templist中是否唯一,如果唯一就修改listb中的值
  • 最终将listb的值赋给list,返回list

很容易,我们可以得到寻找每一行唯一值的方法:

# 寻找每一行的唯一值,更新值域列表
def row_checkUnique(s_row_vrange):
    temp = []
    for list in s_row_vrange:
        temp.append(checkUnique(list))
    s_row_vrange = temp
    return s_row_vrange

得到了每一行的方法,每一列和每一个九宫格的方法也就出来了

# 检查值域列表每一行、每一列、每一个九宫格的值域,并寻找唯一值,更新值域列表
def soduku_checkUnique(s_row_vrange):
    temp = []
    temp_b = []
    s_row_vrange = row_checkUnique(s_row_vrange)
    for i in list(zip(*s_row_vrange)):# 将数独进行行列转换,然后对每一列进行唯一值检测
        temp.append(list(i))
    temp = row_checkUnique(temp)
    for i in list(zip(*temp)):
        temp_b.append(list(i))
    temp_c = matrix_invert(temp_b)# 将数独进行九宫格转换,然后对每一九宫格进行唯一值检测
    temp_c = row_checkUnique(temp_c)
    temp_d = matrix_invert(temp_c)
    return temp_d

考虑到检测出唯一值后,单元格的值域肯定会发生变化,因此我们需要对原来的值域列表缩减函数进行一次改造,在获得数独总值域后,立即进行唯一值检测,然后再把值域列表转化为新的数独题目,不断进行循环:

# 值域列表缩减函数:将值域列表转化为数独题目,求新的数独题目的值域列表,如此反复
def reduce_totalValueRange(soduku):
    for n in range(100):
        total_value_range = totalValueRange(soduku)
        total_value_range = soduku_checkUnique(total_value_range)
        soduku = generator_soduku(total_value_range)
        if total_value_range == totalValueRange(generator_soduku(total_value_range)):
            break
    return total_value_range

我们运行代码,看一下能否得到最终答案:

PS D:python0624-soduku> python zhihutest2.py
[[5], [1], [4], [7, 8], [9], [6], [3], [2], [7, 8]]
[[7], [2], [6], [1, 8], [3], [1, 4, 8], [9], [1, 4, 8], [5]]
[[3], [8], [9], [5], [4, 7], [2], [1, 4], [6], [1, 4, 7]]
[[8], [4], [7], [6], [1], [3], [5], [9], [2]]
[[1], [9], [5], [2], [4, 8], [4, 8], [7], [3], [6]]
[[6], [3], [2], [9], [5], [7], [8], [1, 4], [1, 4]]
[[2], [5, 7], [3], [4], [6, 7, 8], [1, 5, 8], [1, 6], [1, 7, 8], [9]]
[[4], [6], [1, 8], [1, 3, 7, 8], [2, 7, 8], [9], [1, 2], [5], [1, 3, 7, 8]]
[[9], [5, 7], [1, 8], [1, 3, 7, 8], [2, 6, 7, 8], [1, 5, 8], [1, 2, 4, 6], [1, 4, 7, 8], [1, 3, 4, 7, 8]]
代码执行完毕,用时0.02秒

51e462722fcb32d5cec18838674a373b.png

相比于一开始,我们的确有了很大的进步,从1个确认答案,到25个确认答案。但不同于“入门”级别的数独,对于这个“初级”难度的数独,我们依然没有得到最终的答案,那么我们还需要怎么做才能得到最终答案呢?

预知后事如何,且听下回分解。


下一篇链接:用Python解数独[6]:递归获得最终答案

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值