python3.6数独问题的解决


Posted in Python onJanuary 21, 2019

算法比较暴力,直接用穷举的方式一个一个去试,所以程序运行时间会比较长,运行时间视数独而定。
不过从一开始到运行成功,整个过程却是一波三折,设计算法就花了不少时间,然后就是不断地去调试,找bug。刚开始的时候为了省事直接在sudoku类中递归调用blank,但是老哥还是too young too simple,sometimes navie,计算量实在是太大了,后面编译器直接抛出 “RecursionError: maximum recursion depth exceeded while calling a Python object” 超过最大递归深度的错误。在把递归深度改到100000之后,又出现了堆栈溢出问题。当然,解决办法也是相当地暴力:把递归放入while循环中,一旦符合条件就直接exit(0),整个程序直接gg,然后退出结束。
当然,算法还可以再优化一下,可以不用那么暴力,先列出可能的值然后再填入,这样可以大大缩小整个程序的运行时间,但是……懒得优化了,就这样吧,又不是不能用(笑~)。

运行结果:

python3.6数独问题的解决

再试一个其他的数独:

python3.6数独问题的解决

这回就快得多了,11秒就完成了,比第一个数独不知高到哪里去了

代码如下所示:

import copy
import time

t1=time.time()
origin = [[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, 0, 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]]

class sudoku:
 def debug(self): # 调试
 for list in origin:
  print(list)
 print("\n")

 def check_repetition(self,list):#判断表中是否有重复值,0除外
 flag=0
 for i in range(1,10):
  if list.count(i)>=2:
  return 1
  else:
  flag=flag+1
 if flag==9:
  return 0

 def check_row(self,row):#检测横向是否有重复值,无则为返回0,有则返回1
 list = origin[row] # 横向
 r1 = self.check_repetition(list)
 if r1 == 0:
  return 0
 else :
  return 1

 def check_column(self,column):#检测纵向是否重复值,无则为返回0,有则返回1
 list = [] # 纵向
 for num in origin:
  list.append(num[column])
 r2 = self.check_repetition(list)
 if r2==0:
  return 0
 else:
  return 1

 def check_square(self,x,y):#检测九宫格是否有重复值,无则为返回0,有则返回1
 x,y=y,x
 if x>=9 or y>=9:
  return
 square = []#九宫格
 for i in range(0+y//3*3, 3+y//3*3):
  for j in range(0+x//3*3, 3+x//3*3):
  square.append(origin[i][j])
 r3 = self.check_repetition(square)
 if r3==0:
  return 0
 else:
  return 1

 def check(self,x,y):#检测是否有重复值,无则为0,有则不为0
 r1 = self.check_row(x)
 r2 = self.check_column(y)
 r3 = self.check_square(x, y)
 result=r1+r2+r3
 return result

 def get_next(self): # 获得下一个空值,返回row,column值
 i = 0
 for list in origin:
  try: # 当0不在列表中时,跳过
  column = list.index(0)
  row = origin.index(list)
  res = (row, column)
  return res
  except ValueError:
  i = i + 1
  if i == 9:
   t2=time.time()
   print("总用时={}".format(t2 - t1))
   exit(0)

 def poi(self,row, column): # 位置修正
 if row == 0 and column == -1:
  return
 if row == 8 and column == 9:
  return
 if column == -1:
  column = 8
  row = row - 1
 if column == 9:
  column = 0
  row = row - 1
 return (row, column)

 def get_last(self,row, column):
 origin[row].insert(column, 0)
 origin[row].pop(column + 1)
 column = column - 1 # 获得上一个已填值的行、列位置
 row, column = self.poi(row, column)#位置修正
 r = origin[row][column] * compare[row][column]
 while r != 0:
  column = column - 1
  row, column = self.poi(row, column)
  r = origin[row][column] * compare[row][column]
 return (row, column)

 def blank(self):
 try:
  row,column=self.get_next()
 except TypeError:#已填完
  exit(0)
 j=0
 flag=0
 for i in range(1,10):
  origin[row].insert(column,i)
  origin[row].pop(column+1)
  self.debug()
  r = self.check(row, column)
  if r==0:#无重复值
  return
  else:
  j = j + 1
  if j==9:
   flag=1
   break
 if flag==1:
  row, column = self.get_last(row, column)
  value=origin[row][column]
  self.debug()
  while value == 9:
  row, column = self.get_last(row, column)
  value = origin[row][column]
  self.debug()
  while value<9:
  for k in range(value+1,10):
   origin[row].insert(column, k)
   origin[row].pop(column + 1)
   self.debug()
   r=self.check(row,column)
   if r!=0:#有重复
   if k==9:
    row, column = self.get_last(row, column)
    value=origin[row][column]
    self.debug()
    while value==9:
    row, column = self.get_last(row, column)
    value = origin[row][column]
    self.debug()
    break
   else:
   return

if __name__=="__main__":
 compare = copy.deepcopy(origin)
 sudoku = sudoku()
 while 1:
 sudoku.blank()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
解密Python中的描述符(descriptor)
Jun 03 Python
Python使用tablib生成excel文件的简单实现方法
Mar 16 Python
请不要重复犯我在学习Python和Linux系统上的错误
Dec 12 Python
Python如何import文件夹下的文件(实现方法)
Jan 24 Python
python学习教程之使用py2exe打包
Sep 24 Python
对Python 两大环境管理神器 pyenv 和 virtualenv详解
Dec 31 Python
如何更优雅地写python代码
Jul 02 Python
python3的print()函数的用法图文讲解
Jul 16 Python
Python制作微信好友背景墙教程(附完整代码)
Jul 17 Python
全网首秀之Pycharm十大实用技巧(推荐)
Apr 27 Python
浅谈keras中自定义二分类任务评价指标metrics的方法以及代码
Jun 11 Python
python自动获取微信公众号最新文章的实现代码
Jul 15 Python
解决python给列表里添加字典时被最后一个覆盖的问题
Jan 21 #Python
对python列表里的字典元素去重方法详解
Jan 21 #Python
在Python中字典根据多项规则排序的方法
Jan 21 #Python
详解opencv Python特征检测及K-最近邻匹配
Jan 21 #Python
pycharm远程开发项目的实现步骤
Jan 20 #Python
对python中类的继承与方法重写介绍
Jan 20 #Python
python 格式化输出百分号的方法
Jan 20 #Python
You might like
php短址转换实现方法
2015/02/25 PHP
Thinkphp实现站点静态化的方法详解
2017/03/21 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
2017/09/22 PHP
解决laravel session失效的问题
2019/10/14 PHP
php输出形式实例整理
2020/05/05 PHP
不错的JS中变量相关的细节分析
2007/08/13 Javascript
海量经典的jQuery插件集合
2010/01/12 Javascript
javascript跑马灯悬停放大效果实现代码
2012/12/12 Javascript
js判断登录与否并确定跳转页面的方法
2015/01/30 Javascript
AngularJS学习笔记之基本指令(init、repeat)
2015/06/16 Javascript
Javascript点击其他任意地方隐藏关闭DIV实例
2016/06/21 Javascript
简单的渐变轮播插件
2017/01/12 Javascript
JavaScript函数节流的两种写法
2017/04/07 Javascript
基于canvas粒子系统的构建详解
2017/08/31 Javascript
深入理解Vue2.x的虚拟DOM diff原理
2017/09/27 Javascript
微信小程序使用modal组件弹出对话框功能示例
2017/11/29 Javascript
JavaScript通过mouseover()实现图片变大效果的示例
2017/12/20 Javascript
Vue父子组件之间的通信实例详解
2018/09/28 Javascript
jQuery判断自定义属性data-val用法示例
2019/01/07 jQuery
更强大的vue ssr实现预取数据的方式
2019/07/19 Javascript
jQuery实现容器间的元素拖拽功能
2020/12/01 jQuery
[02:05]2014DOTA2西雅图邀请赛 专访啸天mik夫妻档
2014/07/08 DOTA
Python的Flask框架中Flask-Admin库的简单入门指引
2015/04/07 Python
详解Python中列表和元祖的使用方法
2015/04/25 Python
如何使用python爬取csdn博客访问量
2016/02/14 Python
CentOS中升级Python版本的方法详解
2017/07/10 Python
对python3中, print横向输出的方法详解
2019/01/28 Python
基于python实现地址和经纬度转换
2020/05/19 Python
Myprotein西班牙官网:欧洲第一大运动营养品牌
2020/02/24 全球购物
高一政治教学反思
2014/01/28 职场文书
大学生职业生涯规划书
2014/03/14 职场文书
公司业务员岗位职责
2014/03/18 职场文书
销售活动策划方案
2014/08/26 职场文书
房屋买卖委托书格式范本格式
2014/10/13 职场文书
2015年幼儿园后勤工作总结
2015/04/25 职场文书
关于倡议书的范文
2015/04/29 职场文书