我试图想出一种有效的方法将for-expression N皇后解决方案转换为尾递归形式,并且仍然保留使用for语法实现的惯用性,这有点问题。任何想法都非常受欢迎。
def place(boardSize: Int, n: Int): Solutions = n match {
case 0 => List(Nil)
case _ =>
for {
queens <- place(boardSize, n - 1)
y <- 1 to boardSize
queen = (n, y)
if (isSafe(queen, queens))
} yield queen :: queens
}
def isSafe(queen: Queen, others: List[Queen]) = {...}
答案 0 :(得分:1)
您所写的内容基本上与所谓的深度优先搜索(DFS)相对应。
虽然很容易编写DFS的递归实现,但它不是尾递归的。这是一个尾递归的提议。请注意,我不测试此代码,但它至少应该让您知道如何继续。
def solve(): List[List[Int]] = {
@tailrec def solver(fringe: List[List[Int]], solutions: List[List[Int]]): List[List[Int]] = fringe match {
case Nil => solutions
case potentialSol :: fringeTail =>
if(potentialSol.length == n) // We found a solution
solver(fringe.tail, potentialSol.reverse :: solutions)
else { // Keep looking
val unused = (1 to n).toList filterNot potentialSol.contains
val children = for(u <- unused ; partial = u :: fringe.head if isValid(partial)) yield partial
solver(children ++ fringe.tail, solutions)
}
}
solver((1 to n).toList.map(List(_)), Nil).map(_.reverse)
}
如果您关注性能,请注意此解决方案非常差,因为它对不可变数据结构使用了较慢的操作,并且因为在JVM上您最好使用性能重要的迭代。当n增加时,这将开始非常快速地失败。从算法上讲,解决NQueens的方法比使用DFS要好得多。