Scala solution to nQueen using for-comprehension

天涯浪子 提交于 2021-02-10 09:21:19

问题


I have some difficulty in understanding the Scala solution to the n Queens problem, below is the implementation assuming isSafe is defined correctly

def queens(n: Int): Set[List[Int]] = {
    def placeQueens(k: Int): Set[List[Int]] = k match {
        case 0 => Set(List())
        case _ =>
            for {
                queens <- placeQueens(k - 1)
                col <- 0 until n
                if isSafe(col, queens   )
            }yield k :: queens
    }

    placeQueens(n)
  }

The for comprehension, as I have seen, theoretically should return a buffered collection, and I see here it buffers a list of queens with k :: queens, but it indeed returns a Set[List] as defined. Can someone throw some light on how this for comprehension works?

Is my assumption correct that for every time will return a collection of collections and since in this case I deal with a Seq and a Set in the nested for for expression it is returning a Set[List].

The question is more related to the for comprehension in implementing nQueen not nQueen in general.


回答1:


Recall that a for comprehension is just syntactic sugar for map, flatmap and filter, all three of which you are using in your example. Whatever you yield in the yield block will be added to the mapped collection. You might find this article on how yield works to be interesting.

When you yield k :: queens you are creating a list with k added to the queens list which was generated from a recursive invocation using k-1.

Your assumption is correct. The for comprehension will return the types of lists involved. Since placeQueens returns a Set[List[Int]] so will the for comprehension. The translation of your for comprehension is like this:

placeQueens(k-1).flatMap { queens => 
  (0 until n).withFilter { col => 
    isSafe(col, queens)
  }.map { col => 
    k::queens
  }
}



回答2:


Remember, that for comprehension, in essence, when applied to a sequence, describes mapping of elements of a this sequence using a function which is specified inside the body of for-comprehension. Therefore, the end result will be the collection of the original outer type (i.e. Set, List or any other Seq-descendant) over the type returned by the body of for-comprehension.

In your case, the outer type is Set and the inner type is the type of k :: queens (which is List[Int], because queens is an element from the sequence returned by placeQueens, which is Set[List[Int]], and k::queens returns the sequence of the same type as queens.



来源:https://stackoverflow.com/questions/26562951/scala-solution-to-nqueen-using-for-comprehension

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