看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯

书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码

def table(m, lst):
'''绘制m列的棋盘,每行有个皇后旗子'''
head = '┌' + '─┬' * (m-1) + '─┐'
row = lambda x: '│' + ' │' * x + '╳│' + ' │' * (m - x - 1)
trow = '├' + '─┼' * (m-1) + '─┤'
tail = '└' + '─┴' * (m-1) + '─┘'
print(head)
for i, n in zip(range(len(lst)), lst):
print (row(n))
print (trow) if i < len(lst) - 1 else print (tail)
queens = [0]*8
def rightqueen(lst, m):
'''判断lst的所有皇后是否与下一行的m位置皇后干涉,不干涉则返回True'''
for i, n in zip(range(len(lst)), lst):
if(n == m or len(lst) - i == m - n or len(lst) - i == n - m):
return False
return True
def calqueen(lst, n):
'''求解第n个皇后与之前的皇后不干涉
如果第n行成功则求解n+1行,否则求解n-1行且复位n行'''
for i in range(lst[n], 8):
if rightqueen(lst[:n], i):
lst[n] = i
calqueen.count += 1
print(calqueen.count)
table(8, lst[:n+1])
if n < 7: calqueen(lst, n+1)
break
else:
#如果遍历8个之后仍然没有解则重新求解上一行
lst[n] = 0
lst[n-1] += 1
print('求解上一行')
calqueen(lst, n-1)
calqueen.count = 0
calqueen(queens, 0)

前面那个table函数只是用来绘制棋盘的,写完后感觉Python确实是很简洁的语言,当然可以更简洁,现在我的代码风格还保留很强的C语言风格,这个转变估计还需要一段时间

说他ugly倒并不是因为他没有使用迭代器,主要的问题在于函数的两个分支都使用了迭代,只有达到第八层时才会结束迭代,这个代码迭代次数要达到100多次,这样多的迭代其内存占用以及运行效率都是不太好的

因此改进版的代码应该是在失败的时候返回运行结果以便减少迭代次数,调整后的代码如下:

def table(m, lst):
'''绘制m列的棋盘,每行有个皇后旗子'''
head = '┌' + '─┬' * (m-1) + '─┐'
row = lambda x: '│' + ' │' * x + '╳│' + ' │' * (m - x - 1)
trow = '├' + '─┼' * (m-1) + '─┤'
tail = '└' + '─┴' * (m-1) + '─┘'
print(head)
for i, n in zip(range(len(lst)), lst):
print (row(n))
print (trow) if i < len(lst) - 1 else print (tail)
queens = [0]*8
def rightqueen(lst, m):
'''判断lst的所有皇后是否与下一行的m位置皇后干涉,不干涉则返回True'''
for i, n in zip(range(len(lst)), lst):
if(n == m or len(lst) - i == m - n or len(lst) - i == n - m):
return False
return True
def calqueen(lst, n):
'''求解第n个皇后与之前的皇后不干涉
如果第n行成功则求解n+1行,否则求解n-1行且复位n行'''
for i in range(8):
if rightqueen(lst[:n], i):
lst[n] = i
calqueen.count += 1
print(calqueen.count)
table(8, lst[:n+1])
if n < 7:
if not calqueen(lst, n+1): continue
return True
else:
#如果遍历8个之后仍然没有解则重新求解上一行
print('求解上一行')
calqueen.count -= 1
return False
calqueen.count = 0
calqueen(queens, 0)

减少了迭代次数后至少程序是比较合理的了,不过在看过使用生成器,迭代器的代码之后还是觉得我对Python以及迭代器编程的感觉太少了,为了增强感觉,合上书按照自己的理解又盲写了一遍,当然代码跟书上的不太一致了,但思想差不多

def table(m, lst):
'''绘制m列的棋盘,每行有个皇后旗子'''
head = '┌' + '─┬' * (m-1) + '─┐'
row = lambda x: '│' + ' │' * x + '╳│' + ' │' * (m - x - 1)
trow = '├' + '─┼' * (m-1) + '─┤'
tail = '└' + '─┴' * (m-1) + '─┘'
print(head)
for i, n in zip(range(len(lst)), lst):
print (row(n))
print (trow) if i < len(lst) - 1 else print (tail)
def rightqueen(lst, m):
'''判断lst的所有皇后是否与下一行的m位置皇后干涉,不干涉则返回True'''
for i, n in zip(range(len(lst)), lst):
if(n - m in (0, len(lst) - i, i - len(lst))):
return False
return True
def calqueen(lst, n):
'''求解第n个皇后与之前的皇后不干涉
只在第八层提交数据,其余每一层都是把本层的所有可能和后面的所有可能相加'''
for i in range(8):
calqueen.total += 1
if rightqueen(lst, i):
calqueen.count += 1
if n == 7:
calqueen.number += 1
print(calqueen.number, calqueen.count, calqueen.total)
yield lst + [i]
else:
for l in calqueen(lst + [i], n + 1):
yield l
calqueen.total = 0
calqueen.count = 0
calqueen.number = 0
for l in calqueen([], 0):
table(8, l)

事实上两个函数的核心代码只有13行,使用in和元组来替代3个条件判断,用迭代器替代对函数返回值的判断,因为如果迭代器为空,则上层调用函数遍历就会失败,自动解决了我原来算法的问题

而且这个程序能够遍历出92个八皇后的解法,虽然我之前的代码改改应该也能实现,但是不会有这么精简

因为生成器的存在,使得迭代器在使用时非常的方便,后期在处理一些需要循环层进迭代的方法时也应该优先考虑生成器,迭代器的方式.

Python学习二(生成器和八皇后算法)的更多相关文章

  1. Python学习二:词典基础详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7862377.html 邮箱:moyi@moyib ...

  2. python基础教程总结8——特殊方法,属性,迭代器,生成器,八皇后问题

    1. 重写一般方法和特殊的构造方法 1.1 如果一个方法在B类的一个实例中被调用(或一个属性被访问),但在B类中没有找到该方法,那么会去它的超类A里面找. class A: ... def hello ...

  3. 八皇后算法的另一种实现(c#版本)

    八皇后: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于 ...

  4. python学习笔记系列----(八)python常用的标准库

    终于学到了python手册的最后一部分:常用标准库.这部分内容主要就是介绍了一些基础的常用的基础库,可以大概了解下,在以后真正使用的时候也能想起来再拿出来用. 8.1 操作系统接口模块:OS OS模块 ...

  5. Prolog学习:数独和八皇后问题

    上一篇简单介绍了下Prolog的一些基本概念,今天我们来利用这些基本概念解决两个问题:数独和八皇后问题. 数独 数独是一个很经典的游戏: 玩家需要根据n×n盘面上的已知数字,推理出所有剩余空格的数字, ...

  6. python学习之生成器

    4.6 生成器Generrator ​ 生成器本质就是迭代器.python社区生成器与迭代器是一种. ​ 生成器与迭代器的唯一区别:生成器是我们自己用python代码构建的 4.6.1生成器初识 py ...

  7. Python学习二十八周(vue.js)

    一.指令 1.一个例子简单实用vue: 下载vue.js(这里实用1.0.21版本) 编写html代码: <!DOCTYPE html> <html lang="en&qu ...

  8. python学习 (二十八) Python的for 循环

    1: for 循环可以循环如下类型: my_string = "abcabc" // 字符串类型 for c in my_string: print(c, end=' ') car ...

  9. python学习之---生成器

    通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含1000万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元 ...

随机推荐

  1. C# Redis Server分布式缓存编程 --网络转载

    这篇文章我将介绍如果用最简洁的方式配置Redis Server, 以及如何使用C#和它交互编程 一. 背景介绍 Redis是最快的key-value分布式缓存之一 缺点: 没有本地数据缓冲, 目前还没 ...

  2. C# 导入Excel到DataSet中

    class Import { /// <summary> /// 导入Excel到DataSet中 /// </summary> /// <param name=&quo ...

  3. ivy 配置 maven代理

    Ivy 是一个依赖管理工具,直观感受是其跟maven 的作用差不多:但这两个其实是不同的工具: maven 是面向整个项目的工程管理及构建工具:ivy 仅作为依赖管理工具,与ant 高度集成. 需要了 ...

  4. OpenCV学习笔记——OpenCV安装

    关于OpenCV安装 1.下载和安装OpenCV SDK 在官网:http://opencv.org/上找到OpenCV windows版下载 . 后得到一个 opencv-2.X.X.exe的文件, ...

  5. 05:统计单词数【NOIP2011复赛普及组第二题】

    05:统计单词数 总时间限制:  1000ms 内存限制:  65536kB 描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次 ...

  6. Oracle基本教程

    Oracle基本教程 1.Oracle介绍 2.SqlPlus使用 3.用户管理与权限控制 4.数据库备份与还原 5.物理备份--Rman 6.常用查询 7.Oracle用法集锦 8.oracle修改 ...

  7. SQLSERVER 复制同一张表的递归结构

    CREATE PROCEDURE [dbo].[Pro_Copy] @OLDJiFenSeriesId VARCHAR(), @NEWJiFenSeriesId VARCHAR() AS BEGIN ...

  8. .NET的Cookie相关操作

    using System; using System.Collections.Generic; using System.Text; using System.Web; namespace Comm ...

  9. Spring 事务注解 错误问题

    碰到个问题,在一个springmvc项目中,设置好事务,然后在service上添加@Transactional注解,只要一添加这个注解,该service就无法被spring创建成功, error cr ...

  10. CSS3常用30种选择器总结

    CSS3常用30种选择器总结 HTML5/CSS3时尚的圆盘时钟动画 带当前日期 www.html5tricks.com/demo/html5-css3-clock-with-date/index.h ...