利用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
相关推荐
@大迁世界6 分钟前
6 款轻量级 CLI 工具,取代了我臃肿的开发软件
开发语言·lua
handler018 分钟前
算法:Trie树(字典树)
c语言·数据结构·c++·笔记·算法·深度优先
ZPC821010 分钟前
PPO (Proximal Policy Optimization) 算法模块详细拆解
人工智能·pytorch·算法·机器人
阿Y加油吧13 分钟前
力扣打卡day06——滑动窗口最大值、最小覆盖子串
数据结构·算法·leetcode
沉鱼.4414 分钟前
日期题目集
数据结构·算法
MegaDataFlowers15 分钟前
依赖注入(DI)
java·开发语言
csbysj202017 分钟前
Foundation 输入框尺寸指南
开发语言
wertyuytrewm18 分钟前
用Python实现自动化的Web测试(Selenium)
jvm·数据库·python
码云数智-园园18 分钟前
Tailwind CSS vs. 传统CSS/Sass:2026年前端样式开发的深度博弈
开发语言
lly20240621 分钟前
《jEasyUI 创建 XP 风格左侧面板》
开发语言