N-queens in Scala

▼魔方 西西 提交于 2021-02-05 08:43:29

问题


  def queens(n: Int): List[List[(Int, Int)]] = {
    def placeQueens(k: Int): List[List[(Int, Int)]] =
      if (k == 0)
        List(List())
      else
        for {
          queens <- placeQueens(k - 1)
          column <- 1 to n
          queen = (k, column)
          if isSafe(queen, queens)
        } yield queen :: queens
    placeQueens(n)
  }

I don't understand how this code works, even tough I debugged in Eclipse. Can you explain step by step this code? By the way, code works correctly. I also understand the n-queens algorithm but I don't understand the mechanism of this code.


回答1:


Let's break it down.

def queens(n: Int): List[List[(Int, Int)]] = {
  def placeQueens(k: Int): List[List[(Int, Int)]] =
    if (k == 0)
      List(List())
    else
      for {
        queens <- placeQueens(k - 1)
        column <- 1 to n
        queen = (k, column)
        if isSafe(queen, queens)
      } yield queen :: queens
  placeQueens(n)
}

We define a function queens(n: Int) which returns every possible placement of n queens on an n*n chessboard. The functions queens itself is very simple; it just delegates to an inner function, called placeQueens.

placeQueens has a base case listed first: if we are operating on a 0*0 chessboard and placing 0 queens, there is exactly one (very trivial) way to do it. Now, the meat of this function is in the for-loop.

for {
  queens <- placeQueens(k - 1)
  column <- 1 to n
  queen = (k, column)
  if isSafe(queen, queens)
} yield queen :: queens

Parts of this can be read like a "traditional" for-loop, but some of it is not so straightforward. Scala's for-loop is based on Haskell's do-loop syntax, which probably explains some of your confusion. The way to read this is:

// We're starting a for-loop
for {
  // Call placeQueens recursively. placeQueens returns a list of
  // all possible results, so iterate over them.
  queens <- placeQueens(k - 1)
  // Iterate over each column that the kth queen could go in.
  column <- 1 to n
  // Assign the queen to that position.
  queen = (k, column)
  // If the position is safe, keep going. More precisely, if the position
  // is NOT safe, stop.
  if isSafe(queen, queens)
// Put our new queen assignment at the beginning of the recursively computed list.
} yield queen :: queens

These loops take some getting used to. It can be educational to desugar the loop (which is what the compiler does anyway) by hand to see what it means. You can find the translation rules on the Scala website.



来源:https://stackoverflow.com/questions/42789854/n-queens-in-scala

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!