I am working on the last project for the coursera course "functional programming in scala". I need to implement a function called combinations that takes a list of character occurrences and output all possible subsets of character occurrences. As an example, the subsets of the occurrence list List(('a', 2), ('b', 2))
are:
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))
)
My approach to this problem is to loop through each character (such as 'a'), and take its possible occurrence counts (from 0 to 2), and prepand this to the current subset. Then proceed to the next character and repeat until I hit the end of the list, which is caught by the base case. I implemented this with a for comprehension like below:
type Occurrences = List[(Char, Int)]
def combinations(occurrences: Occurrences): List[Occurrences] =
if (occurrences == List()) List() // base case
else
for {
(c, n) <- occurrences
subc <- combinations((occurrences.toMap - c).toList)
i <- 0 to n
} yield {
if (i == 0) subc // not including c in the subset
else (c, i) :: subc // including c in the subset
}
This function always gives me an empty list when I call combinations(List(('a', 2), ('b', 2))
. Any ideas why this is the case?
The reason for the unexpected output is here:
This will recurse, loading the stack frame, until eventually returning the base case
List()
. Now, remember that in afor
comprehension the generators (<-
) are implemented viamap
orflatMap
, and once you map on an empty collection you're done.So the following generator,
i <- 0 to n
, is not invoked, there is nothing toyield
and the emptyList()
is the only thing to return. Then the stack frame pops, the emptyList()
is received, etc.