python刚开始学,python基础教程中有关于八皇后问题的实现,个人对于该代码的理解如下,如有问题请帮忙指正
def conflict(state,nextX):
nextY = len(state)
for i in range(nextY):
#如果后一个皇后和正在考虑的前一个皇后的水平距离为0(列相同)或者等于垂直距离(在一条对象线上)就返回True,否则就返回False
if abs(state[i] - nextX) in (0 , nextY - i):
return True
return False
def queens(num = 8,state = ()):
print("---------num:",num,"state:",state)
for pos in range(num):
if not conflict(state,pos):
print("pos:", pos)
if len(state) == num - 1:
print("if len(state) == num - 1-------","pos:",pos)
yield (pos,) #(1)
else:
for result in queens(num,state + (pos,)): #(2)
print("state:",state,"pos:",pos,"result:",result)
yield (pos,)+ result
print("---------")
def prettyprint(solution):
def line(pos,length = len(solution)):
return '. ' * (pos) + 'X ' + '. '*(length - pos -1)
for pos in solution:
print(line(pos))
print(list(queens(4)))
import random
prettyprint(random.choice(list(queens(8))))
区别:
1、代码#(2)处使用for 这个与以前使用的递归有很大不同
2、不再使用return,而使用yield
个人感觉此处使用for搭配yield的好处在于如果一条路走不通,在走到最内层的时候会跳过前面的推导过程回到最外层再重新推导
而以前使用递归的用法,每一步的推导过程都假定是对的,不会再推翻重来
输出:
[(1, 3, 0, 2), (2, 0, 3, 1)]
. . X . . . . .
. . . . . X . .
. . . X . . . .
X . . . . . . .
. . . . . . . X
. . . . X . . .
. . . . . . X .
. X . . . . . .
queens(
4
) 过程
# ---------num: 4 state: ()
# pos: 0
# ---------num: 4 state: (0,)
# pos: 2
# ---------num: 4 state: (0, 2)
# ---------
# pos: 3
# ---------num: 4 state: (0, 3)
# pos: 1
# ---------num: 4 state: (0, 3, 1)
代码#(2)处因为是for循环,而此时for内部事实上是个空结果,所以逻辑不会进入for内部,代码此时直接跳过for一层一层退出
# ---------
# ---------
# ---------
# 第一个位置是0的已经尝试过了,现在一个位置从1开始
# pos: 1
# ---------num: 4 state: (1,)
# pos: 3
# ---------num: 4 state: (1, 3)
# pos: 0
# ---------num: 4 state: (1, 3, 0)
# pos: 2
# 程序进行到这里已经成功,现在开始返回找到的答案
# if len(state) == num - 1------- pos: 2
代码#(1)把最后一个位置的2扔给上一层调用它的queens函数,此处可以用return
# state: (1, 3) pos: 0 result: (2,)
代码#(2)把倒数两个位置的结果扔给上一层调用它的queens函数,所以此处必须用yield
# state: (1,) pos: 3 result: (0, 2)
代码#(2)把倒数三个位置的结果扔给上一层调用它的queens函数
# state: () pos: 1 result: (3, 0, 2)
代码#(2)把四个位置的结果扔给最外层调用它的queens函数
# ---------
# ---------
# ---------