列表长度检查在数独检查器中不起作用

时间:2016-09-26 11:45:27

标签: python

我想编写一些Python代码来检查矩阵是否符合Sudoku规则。我的代码如下:

correct = [[1,2,3],
           [2,3,1],
           [3,1,2]]

incorrect = [[1,2,3,4],
             [2,3,1,3],
             [3,1,2,3],
             [4,4,4,4]]

incorrect2 = [[1,2,3,4],
             [2,3,1,4],
             [4,1,2,3],
             [3,4,1,2]]

incorrect3 = [[1,2,3,4,5],
              [2,3,1,5,6],
              [4,5,2,1,3],
              [3,4,5,2,1],
              [5,6,4,3,2]]

incorrect4 = [['a','b','c'],
              ['b','c','a'],
              ['c','a','b']]

incorrect5 = [ [1, 1.5],
               [1.5, 1]]

def check_sudoku(matrix):
    n = len(matrix)
    # check each row
    i, j = 0, 0
    while i < n:
        checked = []
        while j < n:
            if matrix[i][j] not in checked:
                checked.append(matrix[i][j])
            j += 1
        if len(checked) < n:
            return False
        i += 1
    # check each column
    i, j = 0, 0
    while i < n:
        checked = []
        while j < n:
            if matrix[j][i] not in checked:
                len(checked)
                checked.append(matrix[j][i])
            j += 1
        if len(checked) < n:
            return False
        i += 1

    return True

# the output should look like this:
print(check_sudoku(incorrect))
#>>> False

print(check_sudoku(correct))
#>>> True

print(check_sudoku(incorrect2))
#>>> False

print(check_sudoku(incorrect3))
#>>> False

print(check_sudoku(incorrect4))
#>>> False

print(check_sudoku(incorrect5))
#>>> False

但这是if语句中的一个奇怪问题。在两个内部while循环之后,语句&#34; len(checked)&#34;评估为0,不应该是这样。我不知道发生了什么。

3 个答案:

答案 0 :(得分:0)

你不要在内循环(两个内循环)中归零j变量。

i, j = 0, 0
while i < n:
    checked = []
    j = 0 # you need set j to zero in each run
          # if you don't do this: j will be equal to n in second run
    while j < n:
        if matrix[i][j] not in checked:
            checked.append(matrix[i][j])
        j += 1
    if len(checked) < n:
        return False
    i += 1

您还需要检查子矩阵。

答案 1 :(得分:0)

问题是你没有正确地为两个内部while循环初始化j。这是您的代码和指示的修改,使其工作:

def check_sudoku(matrix):
    n = len(matrix)
    # check each row
#    i, j = 0, 0
    i = 0
    while i < n:
        j = 0  # added
        checked = []
        while j < n:
            if matrix[i][j] not in checked:
                checked.append(matrix[i][j])
            j += 1
        if len(checked) < n:
            return False
        i += 1
    # check each column
#    i, j = 0, 0
    i = 0
    while i < n:
        j = 0  # added
        checked = []
        while j < n:
            if matrix[j][i] not in checked:
                checked.append(matrix[j][i])
            j += 1
        if len(checked) < n:
            return False
        i += 1

    return True

答案 2 :(得分:0)

您的代码的主要问题是您不会在内部循环结束时将j重置为零。因此,当您尝试检查第二行(以及后续行)时,j值太大。当您对列进行测试时会出现同样的问题。

然而,这个逻辑存在其他问题,例如[5,6,4,3,2]测试没问题,因为它有5个独特的元素,但它们不是正确的元素,它们应该是{{1}的一些排列。 }。类似地,字符串矩阵和包含1.5的矩阵被视为有效而不是无效。

但无论如何,这是一个修复版本,修复了前面提到的[1,2,3,4,5]初始化问题。

j

<强>输出

grids = [
    [[1,2,3],
    [2,3,1],
    [3,1,2]],

    [[1,2,3,4],
    [2,3,1,3],
    [3,1,2,3],
    [4,4,4,4]],

    [[1,2,3,4],
    [2,3,1,4],
    [4,1,2,3],
    [3,4,1,2]],

    [[1,2,3,4,5],
    [2,3,1,5,6],
    [4,5,2,1,3],
    [3,4,5,2,1],
    [5,6,4,3,2]],

    [['a','b','c'],
    ['b','c','a'],
    ['c','a','b']],

    [[1, 1.5],
    [1.5, 1]],
]

def check_sudoku(matrix):
    n = len(matrix)
    # check each row
    i = 0
    while i < n:
        checked = []
        j = 0
        while j < n:
            if matrix[i][j] not in checked:
                checked.append(matrix[i][j])
            j += 1
        if len(checked) < n:
            return False
        i += 1
    # check each column
    i = 0
    while i < n:
        checked = []
        j = 0
        while j < n:
            if matrix[j][i] not in checked:
                checked.append(matrix[j][i])
            j += 1
        if len(checked) < n:
            return False
        i += 1

    return True

for g in grids:
    for row in g:
        print(row)
    print(check_sudoku(g), end='\n\n')

这是一种更紧凑,(可能)更快的替代策略,因为它使用Python的快速[1, 2, 3] [2, 3, 1] [3, 1, 2] True [1, 2, 3, 4] [2, 3, 1, 3] [3, 1, 2, 3] [4, 4, 4, 4] False [1, 2, 3, 4] [2, 3, 1, 4] [4, 1, 2, 3] [3, 4, 1, 2] False [1, 2, 3, 4, 5] [2, 3, 1, 5, 6] [4, 5, 2, 1, 3] [3, 4, 5, 2, 1] [5, 6, 4, 3, 2] True ['a', 'b', 'c'] ['b', 'c', 'a'] ['c', 'a', 'b'] True [1, 1.5] [1.5, 1] True 函数与集合来进行测试。此版本认为矩阵有效,如果它包含从1到 n 的整数,其中 n 是矩阵的大小。< / p>

all

<强>输出

grids = [
    [[1,2,3],
    [2,3,1],
    [3,1,2]],

    [[1,2,3,4],
    [2,3,1,3],
    [3,1,2,3],
    [4,4,4,4]],

    [[1,2,3,4],
    [2,3,1,4],
    [4,1,2,3],
    [3,4,1,2]],

    [[1,2,3,4,5],
    [2,3,1,5,6],
    [4,5,2,1,3],
    [3,4,5,2,1],
    [5,6,4,3,2]],

    [['a','b','c'],
    ['b','c','a'],
    ['c','a','b']],

    [[1, 1.5],
    [1.5, 1]],
]

def check_sudoku(matrix):
    full = set(range(1, len(matrix) + 1))
    return (all(set(row) == full for row in matrix)
        and all(set(row) == full for row in zip(*matrix)))

for g in grids:
    for row in g:
        print(row)
    print(check_sudoku(g), end='\n\n')

这部分:

[1, 2, 3]
[2, 3, 1]
[3, 1, 2]
True

[1, 2, 3, 4]
[2, 3, 1, 3]
[3, 1, 2, 3]
[4, 4, 4, 4]
False

[1, 2, 3, 4]
[2, 3, 1, 4]
[4, 1, 2, 3]
[3, 4, 1, 2]
False

[1, 2, 3, 4, 5]
[2, 3, 1, 5, 6]
[4, 5, 2, 1, 3]
[3, 4, 5, 2, 1]
[5, 6, 4, 3, 2]
False

['a', 'b', 'c']
['b', 'c', 'a']
['c', 'a', 'b']
False

[1, 1.5]
[1.5, 1]
False

验证列是否有效,因为all(set(row) == full for row in zip(*matrix)) 实际上创建了zip(*matrix)的转置版本。

matrix函数非常有效,一旦遇到错误的结果就会停止测试。在类似的说明中,all运算符会短路,这意味着如果行无效,则不会检查列。