利用DeepSeek将python DLX求解数独程序格式化并改成3.x版本

在网站https://blog.csdn.net/weixin_39591720/article/details/111457473上看到这个程序,但原文的缩进都丢失了,无法运行,所以让DeepSeek修改。

请将附件python程序格式化成正确缩进,并将注释翻译成中文,输出成代码格式
原程序是用python 2.7写的,现在要在3.x上用,报错,怎么修改?只要文字给出修改方法即可。不做别的

这个Python 2.7程序在Python 3.x上需要修改以下几个地方:

1. print语句改为函数

python 复制代码
# Python 2.x的print:
print self.answer
print 'no solution'

# 改为Python 3.x的print函数:
print(self.answer)
print('no solution')

2. xrange()改为range()

python 复制代码
# 将文件中所有xrange()改为range():
# xrange(self.num_columns) -> range(self.num_columns)
# xrange(self.num_cells) -> range(self.num_cells)
# xrange(self.dimension) -> range(self.dimension)
# xrange(len(ss.answer)) -> range(len(ss.answer))

3. 除法的差异

from __future__ import division 这行在Python 3中不是必须的,因为Python 3的除法默认就是浮点数除法。但保留也可以。

4. 整数除法

如果程序中需要整数除法(向下取整),Python 2中/就是整数除法,而Python 3中需要使用//

python 复制代码
# 检查是否有整数除法的地方
r = i // self.dimension  # 这个已经用了//,没问题
# 但如果有用/进行整数除法的,需要改为//

具体修改步骤:

  1. 在test.py中

    • print sudoku 改为 print(sudoku)
    • print solved 改为 print(solved)
    • xrange(len(ss.answer)) 改为 range(len(ss.answer))
  2. 在sudoku.py中

    • 将所有的 print 语句加上括号
    • 将所有 xrange() 改为 range()
    • 检查是否还有Python 2特有的语法
  3. 在类的定义中

    python 复制代码
    def run(self):
        self.construct_matrix()
        if self.dlx_search(0):
            self.compute_answer()
            print(self.answer)  # 加括号
        else:
            print('no solution')  # 加括号
  4. 在循环中

    python 复制代码
    # 将所有
    for i in xrange(self.num_columns):
    # 改为
    for i in range(self.num_columns):
    
    # 同样修改其他所有xrange

这些修改后,程序应该能在Python 3.x上正常运行。

最后的输出格式有些差。继续提示

可以了。请将for i in range(len(ss.answer)): solved.append(chr(ss.answer[i] + ord('1'))) print (solved)语句改成矩阵方式输出,不做别的

他的回答:

将这两行代码改成矩阵方式输出:

python 复制代码
# 原代码:
for i in range(len(ss.answer)):
    solved.append(chr(ss.answer[i] + ord('1')))
print(solved)

# 改为矩阵输出:
for i in range(9):
    row = []
    for j in range(9):
        row.append(chr(ss.answer[i*9 + j] + ord('1')))
    print(' '.join(row))

或者更简洁的版本:

python 复制代码
# 一行代码的矩阵输出:
for i in range(9):
    print(' '.join([chr(ss.answer[i*9 + j] + ord('1')) for j in range(9)]))

这样就以9×9的矩阵形式输出数独结果,每行9个数字,用空格分隔。

最终的程序如下

sudokusolver.py 注意文件名保留小写

python 复制代码
# sudokusolver.py
#!/usr/bin/env python
# Copyright (C) 2012 Daogan Ao
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# jul 31, 2012
from __future__ import division
import math


class Node(object):
    def __init__(self, left=None, right=None, up=None, down=None,
                 col_header=None, row_header=None):
        self.left = left or self
        self.right = right or self
        self.up = up or self
        self.down = down or self
        self.col_header = col_header
        self.row_header = row_header


class SudokuSolver(object):
    def __init__(self, sudoku):
        self.sudoku = sudoku
        self.num_cells = len(sudoku)
        self.dimension = int(math.sqrt(self.num_cells))
        self.box_size = int(math.sqrt(self.dimension))
        self.num_columns = self.dimension ** 2 * 4
        self.cell_offset = 0
        self.row_offset = self.dimension ** 2 + self.cell_offset
        self.col_offset = self.dimension ** 2 * 2 + self.cell_offset
        self.box_offset = self.dimension ** 2 * 3 + self.cell_offset
        self.col_headers = []
        self.col_size = [0] * self.num_columns
        self.partial_answer = [-1] * self.num_columns
        self.answer = [-1] * self.num_cells
        self.run()

    def run(self):
        self.construct_matrix()
        if self.dlx_search(0):
            self.compute_answer()
            print(self.answer)
        else:
            print('no solution')

    def construct_matrix(self):
        self.root = Node()
        # 构建列头节点
        for i in range(self.num_columns):
            new_col_header = Node(left=self.root.left, right=self.root)
            self.root.left.right = new_col_header
            self.root.left = new_col_header
            new_col_header.col_header = i
            new_col_header.row_header = 0
            self.col_headers.append(new_col_header)

        for i in range(self.num_cells):
            r = i // self.dimension
            c = i % self.dimension
            # 负数(如-1)表示空单元格
            if self.sudoku[i] < 0:
                # 用所有可能的值填充此空单元格
                for value in range(self.dimension):
                    self.insert_value(r, c, value)
            # 正数表示单元格已填充了一个值
            else:
                self.insert_value(r, c, self.sudoku[i])

    def insert_value(self, row, col, value):
        # 约束1:每个单元格必须填一个数字
        cell_idx = row * self.dimension + col + self.cell_offset
        # 约束2:每行必须恰好包含每个数字一次
        row_idx = row * self.dimension + value + self.row_offset
        # 约束3:每列必须恰好包含每个数字一次
        col_idx = col * self.dimension + value + self.col_offset
        # 约束4:每个宫必须恰好包含每个数字一次
        box_idx = ((row // self.box_size) * self.box_size + (col // self.box_size)) * self.dimension + value + self.box_offset
        # 映射到矩阵的垂直行索引
        vertical_row_idx = ((row * self.dimension + col) * self.dimension + value + self.cell_offset)
        self.add_row(vertical_row_idx, cell_idx, row_idx, col_idx, box_idx)

    def add_row(self, row, col1, col2, col3, col4):
        self.col_size[col1] += 1
        col_header_node = self.col_headers[col1]
        # 添加新节点到 [row, col1]
        row_first_node = Node(up=col_header_node.up,
                              down=col_header_node,
                              col_header=col1,
                              row_header=row)
        # 放置在列col1的垂直底部
        col_header_node.up.down = row_first_node
        col_header_node.up = row_first_node

        # 为其余列添加新节点
        for col in [col2, col3, col4]:
            self.col_size[col] += 1
            col_header_node = self.col_headers[col]
            new_node = Node(left=row_first_node.left,
                            right=row_first_node,
                            up=col_header_node.up,
                            down=col_header_node,
                            col_header=col,
                            row_header=row)
            # 放置在行的水平尾部
            row_first_node.left.right = new_node
            row_first_node.left = new_node
            # 放置在列的垂直底部
            col_header_node.up.down = new_node
            col_header_node.up = new_node

    def dlx_search(self, level):
        # 所有列都已被移除,成功
        if self.root.right == self.root:
            return True

        min_size = 0xfffffff
        j = self.root.right
        # 选择包含最少节点的列j
        while j != self.root:
            if self.col_size[j.col_header] < min_size:
                min_size = self.col_size[j.col_header]
                column_header = j
            j = j.right

        # 覆盖此列
        self.cover(column_header)
        node_down = column_header.down
        # 直到节点回到原始位置(垂直方向)时停止
        while node_down != column_header:
            # 记录可能的答案
            self.partial_answer[level] = node_down.row_header
            node_right = node_down.right
            # 移除行,直到节点回到原始位置(水平方向)
            while node_right != node_down:
                # 覆盖此节点对应的列
                self.cover(self.col_headers[node_right.col_header])
                node_right = node_right.right

            # 在之前的移除后,继续到下一层
            if self.dlx_search(level + 1):
                return True

            # 之前的cover()失败,恢复状态
            node_left = node_down.left
            while node_left != node_down:
                self.uncover(self.col_headers[node_left.col_header])
                node_left = node_left.left
            node_down = node_down.down

        # 之前的cover()失败,恢复原始状态
        self.uncover(column_header)

    def cover(self, column_header):
        # 移除此列
        column_header.left.right = column_header.right
        column_header.right.left = column_header.left
        node_down = column_header.down
        # 垂直向下移动节点
        while node_down != column_header:
            node_right = node_down.right
            # 垂直移除此行
            while node_right != node_down:
                node_right.down.up = node_right.up
                node_right.up.down = node_right.down
                # 减少对应列的节点数计数器
                self.col_size[node_right.col_header] -= 1
                # 移动到右侧的下一个节点
                node_right = node_right.right
            # 移动到下方的下一个节点
            node_down = node_down.down

    def uncover(self, column_header):
        # 恢复此列
        column_header.right.left = column_header
        column_header.left.right = column_header
        node_up = column_header.up
        # 垂直向上移动节点
        while node_up != column_header:
            node_left = node_up.left
            while node_left != node_up:
                # 垂直恢复此行
                node_left.down.up = node_left
                node_left.up.down = node_left
                # 增加对应列的节点数计数器
                self.col_size[node_left.col_header] += 1
                # 移动到左侧的节点
                node_left = node_left.left
            # 移动到上方的节点
            node_up = node_up.up

    def compute_answer(self):
        # 将所选行索引的值映射到单元格的值
        for value_row_index in self.partial_answer:
            if value_row_index < 0:
                return
            t = value_row_index - self.cell_offset
            row = t // (self.dimension ** 2)
            col = (t // self.dimension) % self.dimension
            value = t % self.dimension
            self.answer[row * self.dimension + col] = value

test.py

python 复制代码
# 测试程序 test.py
import sudokusolver

sudoku = []
solved = []
# s="000070508090008300510020000800000000045060980000000004000090056001400070407050000"
s = "081600090000000000004037600600400500030000070007002004005210300000000000070004810"

for i in range(81):
    if s[i] != '0':
        sudoku.append(ord(s[i]) - ord('1'))
    else:
        sudoku.append(-1)
print (sudoku)

ss = sudokusolver.SudokuSolver(sudoku)

for i in range(9):
    print(' '.join([chr(ss.answer[i*9 + j] + ord('1')) for j in range(9)]))

执行结果如下

复制代码
C:\d>python test.py
[-1, 7, 0, 5, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, 2, 6, 5, -1, -1, 5, -1, -1, 3, -1, -1, 4, -1, -1, -1, 2, -1, -1, -1, -1, -1, 6, -1, -1, -1, 6, -1, -1, 1, -1, -1, 3, -1, -1, 4, 1, 0, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, 3, 7, 0, -1]
[1, 7, 0, 5, 3, 4, 6, 8, 2, 6, 5, 2, 8, 1, 7, 0, 3, 4, 4, 8, 3, 0, 2, 6, 5, 1, 7, 5, 1, 8, 3, 6, 2, 4, 7, 0, 3, 2, 7, 4, 8, 0, 1, 6, 5, 0, 4, 6, 7, 5, 1, 8, 2, 3, 7, 3, 4, 1, 0, 8, 2, 5, 6, 2, 0, 1, 6, 7, 5, 3, 4, 8, 8, 6, 5, 2, 4, 3, 7, 0, 1]
2 8 1 6 4 5 7 9 3
7 6 3 9 2 8 1 4 5
5 9 4 1 3 7 6 2 8
6 2 9 4 7 3 5 8 1
4 3 8 5 9 1 2 7 6
1 5 7 8 6 2 9 3 4
8 4 5 2 1 9 3 6 7
3 1 2 7 8 6 4 5 9
9 7 6 3 5 4 8 1 2
相关推荐
浩瀚地学2 小时前
【Java】JDK8的一些新特性
java·开发语言·经验分享·笔记·学习
jllllyuz2 小时前
基于子集模拟的系统与静态可靠性分析及Matlab优化算法实现
算法·matlab·概率论
程序员-King.2 小时前
day143—递归—对称二叉树(LeetCode-101)
数据结构·算法·leetcode·二叉树·递归
BlockChain8882 小时前
字符串最后一个单词的长度
算法·go
爱吃泡芙的小白白2 小时前
深入解析:2024年AI大模型核心算法与应用全景
人工智能·算法·大模型算法
阿崽meitoufa3 小时前
JVM虚拟机:垃圾收集器和判断对象是否存活的算法
java·jvm·算法
yugi9878383 小时前
基于遗传算法优化主动悬架模糊控制的Matlab实现
开发语言·matlab
moxiaoran57533 小时前
Go语言的错误处理
开发语言·后端·golang
ballball~~4 小时前
拉普拉斯金字塔
算法·机器学习