我对Coursera中的以下Scala代码感到困惑。这个代码的目的是在胸板上放置n个王后,这样就不会有王后相互威胁,意思是同一行、同一列或同一对角线。
-
从k=0到k=n,递归调用
PlaceQueen(k-1)
的求值是如何在每一步中进行的?在线路yield col::queens
中是否发生了递归调用PlaceQueen(k-1)
? -
如果
col::queens
将前面行的列附加为列表,则yield col::queens
的输出应该是列列表。但是它是如何转化为一组列表的呢?object nQueens extends App{ def queens(n: Int): Set[List[Int]] = { def placeQueens(k: Int): Set[List[Int]] = if (k == 0) Set(List()) else for { queens <- placeQueens(k - 1) col <- 0 until n if isSafe(col, queens) } yield col :: queens placeQueens(n) } def isSafe(col: Int, queens: List[Int]): Boolean = { val row = queens.length val queensWithRows = (row - 1 to 0 by -1) zip queens queensWithRows forall { case (c, r) => col != c && math.abs(col - c) != row - r } } queens(4) }
输出为:Set(List(1,3,0,2), List(2,0,3,1))
此代码有多个无限循环。
queens
方法简单地调用自己,这显然是不正确的:
def queens(n:Int):Set[List[Int]] = {
def placeQueens(k:Int):Set[List[Int]] = ???
def isSafe(col: Int, queens:List[Int]):Boolean = ???
queens(4)
}
placeQueens
方法也在经过一点计算后调用自己:
def placeQueens(k:Int):Set[List[Int]] = {
if (k==0) Set(List())
else
for {
queens <-placeQueens(k-1)
col <- 0 until n
if isSafe(col,queens)
} yield col:: queens
placeQueens(n)
}
忽略代码中的所有问题,这些问题使它无法执行预期操作,您的问题的答案是:
如何将其转换为列表集?
它被转换,因为for
中的第一个集合是Set
。之所以设置它,是因为Set
被定义为placeQueens
的返回类型。
queens <- placeQueens(k-1)
这也回答了你的第一个问题:
是否存在递归调用
placeQueen(k-1)?
因为这是递归调用所在的位置。