Python学习笔记之八皇后问题

来源:互联网 发布:html打赏视频源码 编辑:程序博客网 时间:2024/05/16 14:01

一、yield语句

    任何包含 yield 语句的函数称为生成器, yield 不像 return 那样返回值,yield 每次产生多个值。使用 yield 语句每次产生一个值后,函数就会被冻结:即函数停在这一点等待被激活,激活后从此点开始执行。

 

例:

>>> def flatten(nested):
               for sublist in nested:
                        for element in sublist:
                                        return element
>>> nested = [[1, 2],[3, 4], [5]]
>>> for num in flatten(nested):
                      print (num)

 
Traceback (most recent call last):
  File "", line 1, in
    for num in flatten(nested):
TypeError: 'int' object is not iterable

 

程序报错,说 flatten(nested) 是不可迭代的,所以来看一下 flatten(nested) 到底输出了什么。

 

>>> nested = [[1, 2],[3, 4], [5]]
>>> flatten(nested)
1
>>> flatten(nested)
1

 

发现原来 flatten(nested) 只输出了一个 int 类型的数,即当函数 flatten 在对列表 nested 进行循环的时候,第一遍采集到数字 1 时,就 return 了,函数就结束了。

 

看一下yield

 

>>> def flatten(nested):
                  for sublist in nested:
                            for element in sublist:
                                       yield element

   
>>> nested = [[1, 2],[3, 4], [5]]
>>> for num in flatten(nested):
                    print (num)

 
1
2
3
4
5

>>> list(flatten(nested))
[1, 2, 3, 4, 5]

 

可以看到,此时 flatten(nested) 返回的是一个列表,可迭代输出。即当函数 flatten 对 nested 进行循环的时候,采集到第一个值 1 的时候,函数即冻结,激活后仍会继续执行双循环,而不是结束函数。

 

二、八皇后问题

要求:在 8 * 8 的棋盘上,8 个皇后不在同行、同列、同对角线。

 

(1)定义冲突

>>> 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

 

其中,nextX 指下一个皇后将要放置的横坐标,也就是列。nextY 指下一个皇后将要放置的纵坐标,即行。state是一个列表,列表内存放着已经放置好的皇后的位置,即存放着元组 (x , y) ,state[ i ] = j 指第(i + 1)行的皇后在第(j + 1)列。

注: if abs(state[i] - nextX) in (0, nextY - i):  中的 (0, nextY - i):  指前面的数是否为 0 或者 nextY - i 两者中的一个,并不是指处在某个范围里面。


 

(2)放置皇后

>>> def queens(num = 8, 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

 

注:程序分为   if len(state) == num - 1:  和  else:  两部分,是因为,递归都需要有一个递归结束的点,否则,递归就会无止境的不断进行下去。

 

其中, for pos in range(num):  这一行,指的是给将要放置的新皇后,她的纵坐标已固定(由定义冲突里的 nextY = len(state) 来固定的),所以,需要在8个列位置上,给她进行选择放置的位置。

 

如果放置 4 个皇后,则有 2 种放置方法:

>>> list(queens(4))
[(1, 3, 0, 2), (2, 0, 3, 1)]

 

应用 print 可以把不同的放置方法,一行一行打印出来。

 

(3)打包输出

输出简易的放置了皇后的棋盘。

 

>>> def prettyprint(solution):
               def line(pos, length = len(solution)):
                           return '.   ' * (pos) + 'X   ' + '.   ' * (length - pos - 1)
               for pos in solution:                          #依次取出随机挑选的方案里的每个数,即每位皇后在自己的行中坐所在的列。
                           print (line(pos))

  
>>> import random
>>> prettyprint(random.choice(list(queens(8))))        #在queens(8) 的方案里随机挑选一个
  .             .
              .
              X
              .
  .   .   X   .   .   .   .
              .
    .   .         .
              .

欢迎关注微信公众号,与您分享更多精彩内容!


0 0
原创粉丝点击