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

Posted

技术标签:

【中文标题】我的数独求解器哪里出了问题?【英文标题】:Where's the problem with my Sudoku solver? 【发布时间】:2022-01-19 21:35:12 【问题描述】:

我在这个功能上工作的时间比预期的要长,因为我不想在这里问任何问题,或者看旁边的教程。 但是,我已经到了无法找到我的功能问题的地步。就是这样:

def sudoku_solver(sudoku, sol):

    #Sudoku is solved (no 0s & correct order):
    import numpy as np
    check = np.all(sudoku)
    if check:
        sol += sudoku
        return sol


    #Number repeats in row:

    filtered_rows = []
    i = 0
    while i < 9:
        filtered_rows.append(list(filter(None, sudoku[i])))
        i += 1
    num_rows = len(filtered_rows)
    for n in range(num_rows):
        if len(filtered_rows[n]) > len(set(filtered_rows[n])):
            return None


    #Number repeats in column:

    each_col = [list(i) for i in zip(*sudoku)]
    filtered_cols = []
    i = 0
    while i < 9:
        filtered_cols.append(list(filter(None, each_col[i])))
        i += 1
    num_cols = len(filtered_cols)
    for s in range(num_cols):
        if len(filtered_cols[s]) > len(set(filtered_cols[s])):
            return None


    #Number repeats in box:

    i = 0
    all_box = []
    while i < 7:
        y = 0
        while y < 9:
            new_number = sudoku[y][i:i + 3]
            all_box += new_number
            y += 1
            if new_number == 0:
                continue
        i += 3
    each_box = [all_box[i:i + 9] for i in range(0, len(all_box), 9)]
    filtered_box = []
    i = 0
    while i < 9:
        filtered_box.append(list(filter(None, each_box[i])))
        i += 1
    num_boxes = len(filtered_box)
    for u in range(num_boxes):
        if len(filtered_box[u]) > len(set(filtered_box[u])):
            return None


    #Recursive Cases
    # Working in...
  
    while i < 9:
        y = 0
        while y < 9:
            if sudoku[i][y] == 0:
                sudoku[i][y] += 1
                sol_with_1 = sudoku_solver(sudoku, sol)
                if sol_with_1 is not None:
                    return sol_with_1
                sudoku[i][y] += 1
                sol_with_2 = sudoku_solver(sudoku, sol)
                if sol_with_2 is not None:
                    return sol_with_2
                sudoku[i][y] += 1
                sol_with_3 = sudoku_solver(sudoku, sol)
                if sol_with_3 is not None:
                    return sol_with_3
                sudoku[i][y] += 1
                sol_with_4 = sudoku_solver(sudoku, sol)
                if sol_with_4 is not None:
                    return sol_with_4
                sudoku[i][y] += 1
                sol_with_5 = sudoku_solver(sudoku, sol)
                if sol_with_5 is not None:
                    return sol_with_5
                sudoku[i][y] += 1
                sol_with_6 = sudoku_solver(sudoku, sol)
                if sol_with_6 is not None:
                    return sol_with_6
                sudoku[i][y] += 1
                sol_with_7 = sudoku_solver(sudoku, sol)
                if sol_with_7 is not None:
                    return sol_with_7
                sudoku[i][y] += 1
                sol_with_8 = sudoku_solver(sudoku, sol)
                if sol_with_8 is not None:
                    return sol_with_8
                sudoku[i][y] -= 4
                sol_with_9 = sudoku_solver(sudoku, sol)
                if sol_with_9 is not None:
                    return sol_with_9
                return None
            y += 1
        i += 1

        
    #No solution
    return "No Solution"

这不应该解决表示为这个的数独吗(0 是空格)?:

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

当我输入一个已解决的数独时,它确实有效,所以我很确定问题出在递归代码中。我也考虑过使用“import as random”来做,每次迭代都会输出一个随机数,但我猜最后一个数字的概率太低了。

【问题讨论】:

您寻求帮助的问题是什么?有错误信息吗?它只是永远运行吗?使用信息更新您的帖子。 你无法通过暴力破解数独游戏。您有 45 个空槽。这意味着有 9**45 种可能性进行测试。那是 1 后跟 43 个零。你必须使用真正的逻辑启发式。 这是一个特别好的入门方法,因为它可以使用最简单的技术来解决。对于每个单元格,计算可以到达那里的数字列表(通过剔除同一行/列/象限中的值)。然后,如果一排只有一个空位,请将其填满。我认为这几乎就是这个谜题所需的全部内容。不要猜测;所有数独都可以解析求解,尽管许多数独需要比这更复杂的技术。 您在函数 ssudoku_solver(sudoku, sol) 中作为 sol 传递的值是什么?你得到了什么输出? 【参考方案1】:

这是一个恰好解决这个数独的例子,虽然它不会解决任何困难的问题。

from pprint import pprint
unsolved_sudoku = [[1, 6, 4, 0, 0, 0, 0, 0, 2],
                   [2, 0, 0, 4, 0, 3, 9, 1, 0],
                   [0, 0, 5, 0, 8, 0, 4, 0, 7],
                   [0, 9, 0, 0, 0, 6, 5, 0, 0],
                   [5, 0, 0, 1, 0, 2, 0, 0, 8],
                   [0, 0, 8, 9, 0, 0, 0, 3, 0],
                   [8, 0, 9, 0, 4, 0, 2, 0, 0],
                   [0, 7, 3, 5, 0, 9, 0, 0, 1],
                   [4, 0, 0, 0, 0, 0, 6, 7, 9]]

all9 = set(range(1,10))

def find_possibles( grid,y, x ):
    # Add the row.
    allx = set( grid[y] )
    # Add the column.
    allx = allx.union( grid[dy][x] for dy in range(9))
    # Add the quadrant.
    x3 = (x // 3) * 3
    y3 = (y // 3) * 3
    allx = allx.union( [grid[y3+dy][x3+dx] for dy in range(3) for dx in range(3)] )
    # Return what's left.
    return all9-allx

def find_all_possibles( grid ):
    filled = 0
    for row in range(9):
        for col in range(9):
            if grid[row][col]:
                continue
            maybe = find_possibles( grid, row, col )
            if len(maybe) == 1:
                val = list(maybe)[0]
                filled += 1
                print( "Placing", val, "at", row, col )
                grid[row][col] = val
    return filled

while find_all_possibles(unsolved_sudoku):
    pprint(unsolved_sudoku)

输出:

Placing 7 at 0 3
Placing 5 at 0 5
Placing 8 at 0 7
Placing 8 at 1 1
Placing 7 at 1 2
Placing 6 at 1 4
Placing 5 at 1 8
Placing 3 at 2 1
Placing 2 at 2 3
Placing 1 at 2 5
Placing 6 at 2 7
Placing 4 at 3 8
Placing 4 at 4 1
Placing 6 at 4 2
Placing 7 at 4 6
Placing 9 at 4 7
Placing 7 at 5 0
Placing 5 at 5 4
Placing 4 at 5 5
Placing 1 at 5 6
Placing 6 at 5 8
Placing 7 at 6 5
Placing 5 at 6 7
Placing 3 at 6 8
Placing 6 at 7 0
Placing 2 at 7 4
Placing 8 at 7 6
Placing 4 at 7 7
Placing 8 at 8 5
[[1, 6, 4, 7, 0, 5, 0, 8, 2],
 [2, 8, 7, 4, 6, 3, 9, 1, 5],
 [0, 3, 5, 2, 8, 1, 4, 6, 7],
 [0, 9, 0, 0, 0, 6, 5, 0, 4],
 [5, 4, 6, 1, 0, 2, 7, 9, 8],
 [7, 0, 8, 9, 5, 4, 1, 3, 6],
 [8, 0, 9, 0, 4, 7, 2, 5, 3],
 [6, 7, 3, 5, 2, 9, 8, 4, 1],
 [4, 0, 0, 0, 0, 8, 6, 7, 9]]
Placing 9 at 0 4
Placing 3 at 0 6
Placing 9 at 2 0
Placing 3 at 3 0
Placing 8 at 3 3
Placing 7 at 3 4
Placing 2 at 3 7
Placing 3 at 4 4
Placing 2 at 5 1
Placing 1 at 6 1
Placing 6 at 6 3
Placing 5 at 8 1
Placing 2 at 8 2
Placing 3 at 8 3
Placing 1 at 8 4
[[1, 6, 4, 7, 9, 5, 3, 8, 2],
 [2, 8, 7, 4, 6, 3, 9, 1, 5],
 [9, 3, 5, 2, 8, 1, 4, 6, 7],
 [3, 9, 0, 8, 7, 6, 5, 2, 4],
 [5, 4, 6, 1, 3, 2, 7, 9, 8],
 [7, 2, 8, 9, 5, 4, 1, 3, 6],
 [8, 1, 9, 6, 4, 7, 2, 5, 3],
 [6, 7, 3, 5, 2, 9, 8, 4, 1],
 [4, 5, 2, 3, 1, 8, 6, 7, 9]]
Placing 1 at 3 2
[[1, 6, 4, 7, 9, 5, 3, 8, 2],
 [2, 8, 7, 4, 6, 3, 9, 1, 5],
 [9, 3, 5, 2, 8, 1, 4, 6, 7],
 [3, 9, 1, 8, 7, 6, 5, 2, 4],
 [5, 4, 6, 1, 3, 2, 7, 9, 8],
 [7, 2, 8, 9, 5, 4, 1, 3, 6],
 [8, 1, 9, 6, 4, 7, 2, 5, 3],
 [6, 7, 3, 5, 2, 9, 8, 4, 1],
 [4, 5, 2, 3, 1, 8, 6, 7, 9]]

【讨论】:

以上是关于我的数独求解器哪里出了问题?的主要内容,如果未能解决你的问题,请参考以下文章

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

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

Gui 可视化递归回溯数独

回溯数独求解器不起作用

python中数独的回溯算法

优化回溯算法求解数独