scala 创建所有子集

x4shl7ld  于 6个月前  发布在  Scala
关注(0)|答案(3)|浏览(115)

好吧。我知道。这是奥德斯基课程里的一个练习。但是我已经坚持了好几天了。
定义方法来创建输入集的所有子集:

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)))
现在我完全卡住了如何合并两者。你能帮助我了解我如何才能实现这一点吗?

mqkwyuun

mqkwyuun1#

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

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

字符串

hsvhsicv

hsvhsicv2#

我可以给予你一个提示,但我不能给予你一个解决方案,因为这将是违反coursera荣誉代码
请注意,在你的推理中,把(_, 0)看作空集是一件好事,所有的集合都包含空集!你可以想一个解决方案来过滤掉它们。

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

字符串
希望对你有帮助!祝你好运!

nnvyjq4y

nnvyjq4y3#

要将它们合并组合起来,你应该允许first取0作为值,然后产生rest,只有当first不等于0时才连接到(entry._1, first)。这使得你输出的子集不包含所有的对。我们实际上是在实现@alamit解释的原则:

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

字符串
因此,first现在可以写成:

first <- (entry._2 to 0 by -1).toList;


你会得到以下结果:

yield if first != 0 then (entry._1, first) :: rest else rest

相关问题