(Python)检查数独中的3x3,有更好的方法吗?

1 投票
4 回答
1072 浏览
提问于 2025-04-18 08:25

我在高中的一个总结项目中,搭档给了我这个算法。我希望有人能告诉我有没有更简洁的写法。CB是当前的棋盘位置(全局变量),它是一个列表的列表。

for a in xrange(0, 3): 
  for b in xrange(0, 3):
    for j in xrange(1, 4): 
      for k in xrange(1, 4): 
        boxsum += CB[3a + j][3b + k] 
        if not(boxsum == 45):        
          return False               
        boxsum = 0

4 个回答

0

因为总和45并不一定意味着答案是正确的,所以需要用不同的方法来解决。个人来说,我会把这些行合并成一个单一的列表,然后和列表(1,2,...9)进行比较,比如:

#assuming this is your format...
box = [[4,2,3],[1,5,9],[8,7,6]]

def valid_box(box):
    check_list = []
    for row in box:
        check_list += row
    return list(range(1,10)) == sorted(check_list)

虽然创建这个列表的代码也可以用列表推导式来写(我不知道哪种方式在处理器上更高效)

def valid_box2(box):
    return list(range(1,10)) == sorted( [item for row in box for item in row ] )

合并列表的代码来自于 在Python中将列表的列表变成扁平列表

0

其实有很多更简单的方法来做到这一点。

首先,为什么不使用 numpy 来处理矩阵呢?因为你显然是在处理一个矩阵。我注意到你从“1”开始编号,这有点奇怪,为什么不从“0”开始呢?

import numpy as np
CB = np.array(CB)

def constraint3x3check(CB):
    return np.all(np.sum( CB[3*a+1:3*a+3, 3*b+1:3*b+3)==45 for a in range(3) for b in range(3))
0

如果说盒子里的数字加起来是45,这并不意味着里面一定有1到9的所有数字。

比如,你可以把这些数字放进一个集合里,然后检查一下这个集合的长度是不是总是9。

1

首先,下面的代码缩进不正确:

if not(boxsum == 45):        
    return False               
boxsum = 0

(按照现在的缩进方式,这段代码在第一次执行时总是会失败)

其次,在下面这一行:

boxsum += CB[3a + j][3b + k] 

你可能想要这样做:

boxsum += CB[3*a + j][3*b + k] 

最后,要检查数独游戏中的一个3x3区域,仅仅检查sum是不够的——你还需要确认1到9的每个数字都出现过(换句话说,就是确保所有数字都在1到9的范围内,并且没有数字出现超过一次)。

撰写回答