为啥这个数独求解器返回相同的板而不解决任何问题?

Posted

技术标签:

【中文标题】为啥这个数独求解器返回相同的板而不解决任何问题?【英文标题】:Why this sudoku solver return same board without solving anything?为什么这个数独求解器返回相同的板而不解决任何问题? 【发布时间】:2020-12-05 16:08:26 【问题描述】:

我正在尝试编写一个简单的 python 数独求解器,它实现了回溯,这似乎根本不起作用,并且不能解决任何我不知道为什么的问题。 The Puzzle 应该有一个解决方案,我猜问题出在回溯机制上,但我完全不确定为什么会发生这种行为。

matric =[
    [7,8,0,4,0,0,1,2,0],
    [6,0,0,0,7,5,0,0,9],
    [0,0,0,6,0,1,0,7,8],
    [0,0,7,0,4,0,2,6,0],
    [0,0,1,0,5,0,9,3,0],
    [9,0,4,0,6,0,0,0,5],
    [0,7,0,3,0,0,0,1,2],
    [1,2,0,0,0,7,4,0,0],
    [0,4,9,2,0,6,0,0,7]
]

def is_possible(y: int, x: int, n: int) -> bool:

        # check row and column
    for i in range(9):
        if matric[y][i] == n:
            return False

    for i in range(9):
        if matric[i][x] == n:
            return False
    # check box
    new_x = x // 3 * 3
    new_y = y // 3 * 3
    for i in range(3):
        for j in range(3):
            if matric[new_y + i][new_x + j] == n:
                return False
    return True

def solve():
    global matric
    # Find a point
    for y in range(9):
        for x in range(9):
            if matric[y][x] == 0:   # found a point to solve
                for n in range(1, 10):   # Check numbers
                    if is_possible(y, x, n):
                        matric[y][x] = n
                        solve()         # Solve Next Point
                        matric[y][x] = 0    # Back track
                return
solve()
for x in matric:
    print(x)

【问题讨论】:

据我所知,solve() 最后只是将matric 的所有元素设置回0?! @mkrieger1 这也是我的想法,我想解决方案会到达某个点,它找不到可能的数字,所以它回溯但似乎找不到另一个解决方案,所以一直回溯直到重新开始。但是当这个难题有解决方案时,我不明白为什么会发生这种情况。 【参考方案1】:

您的代码总是回溯,即使找到了解决方案。您的代码中没有任何内容显示“嘿,我找到了解决方案,让我们停止进一步寻找”。因此,在扫描完所有可能性之后,您最终会得到一个完整的回溯矩阵。这段代码无能为力:它回溯并将所有内容设置为零。没有if solved: announce the solution

你能做什么

solve 返回一个布尔值:当它发现矩阵已满时,它应该返回True。如果递归调用返回True,则不要清除任何单元格!相反,立即返回True。这样,您将快速回溯出递归树,而无需更改矩阵中的任何内容。然后,原始调用者将找到仍然完好的解决方案的矩阵。

所以:

def solve():
    global matric
    for y in range(9):
        for x in range(9):
            if matric[y][x] == 0:
                for n in range(1, 10):
                    if is_possible(y, x, n):
                        matric[y][x] = n
                        if solve():  # Did we find a solution?
                            return True  # Yes! Tell the caller!
                        matric[y][x] = 0  # Back track
                return False  # No way to fill this cell with a valid value
    return True  # Found no free cell, so this is a solved puzzle!

请注意,尽管此算法可能会解决一些谜题,但它会在更难的谜题上花费太多时间。为了解决更难的谜题,您需要添加和维护更多的数据结构,以了解哪些值仍可用于单元格中,哪些值仍需要在行、列或块中找到位置。这将比您必须像现在在 is_possible 中那样验证放置的值时提供更快的结果。

【讨论】:

您是否有证据支持您的说法,即它会在更难的谜题上花费太多时间?上次我编写数独求解器时,我的结论是,对于 9x9 网格,即使是最简单的回溯求解器也足够快(我说的足够快是指实际解决难题所花费的时间与从txt 文件)。当然,这是一个递归函数,python 在递归方面是出了名的糟糕。 @Stef,试试mysudoku.com/game-sudoku/extremely-difficult_ga.html

以上是关于为啥这个数独求解器返回相同的板而不解决任何问题?的主要内容,如果未能解决你的问题,请参考以下文章

具有回溯的数独求解器不能总是检测到多个解决方案

数独求解器回溯算法不起作用

Java中的数独求解器,使用回溯和递归

我的数独求解器哪里出了问题?

回溯数独求解器不起作用

无法回溯以使用递归 javascript 数独求解器