【问题标题】:Scala solution to nQueen using for-comprehension使用 for-comprehension 对 nQueen 的 Scala 解决方案
【发布时间】:2014-10-26 00:18:13
【问题描述】:

我在理解 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)
  }

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

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

这个问题更多地与for 理解在实现 nQueen 而不是一般的 nQueen 相关。

【问题讨论】:

  • 我认为下面的表达式可以清楚地显示背景中发生的情况表达式 for(x &lt;- e1; y &lt;- e2) yield e3 被分解为过于独立的表达式 for(y &lt;- e2) yield e3 与第一个表达式进行平面映射导致 @ 987654331@,因此在上述情况下,每个产生的queens 列表必须平面映射到作为顶级集合的集合。

标签: scala for-comprehension n-queens


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    在你的例子中,外部类型是Set,内部类型是k :: queens(即List[Int],因为queensplaceQueens返回的序列中的一个元素,即Set[List[Int]]k::queens返回与queens相同类型的序列。

    【讨论】:

      猜你喜欢
      • 2016-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      • 1970-01-01
      相关资源
      最近更新 更多