Python递归Sudoku解算器未返回解决方案

时间:2020-09-10 00:18:47

标签: python numpy sudoku

我尝试优化https://airflow.apache.org/docs/stable/kubernetes.html代码,最终代码如下所示

def load_users_into_table(postgres_hook, schema, path):
  gdf = read_csv(path)
  gdf.to_sql('users', con=postgres_hook.get_sqlalchemy_engine(), schema=schema)

我的问题是,即使如下所示成功打印了解决方案,变量 solved 也只是一个NoneType而没有存储任何内容。

_pg_hook = PostgresHook(postgres_conn_id = _conn_id)

with dag: 
test = KubernetesPodOperator(
        namespace=namespace,
        image=image_name,
        cmds=["python", "-c"],
        arguments=[load_users_into_table],
        labels={"dag-id": dag.dag_id},
        name="airflow-test-pod",
        task_id="task-1",
        is_delete_operator_pod=True,
        in_cluster=in_cluster,
        get_logs=True,
        config_file=config_file,
        executor_config={
            "KubernetesExecutor": {"request_memory": "512Mi",
                                   "limit_memory": "1024Mi",
                                   "request_cpu": "1",
                                   "limit_cpu": "2"}
        }
    )

this函数将打印解决方案,但不返回任何内容。我该怎么办才能存储打印的解决方案?

5 个答案:

答案 0 :(得分:0)

问题在您的代码中

                    solve_sudoku(sudoku)
                    sudoku[row, col] = 0
            return

在第一行中,您会重复执行,但是忽略了返回值,该返回值会丢弃该调用及其下的所有递归的所有返回值。

在最后一行,您在None上返回默认值。这两种方法都会破坏您递归返回值的连续性。

答案 1 :(得分:0)

使用完全填充的数独数组(其中一个没有任何零)的print(sudoku)调用时,发生solve_sudoku调用,而不是在顶级递归调用中。

每次用不完整的数独数组调用solve_sudoku时,您正在测试最左上角填充零的单元格中介于1到10之间的每个数字,如果该数字可以放置在该单元格中,则放置在那里尝试解决网格的其余部分,然后将单元格设置回零。对介于1到10之间的每个数字执行此操作后,将返回None,这就是为什么您看到顶级None调用返回了solve_sudoku的原因。

答案 2 :(得分:0)

几个小时后,我想到了这个解决方案。 已解决立即存储解决方案。

import numpy as np
sudoku = np.array([[0, 9, 0, 0, 5, 0, 6, 0, 8],
                   [0, 0, 0, 7, 1, 0, 3, 5, 0],
                   [2, 1, 0, 0, 0, 0, 7, 0, 4],
                   [0, 0, 1, 5, 0, 0, 0, 0, 6],
                   [6, 3, 0, 2, 0, 8, 0, 4, 5],
                   [7, 0, 0, 0, 0, 4, 9, 0, 0],
                   [9, 0, 3, 0, 0, 0, 0, 2, 1],
                   [0, 4, 8, 0, 2, 7, 0, 0, 0],
                   [5, 0, 6, 0, 8, 0, 0, 3, 0]])
solved = np.zeros_like(sudoku)

def check(arg, row, col, n):
    if np.sum(arg[row,:] == n) != 0: return False;
    if np.sum(arg[:,col] == n) != 0: return False;
    row0, col0 = (row//3)*3, (col//3)*3
    if np.sum(arg[row0:row0+3,col0:col0+3] == n) != 0: return False;
    return True

def solve_sudoku(arg):
    global solved
    rows, cols = np.where(arg == 0)
    for row in rows:
        for col in cols:
            for num in range(1, 10):
                if check(arg, row, col, num):
                    arg[row, col] = num
                    solve_sudoku(arg)
                    arg[row, col] = 0
            return
    solved = arg.copy()
solve_sudoku(sudoku)

我不知道这是否是优化代码的最佳方法,欢迎反馈。

答案 3 :(得分:0)

def check(grid, num, x, y):
    for i in range(9):
        if grid[i][y] == num:
            return False
    for j in range(9):
        if grid[x][j] == num:
            return False
    x0 = (x//3) * 3
    y0 = (y//3) * 3
    for i in range(3):
        for j in range(3):
            if grid[x0+i][y0+j] == num:
                return False
    return True

def solve(grid):
    for i in range(9 + 1):
        if i==9:
            return True
        for j in range(9):
            if grid[i][j] == 0:
                for num in range(1,10):
                    if check(grid, num, i, j):
                        grid[i][j] = num
                        if solve(grid):
                            return True
                        grid[i][j] = 0
                return False

这应该为您工作。它不返回数组而是对其进行修改。因此,如果您通过

solve(sudoku_grid) 

然后打印sudoku_grid,它将为您提供已解决的输出

答案 4 :(得分:0)

if check(sudoku, row, col, num):
                sudoku[row, col] = num
                solve_sudoku(sudoku)
                sudoku[row, col] = 0

在某个周期“solve_sudoku(sudoku)”会得到解。当你得到你的解决方案时,你应该立即通过返回或打破循环来停止回溯。否则,下一行“sudoku[row, col] = 0”将取消您之前的尝试并继续检查下一个可能的数字。由于数独只有一个解决方案,因此没有必要继续检查下一个数字。您可以只返回一个真值来结束循环。例如,您可以这样编码 如果 solve_sudoku(sudoku)==True: 返回真