Scala中自定义的组合函数

时间:2018-05-31 08:07:38

标签: scala combinations combinatorics

我想在scala中实现一个组合函数,我的代码如下:

def combination[A](n: Int, ls: List[A]): List[List[A]] ={
    (n, ls) match{
        case (_, Nil) => List(Nil)
        case (1, _) => ls.map(List(_))
        case (_, _) if n > ls.size => List.empty
        case _ => ls.flatMap(x => combination(n - 1, subList(x, ls)).map(x :: _))
      }
  }
def subList[A](e: A, in: List[A]) = in.takeRight(in.size - in.indexOf(e) - 1)

但结果不是我的预期。当我拨打combination(3, List('a, 'b, 'c, 'd, 'e, 'f)时。它会给我一些或两个元素的结果,如List('d,'f),List('f)等等。任何人都可以帮我找到问题吗?感谢。

更新: 正确的版本是

def combination[A](n: Int, ls: List[A]): List[List[A]] ={
    (n, ls) match{
        case (_, Nil) => Nil
        case (1, _) => ls.map(List(_))
        case (_, _) if n > ls.size => Nil
        case _ => ls.flatMap(x => combination(n - 1, subList(x, ls)).map(x :: _))
      }
  }
def subList[A](e: A, in: List[A]) = in.takeRight(in.size - in.indexOf(e) - 1)

3 个答案:

答案 0 :(得分:2)

案件太多,不必要的复杂combinations2subList

回想一下如何定义combinations。如果你有一组{a1, ..., aN},并且想要从这个集合中选择k个元素,那么你基本上可以只做两个的事情:

  • 您未将a1包含在子集中。然后,您必须从剩余的k
  • 中选择{a2, ..., aN}个元素
  • 您将a1包含在子集中。然后,您必须从k-1中选择{a2, ..., aN}个元素,并将a0添加到这些k-1元素中。

那就是公式

C(N, k) =         C(N - 1, k) + C(N - 1, k - 1)

来自。

翻译成代码,这只是:

def comb[A](ls: List[A], k: Int): List[List[A]] = {
  if (k == 0) List(Nil)
  else ls match {
    case Nil => List()
    case h :: t => comb(t, k) ++ comb(t, k - 1).map(h :: _)
  }
}

示例:

comb(List('a, 'b, 'c, 'd, 'e), 3) foreach println 

给出:

List('c, 'd, 'e)
List('b, 'd, 'e)
List('b, 'c, 'e)
List('b, 'c, 'd)
List('a, 'd, 'e)
List('a, 'c, 'e)
List('a, 'c, 'd)
List('a, 'b, 'e)
List('a, 'b, 'd)
List('a, 'b, 'c)

答案 1 :(得分:0)

在最后一种情况下,您正在呼叫combination2。如果您更改为combinationsubList的合理定义),则可以使用。我想这是中间版本的一部分。

答案 2 :(得分:0)

这是一种更简单的方法

def comb[A](n: Int, ls:List[A]): List[List[A]] = {
  if(ls.isEmpty) List(Nil)
  else ls.toSet[A].subsets.map(_.toList).filter(_.length == n).toList
}

Scala fiddle