【问题标题】:Create all Subset创建所有子集
【发布时间】:2017-07-11 18:05:34
【问题描述】:

好的。我知道。这是 Odersky's Course 中的一个练习。但是我好几天都坚持这个。

定义方法来创建输入集的所有子集:

def combination(occ: List[(Char,Int)]) : List[List[(Char,Int)]]

示例:输入List(('a', 2), ('b', 2))获取输出:

List(
  List(),
  List(('a', 1)),
  List(('a', 2)),
  List(('b', 1)),
  List(('a', 1), ('b', 1)),
  List(('a', 2), ('b', 1)),
  List(('b', 2)),
  List(('a', 1), ('b', 2)),
  List(('a', 2), ('b', 2))
)

完美。目前我得到两个不同的东西:所有夫妇(1a)和单元素列表(1b)

1a 有效。它给了我所有的情侣(一般的元组)

  def combinations(occurrences: List[(Char,Int)]) : List[List[(Char,Int)]] = {
    if (occurrences.isEmpty) List(Nil)
    else {
      val entry = occurrences.head;
      for (
           first <- (entry._2 to 1 by -1).toList;
           rest <- combinations(occurrences.tail))
        yield (entry._1, first) :: rest
    }
  }

输出List(List((a,2), (b,2)), List((a,2), (b,1)), List((a,1), (b,2)), List((a,1), (b,1)))

1b。它有效,除了我没有得到空列表(当然我没有)

  def combinations(occurrences: List[(Char,Int)]) : List[List[(Char,Int)]] = {
    for (entry <- occurrences;
         freq <- (entry._2 to 1 by -1).toList) yield List((entry._1,freq))

  }

输出List(List((a,2)), List((a,1)), List((b,2)), List((b,1)))

现在我完全不知道如何将两者结合起来。 您能否帮助我了解如何实现这一目标?

【问题讨论】:

  • 我有点不想告诉你这个,因为当我上这门课时读到这样的东西会让我陷入困境,但它可以在一个语句中完成,即之后不需要{} =。这是一个相当长的单个语句(我将它分成 3 行),涉及递归、标准库中的一些项目以及对文件中另一个方法的调用(提示:它是该文件中的下一个方法)。我希望这不是有害多于有益。祝你好运。
  • 嗯,对标准库的方法有什么建议吗?
  • 我使用了::flatMap() 并使用distinct 删除了冗余。 (不要告诉任何人我说过。)

标签: scala set subset


【解决方案1】:

不确定效率,但你可以看看这个。这是一种硬币找零问题,即给定总金额和所有可能的硬币,有多少种方法可以组成找零。其中一个想法(从上到下的方法) 是想出一个递归函数,它分叉你是否会拿特定种类的硬币,这就是内部组合函数在这里所做的:

def combinations(occurrences: List[(Char,Int)]) : List[List[(Char,Int)]] = {
    // total number of coins
    val tot = occurrences.map(_._2).sum

    // add a pair to an existing combination
    def add(counter: List[(Char, Int)], element: (Char, Int)) = {
      val countMap = counter.toMap
      (countMap + (element._1 -> (countMap.getOrElse(element._1, 0) + element._2))).toList
    }

    // a recursive function to calculate all the combinations
    def combinations(occurs: List[(Char,Int)], n: Int): List[List[(Char,Int)]] = {
      if(n == 0) List(List())
      else if(occurs.isEmpty) List()
      else {
        val firstElement = if(occurs.head._2 == 1) List() else List((occurs.head._1, 1))
        // all the combinations if you take the first kind of coin
        val headComb = combinations(firstElement ++ occurs.tail, n - 1)

        // all the combinations if you don't take the first kind of coin
        val tailComb = combinations(occurs.tail, n)    

        // add the first coin pair to head combination and concatenate it with tail combination
        headComb.map(add(_, (occurs.head._1, 1))) ++ tailComb    
      }
    }

    // calculate the combinations for each amount separately
    (0 to tot).toList.flatMap(combinations(occurrences, _))
}


combinations(List())
// res49: List[List[(Char, Int)]] = List(List())

combinations(List(('a', 1)))
// res50: List[List[(Char, Int)]] = List(List(), List((a,1)))


combinations(List(('a', 1), ('b', 2)))
// res51: List[List[(Char, Int)]] = List(List(), List((a,1)), List((b,1)), List((b,1), (a,1)), List((b,2)), List((
// b,2), (a,1)))

combinations(List(('a', 2), ('b', 2)))
// res52: List[List[(Char, Int)]] = List(List(), List((a,1)), List((b,1)), List((a,2)), List((b,1), (a,1)), List((
// b,2)), List((b,1), (a,2)), List((b,2), (a,1)), List((b,2), (a,2)))

【讨论】:

  • 我很高兴它可以工作,但我不敢相信实现这样的东西会这么难:(无论如何,我真的很感谢你,我会自己尝试一个不同的自上而下的实现方式
【解决方案2】:

我可以给你一个提示,但我不能给你一个解决方案,因为这将是 coursera 荣誉代码违规

请注意,在您的推理中,将(_, 0) 视为空集是一件好事,并且所有集合都包含空集!你可以想办法过滤掉它们。

List(('a', 2), ('b', 2)) <=> List(('a', 2), ('b', 2), ('a', 0), ('b', 0))

希望对你有帮助!祝你好运!

【讨论】:

  • Umh 使用 Range (entry._2 to 1 by -1) 自动过滤掉是否存在 (_,0) 因为生成-for,映射到 None 并退出
  • 是的,但你不想跳过带有 0 的集合,你想在没有它的情况下添加它们
猜你喜欢
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多