这是一个数独求解程序。我遇到了递归错误。我导入了 sys 模块并将递归限制设置为 1500,但仍然显示错误

Posted

技术标签:

【中文标题】这是一个数独求解程序。我遇到了递归错误。我导入了 sys 模块并将递归限制设置为 1500,但仍然显示错误【英文标题】:This is a sudoku solving program.I got recursive errors.I imported sys module and set the recursion limit to 1500,but still it shows errors 【发布时间】:2020-01-11 03:59:18 【问题描述】:
import sys
sys.setrecursionlimit(1500)  # the default recursion limit is 1000


def print_grid(arr):
    for i in range(9):
        for j in range(9):
            print(arr[i][j])
    print('\n')


def find_empty_location(arr, l):
    for i in range(9):
        for j in range(9):
            if (arr[i][j] == 0):
                l[0] = i
                l[1] = j
                return True

    return False


def row_check(arr, row, num):
    for x in range(9):
        if arr[row][x] == num:
            return True

    return False


def col_check(arr, col, num):
    for i in range(9):
        if arr[i][col] == num:
            return True

    return False


def used_in_box(arr, row, col, num):
    for i in range(3):
        for j in range(3):
            if (arr[i + row][j + col] == num):
                return True

    return False


def check_location_is_safe(arr, row, col, num):
    return not row_check(arr, row, num) and not col_check(arr, col, num) and not used_in_box(arr, row - row % 3, col - col % 3, num)


def solve_sudoku(arr):
    l = [0, 0]
    if (not find_empty_location(arr, l)):
        return True

    row = l[0]
    col = l[1]

    for num in range(1, 10):
        if check_location_is_safe(arr, row, col, num):
            arr[row][col] == num

        if solve_sudoku(arr):
            return True

        else:
            arr[row][col] = 0
            return False


if __name__ == "__main__":
    grid = [[0 for x in range(9)] for y in range(9)]

    grid = [[3, 0, 6, 5, 0, 8, 4, 0, 0],
            [5, 2, 0, 0, 0, 0, 0, 0, 0],
            [0, 8, 7, 0, 0, 0, 0, 3, 1],
            [0, 0, 3, 0, 1, 0, 0, 8, 0],
            [9, 0, 0, 8, 6, 3, 0, 0, 5],
            [0, 5, 0, 0, 9, 0, 6, 0, 0],
            [1, 3, 0, 0, 0, 0, 2, 5, 0],
            [0, 0, 0, 0, 0, 0, 0, 7, 4],
            [0, 0, 5, 2, 0, 6, 3, 0, 0]]
    if (solve_sudoku(grid)):
        print_grid(grid)

    else:
        print('NO SOLUTION EXISTS')

【问题讨论】:

什么错误?请edit 发布完整的 Traceback。 【参考方案1】:

在查看代码之前,您应该已经意识到,在正确的解决方案中,递归深度绝不应该大于数独网格中空单元格的数量。因此,如果递归比这更深,它应该敲响警钟,您实际上有一个错误,使您的代码递归无限。增加递归限制是错误的反应。

相反,您应该调试并查看实际发生的情况。在这种情况下,我倾向于将depth=0 参数添加到递归函数(默认值为0)。然后确保递归调用传递值depth+1。在函数中添加if depth > 5: raise ValueError("stop") 以确保它不会经常运行。最后添加一些print 语句来检查你的网格是什么样的,选择了哪些行/列,......等等。你很快就会发现有什么地方出了大问题……

现在看代码:solve_sudoku 函数中存在以下问题:

arr[row][col] == num 不是赋值,而是比较。所以你实际上永远不会改变网格。

即使进行了上述更正,当check_location_is_safe 返回False 时,您仍然可以继续递归而不更改网格。所以下面几行应该缩进更多,所以它们属于上面的if块:

if solve_sudoku(arr):
     return True
else:
     arr[row][col] = 0
     # return False <--- not here (cf. previous issue)

注意:由于在if 的情况下您退出了函数,实际上并没有真正需要在else 中包含arr[row][col] = 0。所以很可能是:

if solve_sudoku(arr):
     return True
arr[row][col] = 0
return False 不应该在 for 循环内,因为您仍然希望在循环的下一次迭代中验证替代“移动”。 return False 应该在循环结束后执行

因此,将这些更正放在一起:solve_sudoku 的后半部分应如下所示:

for num in range(1, 10):
    if check_location_is_safe(arr, row, col, num):
        arr[row][col] = num
        if solve_sudoku(arr):
            return True
        arr[row][col] = 0
return False

【讨论】:

以上是关于这是一个数独求解程序。我遇到了递归错误。我导入了 sys 模块并将递归限制设置为 1500,但仍然显示错误的主要内容,如果未能解决你的问题,请参考以下文章

数独游戏求解程序

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

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

中止陷阱错误:6 - 它来自哪里? - 数独求解器

为啥这个“数独求解器”算法不起作用

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