八皇后问题之python和scheme实现
2014-03-08 19:09
531 查看
今天看python的书籍,看到递归时又遇到递归中的一个老问题—八皇后问题,书里给出了python的实现版本,具体如下:
def conflict(state,nextX):
nextY = len(state)
for i in range(nextY):
if abs(state[i]-nextX) in (0,nextY-i):
return True
return False
def queens(num,state):
for pos in range(num):
if not conflict(state,pos):
if len(state) == num-1:
yield (pos,)
else:
for result in queens(num,state + (pos,)):
yield (pos,) + result
这是我到现在为止看到的程序最简短的答案了,看来python的语言表达力果然了的,这里生成器的使用使得最终数据的收集工作变的很直接,生成器是逐渐产生结果的复杂递归算法的理想实现工具,使用生成器所有的递归调用只需要创建自己的yield部分。
学习SICP的时候,嵌套映射时候也提到了八皇后问题,文中给出了程序的模版,留了3个函数自己实现,主要时判断是否冲突,于上面conflict的功能时一样的,只是python这边因为以下标作为皇后所在的行,所以传递的参数只需要一个,而Scheme中由于时通过嵌套的map,所以构造的数据结构是一个两个元素组成的列表,程序也是全程操作所有的嵌套列表,这也就导致的搜索的空间很大,程序代码如下:
#!/usr/bin/guile -s
!#
(define (queens board-size)
(define (queen-cols k)
(if (= k 0)
(list empty-board)
(filter
(lambda (positions) (safe? k positions))
(flatmap
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
(queen-cols (- k 1))))))
(queen-cols board-size))
; Adds a new row to the board (list)
(define (adjoin-position new-row k rest-of-queens)
(cons new-row rest-of-queens))
(define empty-board '())
; current queen is at start of positions, check it against rest of the queens
(define (safe? k positions)
; current queen is at start of positions list
(define queenPos (car positions))
; top and bot are used to check for diagonal entries
(define (safe-iter top bot remain)
(cond ((null? remain)
#t)
; Checks for same row and diagonals
((or (= (car remain) queenPos)
(= (car remain) top)
(= (car remain) bot))
#f)
(else
(safe-iter (- top 1) (+ bot 1) (cdr remain)))))
(safe-iter (- queenPos 1) (+ queenPos 1) (cdr positions)))
; Helper procedures
(define (flatmap proc seq)
(accumulate append '() (map proc seq)))
(define (accumulate op init seq)
(if (null? seq)
init
(op (car seq)
(accumulate op init (cdr seq)))))
(define (enumerate-interval low high)
(if (> low high)
'()
(cons low (enumerate-interval (+ low 1) high))))
这里操作的数据结构确实没有python中选择的好,而且由于没有采用尾递归,都是函数调用,导致需要很大的栈空间,到数据给到8时就会出现Stack overflow。可能书上给的这个模版是为了说明嵌套映射吧,所以没有采用python解决问题上的思路,更是因为这里Scheme采用了函数式的编程思维,这里不采用赋值,任何有赋值的式子都是命令式的思维方式,而Scheme的思维方式导致程序最终是如此。
def conflict(state,nextX):
nextY = len(state)
for i in range(nextY):
if abs(state[i]-nextX) in (0,nextY-i):
return True
return False
def queens(num,state):
for pos in range(num):
if not conflict(state,pos):
if len(state) == num-1:
yield (pos,)
else:
for result in queens(num,state + (pos,)):
yield (pos,) + result
这是我到现在为止看到的程序最简短的答案了,看来python的语言表达力果然了的,这里生成器的使用使得最终数据的收集工作变的很直接,生成器是逐渐产生结果的复杂递归算法的理想实现工具,使用生成器所有的递归调用只需要创建自己的yield部分。
学习SICP的时候,嵌套映射时候也提到了八皇后问题,文中给出了程序的模版,留了3个函数自己实现,主要时判断是否冲突,于上面conflict的功能时一样的,只是python这边因为以下标作为皇后所在的行,所以传递的参数只需要一个,而Scheme中由于时通过嵌套的map,所以构造的数据结构是一个两个元素组成的列表,程序也是全程操作所有的嵌套列表,这也就导致的搜索的空间很大,程序代码如下:
#!/usr/bin/guile -s
!#
(define (queens board-size)
(define (queen-cols k)
(if (= k 0)
(list empty-board)
(filter
(lambda (positions) (safe? k positions))
(flatmap
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
(queen-cols (- k 1))))))
(queen-cols board-size))
; Adds a new row to the board (list)
(define (adjoin-position new-row k rest-of-queens)
(cons new-row rest-of-queens))
(define empty-board '())
; current queen is at start of positions, check it against rest of the queens
(define (safe? k positions)
; current queen is at start of positions list
(define queenPos (car positions))
; top and bot are used to check for diagonal entries
(define (safe-iter top bot remain)
(cond ((null? remain)
#t)
; Checks for same row and diagonals
((or (= (car remain) queenPos)
(= (car remain) top)
(= (car remain) bot))
#f)
(else
(safe-iter (- top 1) (+ bot 1) (cdr remain)))))
(safe-iter (- queenPos 1) (+ queenPos 1) (cdr positions)))
; Helper procedures
(define (flatmap proc seq)
(accumulate append '() (map proc seq)))
(define (accumulate op init seq)
(if (null? seq)
init
(op (car seq)
(accumulate op init (cdr seq)))))
(define (enumerate-interval low high)
(if (> low high)
'()
(cons low (enumerate-interval (+ low 1) high))))
这里操作的数据结构确实没有python中选择的好,而且由于没有采用尾递归,都是函数调用,导致需要很大的栈空间,到数据给到8时就会出现Stack overflow。可能书上给的这个模版是为了说明嵌套映射吧,所以没有采用python解决问题上的思路,更是因为这里Scheme采用了函数式的编程思维,这里不采用赋值,任何有赋值的式子都是命令式的思维方式,而Scheme的思维方式导致程序最终是如此。
相关文章推荐
- Python动态类型的学习---引用的理解
- 垃圾邮件过滤器 python简单实现
- install and upgrade scrapy
- Scrapy的架构介绍
- Centos6 编译安装Python
- 使用Python生成Excel格式的图片
- 让Python文件也可以当bat文件运行
- [Python]推算数独
- Python中zip()函数用法举例
- Python中map()函数浅析
- Python在CAM软件Genesis2000中的应用
- 使用Shiboken为C++和Qt库创建Python绑定
- Python,Flex 2和Aptana[js开放工具]
- 国外开发者谈为何放弃PHP而改用Python
- 利用webqq协议使用python登录qq发消息源码参考
- python 判断自定义对象类型
- 让python的Cookie.py模块支持冒号做key的方法
- Python 面向对象 成员的访问约束
- 新手该如何学python怎么学好python?
- Python linecache.getline()读取文件中特定一行的脚本