Listing combinations WITH repetitions in Scala

后端 未结 7 889
盖世英雄少女心
盖世英雄少女心 2021-01-12 01:18

Trying to learn a bit of Scala and ran into this problem. I found a solution for all combinations without repetions here and I somewhat understand the idea behind i

7条回答
  •  死守一世寂寞
    2021-01-12 01:32

    I wrote a similar solution to the problem in my blog: http://gabrielsw.blogspot.com/2009/05/my-take-on-99-problems-in-scala-23-to.html

    First I thought of generating all the possible combinations and removing the duplicates, (or use sets, that takes care of the duplications itself) but as the problem was specified with lists and all the possible combinations would be too much, I've came up with a recursive solution to the problem:

    to get the combinations of size n, take one element of the set and append it to all the combinations of sets of size n-1 of the remaining elements, union the combinations of size n of the remaining elements. That's what the code does

     //P26
     def combinations[A](n:Int, xs:List[A]):List[List[A]]={
        def lift[A](xs:List[A]):List[List[A]]=xs.foldLeft(List[List[A]]())((ys,y)=>(List(y)::ys))
    
        (n,xs) match {
          case (1,ys)=> lift(ys)
          case (i,xs) if (i==xs.size) => xs::Nil
          case (i,ys)=> combinations(i-1,ys.tail).map(zs=>ys.head::zs):::combinations(i,ys.tail)
        }
     }
    

    How to read it:

    I had to create an auxiliary function that "lift" a list into a list of lists

    The logic is in the match statement:

    If you want all the combinations of size 1 of the elements of the list, just create a list of lists in which each sublist contains an element of the original one (that's the "lift" function)

    If the combinations are the total length of the list, just return a list in which the only element is the element list (there's only one possible combination!)

    Otherwise, take the head and tail of the list, calculate all the combinations of size n-1 of the tail (recursive call) and append the head to each one of the resulting lists (.map(ys.head::zs) ) concatenate the result with all the combinations of size n of the tail of the list (another recursive call)

    Does it make sense?

提交回复
热议问题