Python/数独求解器/方法工作不正确

Python/ Sudoku solver/ Method works incorrect

提问人:flo 提问时间:7/18/2023 最后编辑:flo 更新时间:7/18/2023 访问量:60

问:

我正在尝试在 Python 中实现数独求解器,但我的一种方法无法正常工作,尽管它非常简单且简短。我的代码中有一个(零表示框为空)和一个列表,其中包含每个框的可能数字。因此,这种有问题的方法是,一旦找到一个框,它就会简单地更改它的值,并从同一框、列和网格中的其他可能数组中删除这个特定的数字。sudoku_gridpossibility_arrayschange_value(row, column, value)

这是代码(我只放了相关的部分 - 还有其他方法只是应用不同的消除技术 - 我做了一些跟踪,发现问题出在这种方法中出于某种原因 - :

    sudoku_grid = [
        [4, 2, 9, 0, 0, 3, 0, 0, 0],
        [3, 7, 0, 1, 0, 0, 9, 0, 0],
        [0, 0, 0, 2, 9, 0, 3, 0, 0],
        [8, 3, 0, 0, 1, 0, 4, 0, 6],
        [0, 0, 0, 8, 0, 0, 7, 5, 0],
        [7, 4, 5, 9, 3, 0, 0, 1, 0],
        [9, 0, 0, 7, 0, 0, 0, 3, 1],
        [2, 5, 7, 0, 0, 0, 6, 0, 0],
        [6, 0, 3, 0, 0, 9, 8, 0, 7]
    ]
    possibility_arrays = []
    for _ in range(9):
        possibility_arrays.append([])
    for s in range(9):
        for x in range(9):
            possibility_arrays[x].append([])

    def is_valid(row, column, num):
        # Check if the number already exists in the row
        if num in sudoku_grid[row]:
            return False

        # Check if the number already exists in the column
        for i in range(9):
            if sudoku_grid[i][column] == num:
                return False

        # Check if the number already exists in the 3x3 grid
        start_row = (row // 3) * 3
        start_col = (column // 3) * 3
        for a in range(start_row, start_row + 3):
            for b in range(start_col, start_col + 3):
                if sudoku_grid[a][b] == num:
                    return False

        return True

    def change_value(row, column, value):

        if is_valid(row,column,value):
            sudoku_grid[row][column] = value
            possibility_arrays[row][column] = []

            for k in range(9):
                if value in possibility_arrays[k][column]:
                    possibility_arrays[k][column].remove(value)
                if value in possibility_arrays[row][k]:
                    possibility_arrays[row][k].remove(value)

            start_row = (row // 3) * 3
            start_col = (column // 3) * 3
            for a in range(start_row, start_row + 3):
                for b in range(start_col, start_col + 3):
                    if value in possibility_arrays[a][b]:
                        possibility_arrays[a][b].remove(value)
        else:
            print("THERE IS A MISTAKE")

以下是经过一些消除的过程:possibility_arrays

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

当我放置代码时,它只是按预期删除了 6,因为它在同一列中,但也从中删除了 6 并变成这样:change_value(5, 5, possibility_array[5][5][0])possibility_array[6][5]possibility_arrays[6][4]

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

我不知道它有时是如何不正确地工作并且工作完全正常的。正如我所说,我只在这两种状态之间放了这条线()。数组彼此之间没有关系,它们是单独的。为什么会发生这种情况?change_value(5, 5, possibility_array[5][5][0])

蟒蛇 数独

评论

0赞 BoppreH 7/18/2023
我无法重现该问题。如果我设置为您给出的示例并运行 ,则 6 不会从 .possibility_arrayschange_value(5, 5, possibility_array[5][5])possibility_array[6][5]
1赞 Michael Butscher 7/18/2023
possibility_array[5][5]是,所以和看起来不对的相同。[6]change_value(5, 5, possibility_array[5][5])change_value(5, 5, [6])
0赞 Ulrich Eckhardt 7/18/2023
您是否尝试过使用调试器单步执行代码?
0赞 flo 7/18/2023
@MichaelButscher是的,我的错,我现在编辑了我的问题。我只是在我的问题中写错了,它之前在我的代码中也以更正的方式。所以问题仍然是一样的。
1赞 BoppreH 7/18/2023
然后你真的必须提供一个显示错误的最小示例,我根本无法重现它。

答:

0赞 BoppreH 7/18/2023 #1

如果您的代码有问题,则此处不会显示。不断传播值,解决了这个难题:change_value

# Setup possibility_array with correct values for starting state.
for row in range(9):
    for col in range(9):
        possibility_arrays[row][col].extend(range(1, 10))
for row in range(9):
    for col in range(9):
        value = sudoku_grid[row][col]
        if value > 0:
            # Hacky way of propagating changes without failing the is_valid check.
            sudoku_grid[row][col] = 0
            change_value(row, col, value)

# Continuosly propagate cells with a single possibility.
progress = True
while progress:
    progress = False
    for row in range(9):
        for col in range(9):
            if len(possibility_arrays[row][col]) == 1:
                change_value(row, col, possibility_arrays[row][col][0])
                progress = True

# We either solved the puzzle, or have to guess.
from pprint import pprint
pprint(sudoku_grid)
[[4, 2, 9, 6, 7, 3, 1, 8, 5],
 [3, 7, 8, 1, 4, 5, 9, 6, 2],
 [5, 6, 1, 2, 9, 8, 3, 7, 4],
 [8, 3, 2, 5, 1, 7, 4, 9, 6],
 [1, 9, 6, 8, 2, 4, 7, 5, 3],
 [7, 4, 5, 9, 3, 6, 2, 1, 8],
 [9, 8, 4, 7, 6, 2, 5, 3, 1],
 [2, 5, 7, 3, 8, 1, 6, 4, 9],
 [6, 1, 3, 4, 5, 9, 8, 2, 7]]
1赞 flo 7/18/2023 #2

事实证明change_value方法不是问题。显然,在我实现数独求解技术(hidden_pairs)的其他方法之一中,我键入了一个代码,它只是说

possibility_arrays[i][j] = mutual_array
possibility_arrays[i][k] = mutual_array

我猜,这在某种程度上导致了问题。当我这样编辑时,问题得到了解决:

possibility_arrays[i][j] = mutual_array.copy()
possibility_arrays[i][k] = mutual_array.copy()

我认为change_value是问题所在,因为它同时删除了 2 个值,但现在我认为是数组。