使用for-understanding的scala解决方案到nQueen

时间:2014-10-25 13:33:28

标签: scala for-comprehension n-queens

我在理解n Queens problem的Scala解决方案时遇到一些困难,下面是假设正确定义了isSafe的实现

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)
  }

正如我所见,理解上理解上应该返回一个缓冲集合,我在这里看到它缓存了k :: queens的皇后列表,但它确实返回了Set[List]的定义。有人可以说明这种for理解是如何起作用的吗?

我的假设是正确的for每次都会返回一个集合集合,因为在这种情况下我处理嵌套for表达式中的Seq和Set它返回Set[List]

这个问题与for在实施nQueen而不是nQueen时的理解更为相关。

2 个答案:

答案 0 :(得分:1)

请记住,for理解,实质上,当应用于序列时,使用在for - 主体内部指定的函数来描述该序列的元素的映射。因此,最终结果将是{{1}主体返回的类型的原始外部类型(即SetList或任何其他Seq - 后代)的集合。 } -comprehension。

在您的情况下,外部类型为for,内部类型为Set的类型(k :: queens,因为List[Int]是序列中的元素由queens返回,placeQueensSet[List[Int]]返回与k::queens相同类型的序列。

答案 1 :(得分:1)

回想一下,for comprehension只是map,flatmap和filter的语法糖,你在这个例子中使用了所有三个。无论您在yield块中产生什么,都会添加到映射的集合中。您可能会发现this article on how yield works很有趣。

当您产生k :: queens时,您正在创建一个列表,其中k添加到皇后列表中,该列表是使用k-1从递归调用生成的。

你的假设是正确的。 for理解将返回所涉及的列表类型。由于placeQueens返回Set[List[Int]],因此for comprehension。 for理解的翻译是这样的:

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