python实现解数独程序代码

偶然发现linux系统附带的一个数独游戏,打开玩了几把。无奈是个数独菜鸟,以前没玩过,根本就走不出几步就一团浆糊了。

于是就打算借助计算机的强大运算力来暴力解数独,还是很有乐趣的。

下面就记录一下我写解数独程序的一些思路和心得。

一.数独游戏的基本解决方法

编程笼统的来说,就是个方法论。不论什么程序,都必须将问题的解决过程分解成计算机可以实现的若干个简单方法。俗话说,大道至简。对于只能明白0和1的计算机来说,就更需要细分步骤,一步一步的解决问题了。

首先来思考一下解数独的基本概念。

数独横九竖九共八十一个格子,同时又分为9个九宫格。规则很简单——需要每一个格中的数字,都保证与其所在横排和竖排以及九宫格内无相同数字。

所以我们的大概思路就是,从第一个空格开始试着填数,从 1 开始填,如果 1 不满足横排竖排九宫格无重复的话,就再填入 2 ,以此类推,直到填入一个暂时满足规则的数,中断此格,移动到下一个空格重复这个过程。

如果到达某个空格发现已经无数可选了,说明前面某一格填错了,那就返回上一格,从上一格的中断处继续往 9 尝试,直到这样回朔到填错的那一格。

这样的话,我们就可以整理出重要的步骤了:

•寻找到下一个空格
•轮流填入格中数字 1 到 9
•递归判断填入数是否符合规则

二.程序

首先测试数独使用的是芬兰数学家因卡拉花费3个月时间设计出的世界上迄今难度最大的数独。如下

将空格用 0 表示,同时将数独表示成嵌套的列表,这样每格的行数和列数就正好是列表中每个对应数的索引。

程序如下:

 #coding=utf-8
 import datetime
 class solution(object):
   def __init__(self,board):
     self.b = board
     self.t = 0

   def check(self,x,y,value):#检查每行每列及每宫是否有相同项
     for row_item in self.b[x]:
       if row_item == value:
         return False
     for row_all in self.b:
       if row_all[y] == value:
         return False
     row,col=x/3*3,y/3*3
     row3col3=self.b[row][col:col+3]+self.b[row+1][col:col+3]+self.b[row+2][col:col+3]
     for row3col3_item in row3col3:
       if row3col3_item == value:
         return False
     return True

   def get_next(self,x,y):#得到下一个未填项
     for next_soulu in range(y+1,9):
       if self.b[x][next_soulu] == 0:
         return x,next_soulu
     for row_n in range(x+1,9):
       for col_n in range(0,9):
         if self.b[row_n][col_n] == 0:
           return row_n,col_n
     return -1,-1 #若无下一个未填项,返回-1

   def try_it(self,x,y):#主循环
     if self.b[x][y] == 0:
       for i in range(1,10):#从1到9尝试
         self.t+=1
         if self.check(x,y,i):#符合 行列宫均无条件 的
           self.b[x][y]=i #将符合条件的填入0格
           next_x,next_y=self.get_next(x,y)#得到下一个0格
           if next_x == -1: #如果无下一个0格
             return True #返回True
           else:    #如果有下一个0格,递归判断下一个0格直到填满数独
             end=self.try_it(next_x,next_y)
             if not end:  #在递归过程中存在不符合条件的,即 使try_it函数返回None的项
               self.b[x][y] = 0  #回朔到上一层继续
             else:
               return True

   def start(self):
     begin = datetime.datetime.now()
     if self.b[0][0] == 0:
       self.try_it(0,0)
     else:
       x,y=self.get_next(0,0)
       self.try_it(x,y)
     for i in self.b:
       print i
     end = datetime.datetime.now()
     print '\ncost time:', end - begin
     print 'times:',self.t
     return

 s=solution([[8,0,0,0,0,0,0,0,0],
     [0,0,3,6,0,0,0,0,0],
     [0,7,0,0,9,0,2,0,0],
     [0,5,0,0,0,7,0,0,0],
     [0,0,0,8,4,5,7,0,0],
     [0,0,0,1,0,0,0,3,0],
     [0,0,1,0,0,0,0,6,8],
     [0,0,8,5,0,0,0,1,0],
     [0,9,0,0,0,0,4,0,0]])
 73 s.start()

值得注意的是使用的递归判断能够很巧妙的在走错分支时回朔到上一层。具体实现是通过 for 循环来从 1 到 9 不断填入数字同时达到记录中断点的作用。通过下一层的返回值来确定是否回朔。

程序输出如下:

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

cost time: 0:00:00.060687
times: 45360

可以看到程序虽然运算次数比较多,但是速度还是很快的。

(0)

相关推荐

  • Python如何判断数独是否合法

    介绍 该数独可能只填充了部分数字,其中缺少的数字用 . 表示. 注意事项 一个合法的数独(仅部分填充)并不一定是可解的.我们仅需使填充的空格有效即可. 解体思路 将数独按照行.列和块进行预处理,然后分别判断是否合法. 利用Python的表达式推导,匿名函数和all函数可以很方便的进行处理. 代码 class Solution: # @param board, a 9x9 2D array # @return a boolean def isValidSudoku(self, board): ro

  • python实现数独算法实例

    本文实例讲述了python实现数独算法的方法.分享给大家供大家参考.具体如下: # -*- coding: utf-8 -*- ''' Created on 2012-10-5 @author: Administrator ''' from collections import defaultdict import itertools a = [ [ 0, 7, 0, 0, 0, 0, 0, 0, 0], #0 [ 5, 0, 3, 0, 0, 6, 0, 0, 0], #1 [ 0, 6, 2

  • python实现解数独程序代码

    偶然发现linux系统附带的一个数独游戏,打开玩了几把.无奈是个数独菜鸟,以前没玩过,根本就走不出几步就一团浆糊了. 于是就打算借助计算机的强大运算力来暴力解数独,还是很有乐趣的. 下面就记录一下我写解数独程序的一些思路和心得. 一.数独游戏的基本解决方法 编程笼统的来说,就是个方法论.不论什么程序,都必须将问题的解决过程分解成计算机可以实现的若干个简单方法.俗话说,大道至简.对于只能明白0和1的计算机来说,就更需要细分步骤,一步一步的解决问题了. 首先来思考一下解数独的基本概念. 数独横九竖九

  • C语言解数独程序的源码

    用C语言写的解数独的程序.在linux下测试成功运行. 效果如图: 这是带解的数独,需要填写的部分用数字0代替. 这是程序运行后的效果图.看看,数独已经搞定啦. 程序源码如下: #include <stdio.h> #include <stdlib.h> #define SIZE 9 #define get_low_bit(x) ((~x&(x-1))+1) struct{ int left; char num; char try; }board[SIZE][SIZE];

  • python制作抽奖程序代码详解

    实现制作抽奖程序,需要认知到我们可以看到一般抽奖程序界面上是有很多按钮的,比如中奖区域,按键开始区域等等,所以我们先要设置界面,然后把这些按钮添加到界面中去,想必这对于学过tkinter的同学应该不难.下面结合实现步骤:设计界面.利用循环.多线程来完成抽奖程序设置吧. 实现代码: import random #导入内置的random模块 list1=list(range(0,15)) #将range元素进行列表转换并赋值给列表list1 print("抽奖号码是:",list1) #打

  • Python通过30秒就能学会的漂亮短程序代码(过程全解)

    ① 二维列表 根据给定的长和宽,以及初始值,返回一个二维列表: def initialize_2d_list(w, h, val=None): return [[val for x in range(w)] for y in range(h)] 例如: >>> initialize_2d_list(2,2) [[None, None], [None, None]] >>> initialize_2d_list(2,2,0) [[0, 0], [0, 0]] ② 函数切割

  • 用Python解数独的方法示例

    芬兰数学家因卡拉花费3个月时间设计出的世界上迄今难度最大的数独.数独是 9 横 9 竖共有 81 个格子,同时又分为 9 个九宫格.规则很简单:每个空格填入 1~9 任意一个数字,需要保证每个横排和竖排以及九宫格内无相同数字. 解数独是一个可有可无的爱好,知道这个益智游戏,但是不很上心.但是前两天,由于自己的学生装了一个 ubuntu 18.04 的系统,上面有一些数独游戏,偶然间,让我看见了,为了更好的显摆自己的 Python 知识,决定用 Python 写一个程序,所以就有了下面的文字. 1

  • python+VTK环境搭建及第一个简单程序代码

    简介: Vtk,(visualization toolkit)是一个开源的免费软件系统,主要用于三维计算机图形学.图像处理和可视化.Vtk是在面向对象原理的基础上设计和实现的,它的内核是用C++构建的,包含有大约250,000行代码,2000多个类,还包含有几个转换界面,因此也可以自由的通过Java,Tcl/Tk和Python各种语言使用vtk. 在Windows环境下用Python语言开发VTK程序 1.安装Python集成开发环境IDLE,相信大家已经轻车熟路,如果不了解,大家可以参考:运行

  • Python中协程用法代码详解

    本文研究的主要是python中协程的相关问题,具体介绍如下. Num01–>协程的定义 协程,又称微线程,纤程.英文名Coroutine. 首先我们得知道协程是啥?协程其实可以认为是比线程更小的执行单元. 为啥说他是一个执行单元,因为他自带CPU上下文.这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程. 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的. Num02–>协程和线程的差异 那么这个过程看起来和线程差不多.其实不然, 线程切换从系统层面远不止保存和恢复 CP

  • 详解用python写一个抽奖程序

    第一次使用python写程序,确实比C/C++之类方便许多.既然这个抽奖的数据不大,对效率要求并不高,所以采用python写,更加简洁.清晰.方便. 1.用到的模块 生成随机数的模块random 用来读取excel表格的模块xlrd 2.思路:首先打开excel表格,然后读取其中某个单元格或者某行或某列的元素,进行输出或存储. 3.如何保证随机:随机的关键在于取随机数.每抽一个人之前,我们随机生成一个随机数i,i代表了读取第i个人的数据,由于i的生成是完全随机的,所以也就保证了选取的人员是完全随

  • Python Flask微信小程序登录流程及登录api实现代码

    一.先来看看效果 接口请求返回的数据: 二.官方登录流程图 三.小程序登录流程梳理: 1.小程序端调用wx.login 2.判断用户是否授权 3.小程序端访问 wx.getUserInfo 4.小程序端js代码: wx.login({ success: resp => { // 发送 res.code 到后台换取 openId, sessionKey, unionId console.log(resp); var that = this; // 获取用户信息 wx.getSetting({ su

  • 详解Python小数据池和代码块缓存机制

    前言 本文除"总结"外,其余均为认识过程:3.7.5:这部分官方文档不知道在哪里找,目前没有找到,有谁知道的可以麻烦留言吗? 谢谢了! 总结: 如果在同一代码块下,则采用同一代码块下的缓存机制: 如果是不同代码块,则采用小数据池的驻留机制: 需要注意的是,交互式输入时,每个命令都是一个代码块: 实现 Intern 保留机制的方式非常简单,就是通过维护一个字符串储蓄池,这个池子是一个字典结构,编译时,如果字符串已经存在于池子中就不再去创建新的字符串,直接返回之前创建好的字符串对象, 如果

随机推荐