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之dict()的操作方法
Sep 24 Python
python BeautifulSoup设置页面编码的方法
Apr 03 Python
Python 实现选择排序的算法步骤
Apr 22 Python
Python获取昨天、今天、明天开始、结束时间戳的方法
Jun 01 Python
Python检查ping终端的方法
Jan 26 Python
pyenv与virtualenv安装实现python多版本多项目管理
Aug 17 Python
python pyenv多版本管理工具的使用
Dec 23 Python
使用Python爬虫库requests发送请求、传递URL参数、定制headers
Jan 25 Python
打包PyQt5应用时的注意事项
Feb 14 Python
python3将变量写入SQL语句的实现方式
Mar 02 Python
pytorch SENet实现案例
Jun 24 Python
python如何快速生成时间戳
Jul 21 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
一个可以删除字符串中HTML标记的PHP函数
2006/10/09 PHP
解析数组非数字键名引号的必要性
2013/08/09 PHP
php获取、检查类名、函数名、方法名的函数方法
2015/06/25 PHP
php获取当前月与上个月月初及月末时间戳的方法
2016/12/05 PHP
js文字滚动停顿效果代码
2008/06/28 Javascript
js 禁止选择功能实现代码(兼容IE/Firefox)
2010/04/23 Javascript
合并table相同单元格的jquery插件分享(很精简)
2011/06/20 Javascript
使用Jquery实现点击文字后变成文本框且可修改
2013/09/21 Javascript
PhantomJS快速入门教程(服务器端的 JavaScript API 的 WebKit)
2015/08/06 Javascript
Clipboard.js 无需Flash的JavaScript复制粘贴库
2015/10/02 Javascript
完全深入学习Bootstrap表单
2016/11/28 Javascript
vue实现列表的添加点击
2016/12/29 Javascript
angularJS利用ng-repeat遍历二维数组的实例代码
2017/06/03 Javascript
深究AngularJS——ng-checked(回写:带真实案例代码)
2017/06/13 Javascript
Bootstrap弹出框之自定义悬停框标题、内容和样式示例代码
2017/07/11 Javascript
vue router使用query和params传参的使用和区别
2017/11/13 Javascript
基于node.js实现微信支付退款功能
2017/12/19 Javascript
python集合类型用法分析
2015/04/08 Python
Python argv用法详解
2016/01/08 Python
Python实现屏幕截图的两种方式
2018/02/05 Python
python实现自动化上线脚本的示例
2019/07/01 Python
Python Web版语音合成实例详解
2019/07/16 Python
Django学习之文件上传与下载
2019/10/06 Python
python图像处理模块Pillow的学习详解
2019/10/09 Python
TensorFlow命名空间和TensorBoard图节点实例
2020/01/23 Python
HTML5 FormData 方法介绍以及实现文件上传示例
2017/09/12 HTML / CSS
四方通行旅游网:台湾订房、出国旅游
2017/09/20 全球购物
美体小铺波兰官方网站:The Body Shop波兰
2019/09/03 全球购物
应届医学毕业生求职信分享
2013/12/02 职场文书
小学生美德少年事迹
2014/02/02 职场文书
学习雷锋寄语大全
2014/04/11 职场文书
国旗下演讲稿
2014/05/08 职场文书
活动倡议书范文
2014/05/13 职场文书
群众路线教育实践活动整改方案(个人版)
2014/10/25 职场文书
写给媳妇的检讨书
2015/05/06 职场文书
漫画「你在春天醒来」第10卷封面公开
2022/03/21 日漫