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

书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个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. 庞巴迪TCMS学习笔记之一(IEC 61131-3函数)

    在学习列车TCMS系统的软件逻辑图时会遇到IEC 61131-3的语言.其中通用的图形化函数总结如下.

  2. undefined reference to `dlopen'

    g++ -O0 -g3 -I. -Ithird/json -Ithird/core/include -Ithird/vite/include -Ithird/openfst-1.2.10/src/in ...

  3. 远程调试js注意事项

    1:使用host切换工具,先注释掉93服务器的地址,打开链接,点击高级选项,进去后登陆账号密码(如果不行重启浏览器): 2:进入后,增加93服务器上的host地址,重启浏览器,css样式生效: 3:使 ...

  4. centos 7 安装zabbix3.0

    1.安装MySQL 从最新版本的linux系统开始,默认的是 Mariadb而不是mysql! 使用系统自带的repos安装很简单: # yum install -y mariadb mariadb- ...

  5. Delphi、C C++、Visual Basic数据类型的对照 转

    Delphi.C C++.Visual  Basic数据类型的对照 变量类型 Delphi C/C++ Visual Basic 位有符号整数 ShortInt char -- 位无符号整数 Byte ...

  6. es6 代码片段理解

    代码片段理解: [INCREMENT]: (state, action) => { const { payload: { id } } = action //because payload co ...

  7. JS总结

    数组: var cars=new Array(); cars[0]="Audi"; cars[1]="BMW"; cars[2]="Volvo&quo ...

  8. 【java】之3种方式实现Object和Map之间的转换

    利用commons.BeanUtils实现Obj和Map之间转换,这种是最简单,也是最经常用的 public static Object mapToObject(Map<String, Obje ...

  9. Windows 查看端口占用和关闭进程

    支持原创地址 :http://www.cnblogs.com/moodlxs/p/4145384.html 开始--运行--cmd 进入命令提示符 输入netstat -ano 即可看到所有连接的PI ...

  10. jquery 百度搜索

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...