Python中的数独检查器

2024-09-24 22:33:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用python创建一个数独检查器:

ill_formed = [[5,3,4,6,7,8,9,1,2],
              [6,7,2,1,9,5,3,4,8],
              [1,9,8,3,4,2,5,6,7],
              [8,5,9,7,6,1,4,2,3],
              [4,2,6,8,5,3,7,9],  # <---
              [7,1,3,9,2,4,8,5,6],
              [9,6,1,5,3,7,2,8,4],
              [2,8,7,4,1,9,6,3,5],
              [3,4,5,2,8,6,1,7,9]]
easy = [[2,9,0,0,0,0,0,7,0],
       [3,0,6,0,0,8,4,0,0],
       [8,0,0,0,4,0,0,0,2],
       [0,2,0,0,3,1,0,0,7],
       [0,0,0,0,8,0,0,0,0],
       [1,0,0,9,5,0,0,6,0],
       [7,0,0,0,9,0,0,0,1],
       [0,0,1,2,0,0,3,0,6],
       [0,3,0,0,0,0,0,5,9]]

我期待这样的输入-一个由9个列表组成的列表。零表示用户尚未填写的数字。它们可以在一行、一列或3x3中多次出现。

def check_sudoku(grid):
if len(grid) == 9:
    numsinrow = 0
    for i in range(9):
        if len(grid[i]) == 9:
            numsinrow += 1
    if numsinrow == 9:
        for i in range(9):
            rowoccurence = [0,0,0,0,0,0,0,0,0,0]
            for j in range(9):
                rowoccurence[grid[i][j]] += 1
                temprow = rowoccurence[1:10]
                if temprow == [1,1,1,1,1,1,1,1,1]:
                    return True
                else:
                    return False
    else:
        return False
else:
    return False

显然,我需要检查是否有一个9x9列表(网格),并且在每一行、每一列和3x3小正方形中没有重复项。在代码中,我首先检查是否有适当数量的行(应该有9行)。然后我检查每一行中是否有9个元素(使用格式错误的示例,您会发现情况并非如此)。然后我试图检查每一行中的重复项,但这样做有些困难。我想我可以循环每一行,循环每一行中的元素,并将1添加到一个int列表中(rowoccurrence)。例如,如果第一个数字是2,那么rowoccurence[2]应该等于1。0在rowOccurrence[0]中,未被选中(我有一个临时列表,该列表应包含除第一个元素(零)之外的所有内容,因为一行中可能有超过1个零,并且网格仍然是合法的)。我试着对照正确值的引用列表检查临时列表(基本上是rowoccurrence),但它似乎不起作用。你能帮我检查一下这个数独检查器里的行吗?提前谢谢你!


Tags: infalse元素列表forlenreturnif
3条回答

定义一个函数来验证是否没有重复项,然后可以使用它来检查行、列和3x3网格。如果不满足某些条件(例如,行数大于9),可以通过提前返回来减少嵌套块。只有在函数的最后,如果没有一个检查失败,才返回true。

from collections import Counter

def check_dups(l):
    counts = Counter()
    for cell in l:
        if cell != 0: counts[cell] += 1
        if cell > 9 or counts[cell] > 1: return False
    return True

def check_sudoku(grid):
    if len(grid) != 9: return False
    if sum(len(row) == 9 for row in grid) != 9: return False
    for row in grid:
        if not check_dups(row): return False
    return True

你太早了,所以你没能通过你希望的考试:

            if temprow == [1,1,1,1,1,1,1,1,1]:
                return True  # <-- this is the culprit
            else:
                return False

其他注意事项:确保某个向量的所有元素都等于某个常数的一个简单方法是:

all(i == const for i in vector)

另一个更简单的方法:如果vec[1:10]都是1,那么sum(vec[1:10])必须是9。(坏主意,请参阅下面的注释。)

记住,您不是在搜索重复项--只是非零重复项。对集合求和可以解决这个问题。您还可以同时检查行/列的合法性:

def sudoku_ok(line):
    return (len(line) == 9 and sum(line) == sum(set(line)))

def check_sudoku(grid):
    bad_rows = [row for row in grid if not sudoku_ok(row)]
    grid = list(zip(*grid))
    bad_cols = [col for col in grid if not sudoku_ok(col)]
    squares = []
    for i in range(9, step=3):
        for j in range(9, step=3):
          square = list(itertools.chain(row[j:j+3] for row in grid[i:i+3]))
          squares.append(square)
    bad_squares = [square for square in squares if not sudoku_ok(square)]
    return not (bad_rows or bad_cols or bad_squares)

相关问题 更多 >