返回顶部
首页 > 资讯 > 后端开发 > Python >使用Python进行数独求解详解(一)
  • 793
分享到

使用Python进行数独求解详解(一)

2024-04-02 19:04:59 793人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录1.引言2.描述数独九宫格3.寻找下一个空子单元格4.子单元格中设置值的合法性5.实现回溯算法6.性能表现7.总结1. 引言 本文为介绍流行的数独游戏的系列文章中的第一篇。更具体

1. 引言

本文为介绍流行的数独游戏的系列文章中的第一篇。更具体地说,我们如何构建一个脚本来解决数独难题,本文的重点在于介绍用于构建数独求解器的回溯算法。

数独这个名字的由来来自日语短语suuji wa dokushin ni kagiru,意思是“数字必须保持单一”。数独游戏的流行也源于其规则的简单性:数独游戏要求在 9 x 9 空间的网格上进行数字填写。在行和列中有 9 个“正方形”的格子block(由 3 x 3 个子单元格cell组成)。每一行、每一列、每一个block都需要填写数字 1-9,行、列、block内不得重复任何数字。

好的,知道了上述数独的规则,那么我们就来直接进入主体吧。 :)

2.描述数独九宫格

这一步主要为使用一组数字来初始化我们的九宫格。我们使用setBoard() 函数将输入转换为适合我们后续操作的数据类型。我们使用以下约定:

  • 空的单元格cell初始化为默认值0。
  • 维持数独谜题数字值的数据类型是一个 9x9 大小的二维列表。

这里我们的输入是一个多行字符串,我们将其处理成二维列表的形式。样例代码如下:

# Initialize a 2-D list with initial values described by the problem. 
# Returns board
def setBoard():
    board = list()
    sudokuBoard = '''
    200080300
	060070084
	030500209
	000105408
	000000000
	402706000
	301007040
	720040060
	004010003
	'''
    rows = sudokuBoard.split('\n')
    for row in rows:
        column = list()
        for character in row:
            digit = int(character)
            column.append(digit)
        board.append(column)
    return board

上述代码运行后,如果展示在拼图游戏中,他的样子大概如下:

3.寻找下一个空子单元格

函数findEmpty() 函数的操作更加简单:对初始化后的九宫格作为参数传递,然后该遍历该九宫格中每一个子单元格cell,直到找到返回的第一个空的子单元格。如果没有找到空的子单元格,这表明我们的问题已解决,因此它返回None。

样例代码如下:

# Find next empty space in Sudoku board and return dimensions
def findEmpty(board):
    for row in range(9):
        for col in range(9):
            if board[row][col] == 0 :
                return row,col
    return None

4. 子单元格中设置值的合法性

函数isValid()的操作是确认设定的数字是否是九宫格子单元格的有效选项。为了使设置的值满足数独九宫格的要求,该值的设置需满足以下条件:

  • 同一行的任何子单元格cell都不应包含该数字
  • 同一列的任何子单元格cell都不应包含该数字
  • 该子单元格cell所在的block不应该包含该数字

如果我们设定的值满足以上所有条件,该函数返回True,否则返回False。代码如下:

# Check whether a specific number can be used for specific dimensions
def isValid(board, num, pos):
    row, col = pos
    # Check if all row elements include this number
    for j in range(9):
        if board[row][j] == num:
            return False
    # Check if all column elements include this number
    for i in range(9):
        if board[i][col] == num:
            return False
    # Check if the number is already included in the block
    rowBlockStart = 3* (row // 3)
    colBlockStart = 3* (col // 3)

    rowBlockEnd = rowBlockStart + 3
    colBlockEnd = colBlockStart + 3
    for i in range(rowBlockStart, rowBlockEnd):
        for j in range(colBlockStart, colBlockEnd):
            if board[i][j] == num:
                return False

    return True

以下是通过isValid() 函数中描述的条件后成功插入新值的动态示例:

同时,若我们引入一个与九宫格数独上已经存在的值冲突的数值,那么此时该值将不会被插入。图例如下:

5. 实现回溯算法

下一个函数是我们整个解决方案的核心思想,这里引入了回溯思想,该算法的实现步骤如下:

  • 搜索下一个空的子单元格cell。如果没有找到,那么我们已经解决了这个难题;如果没有,则转到第 2 步。
  • 通过迭代数字1-9 来猜测正确的数字,并参考已经确定的数字来检查它是否是一个合法的数字。
  • 如果找到一个有效的数字,此时递归调用solve() 函数并猜测下一个空的子单元格cell。
  • 如果数字1-9均无效,则将将子单元格cell的值重置为 0,并继续迭代以查找下一个有效数字。
# Solve Sudoku using backtracking
def solve(board):
    blank = findEmpty(board)
    if not blank:
        return True
    else:
        row, col = blank
    for i in range(1,10):
        if isValid(board, i, blank):
            board[row][col] = i

            if solve(board):
                return True

            board[row][col] = 0
    return False

由于递归理解起来不是那么直观,不妨让我们尝试使用动态来将整个过程形象化:

正如我们在上面的示例中看到的那样,该算法用有效数字填充空子单元格cell,直到出现死胡同;然后它回溯,直到重新迭代该过程。

6. 性能表现

上述我们的程序需要使用回溯算法来遍历每个单元格的许多潜在值。这当然不是最优的解法,可以预想到我们的解决方法的性能会很慢。

我们使用上述代码,来解决欧拉计划的第96题中的50道数独题目,运行时间为:

The execution time of above program is : 23.56185507774353 s

好吧,确实有点慢。我们后面再来开篇讲解数独算法的优化

7. 总结

本文讲解了数独游戏的相关规则,以及如何在python中利用回溯思想来一步一步解决数独问题,并给出了完整的实现。

以上就是使用Python进行数独求解详解(一)的详细内容,更多关于Python数独求解的资料请关注编程网其它相关文章!

--结束END--

本文标题: 使用Python进行数独求解详解(一)

本文链接: https://lsjlt.com/news/139761.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 使用Python进行数独求解详解(一)
    目录1.引言2.描述数独九宫格3.寻找下一个空子单元格4.子单元格中设置值的合法性5.实现回溯算法6.性能表现7.总结1. 引言 本文为介绍流行的数独游戏的系列文章中的第一篇。更具体...
    99+
    2024-04-02
  • 使用Python进行数独求解详解(二)
    目录1.引言2.前文回顾3.减少非比要的迭代次数3.1生成候选值字典3.2生成候选值列表3.3函数调用4.总结1. 引言 本文是数独游戏问题求解的第二篇,在前文中我们使用回溯算法实现...
    99+
    2024-04-02
  • 如何使用Python进行数独求解
    这篇文章主要介绍“如何使用Python进行数独求解”,在日常操作中,相信很多人在如何使用Python进行数独求解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用Python进行数独求解”的疑惑有所帮助!...
    99+
    2023-06-29
  • 怎么使用Python进行数独求解
    本篇内容主要讲解“怎么使用Python进行数独求解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Python进行数独求解”吧!1. 引言数独这个名字的由来来自日语短语suuji wa d...
    99+
    2023-06-29
  • httpproxy对网络请求进行代理使用详解
    目录正文命令行启动服务器详细的调用栈捕捉错误正文 使用下面这段简单的代码对网络请求进行代理: const http = require('http'); const httpProx...
    99+
    2024-04-02
  • python使用open函数对文件进行处理详解
    目录1.open()1.1 参数11.2 参数21.3 参数32.with open() as3.open函数常用的方法3.1 读3.2 写3.3 获取文件读写类型3.4 指针移动3...
    99+
    2024-04-02
  • 基于Matlab制作一个数独求解器
    目录1.完整效果2.数独求解(错误示范)3.数独求解(升维)4.数字识别5.GUI / APP讲解一个完整的小项目,顺便说明如何使用整数规划求解数独。 1.完整效果 2.数独求解...
    99+
    2024-04-02
  • 详解使用Python+Pycaret进行异常检测
    目录概述介绍为什么是PyCaret学习目标PyCaret安装数据导入探索性异常检测分析Swarm图箱形图散点图异常检测模型创建隔离森林局部异常因子K最近邻比较模型中的异常解释和可视化...
    99+
    2024-04-02
  • python使用sum函数进行求和计算
    在python中使用sum()函数进行求和计算的方法sum:sum()函数的作用是对序列进行求和计算。sum()函数语法:sum(iterable[, start])sum()函数使用方法:>>>sum([0,1,2]) 3 >>> sum...
    99+
    2024-04-02
  • Python使用Asyncio进行web编程方法详解
    目录前言什么是同步编程什么是异步编程ayncio 版 Hello 程序如何使用 asyncio总结前言 许多 Web 应用依赖大量的 I/O (输入/输出) 操作,比如从网站上下载图...
    99+
    2024-04-02
  • Vue使用axios进行get请求拼接参数的2种方式详解
    目录前言方式1(不推荐)方式2(推荐)总结前言 本文主要介绍如何在Vue使用axios进行get请求拼接参数的两种方式 我们就以github上的一个开源接口举例: https://a...
    99+
    2023-01-05
    vue get请求传递参数 vue获取get请求参数 vue的get请求
  • 基于Matlab如何制作一个数独求解器
    这篇“基于Matlab如何制作一个数独求解器”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于Matlab如何制作一个数独求...
    99+
    2023-06-30
  • 详解在Python中使用OpenCV进行直线检测
    目录1. 引言2. 霍夫变换3. 举个栗子3.1 读入图像 进行灰度化3.2 执行边缘检测3.3 进行霍夫变换补充1. 引言 在图像处理中,直线检测是一种常见的算法,它通常获取n个边...
    99+
    2024-04-02
  • 详解Python如何使用Netmiko进行文件传输
    目录Netmiko简介Netmiko安装使用Netmiko的SCP函数传输文件从设备传输文件到本地计算机从本地计算机传输文件到设备总结在网络设备管理中,传输配置文件、镜像文件等是经常...
    99+
    2023-05-18
    Python Netmiko实现文件传输 Python Netmiko文件传输 Python Netmiko
  • Python如何使用opencv进行手势识别详解
    目录前言原理程序部分附另一个手势识别实例总结前言 本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等。 原理 首先...
    99+
    2024-04-02
  • Android之使用Bundle进行IPC详解
    一、Bundle进行IPC介绍 四大组件中的三大组件(Activity、Service、Receiver)都是支持在Intent中传递Bundle数据的,由于Bundle实现...
    99+
    2022-06-06
    ipc bundle Android
  • react使用axios进行api网络请求的封装方法详解
    目录前言准备工作开始封装axiosconfig.jsrequest.js进行请求总结前言 最近写react项目使用到axios进行请求封装,在这里记录一下,希望可以帮助到初学的小伙伴...
    99+
    2024-04-02
  • 一文详解Python如何优雅地对数据进行分组
    假设我们有这样一种数据: data = [     ("apple", 30), ("apple", 35),     ("apple", 32), ("pear", 60),   ...
    99+
    2024-04-02
  • 使用Python连接MySQL数据库进行编程的步骤详解
    目录1.连接到mysql数据库2.创建表3.插入/更新数据4.查询数据5. 异常处理6.小结PostgreSQL等。本教程将重点介绍使用python连接MySQL数据库进行编程。 MySQL是一种常见的关系型数据库,我们...
    99+
    2023-06-10
    Python连接MySQL进行编程 Python连接MySQL数据库 Python MySQL
  • Python命令行参数解析包argparse的使用详解
    目录一、argparse简介二、简单案例三、ArgumentParser参数四、add_argument指令参数解释五、vars()一、argparse简介 argparse 是 p...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作