Reputation: 23
I am trying to build a scala object that finds combinations for the given list. Mathematical Notation: nc3 (ncr) Example:
input : List("a", "b", "c", "d", "e", "f")
output: List(abc, abd, abe, abf, acd, ace, acf, ade, adf, aef, bcd, bce, bcf, bde, bdf, bef, cde, cdf, cef, def)
I have come up with this below object and logic however,
I see that this approach is not right because i have to add more functions as my r increases and the number of functions linearly increases with r (here r being 3).
All i have done is just coded the imperative style of three for loops in three functions.
Is there anyway these functions can be merged so that they are functional and should not have to repeat. By this way the object works for any value of r (ncr) without the need to add new functions.
ie; i can give input of nc4, nc5 without the need to add new functions.
object combinations_functionals {
def main(args: Array[String]): Unit = {
val list = List("a", "b", "c", "d", "e", "f")
println(function(list))
}
def function(x: List[String]): List[String] = {
def fun(x: List[String], y: List[String]): List[String] = x match {
case Nil => y.reverse
case x :: xs => {
fun(xs, function1(xs, x) ::: y)
}
}
fun(x, Nil)
}
def function1(x: List[String], a: String): List[String] = {
def fun1(x: List[String], y: List[String]): List[String] = x match {
case Nil => y
case x :: xs => {
fun1(xs, function2(xs, a + x) ::: y)
}
}
fun1(x, Nil)
}
def function2(x: List[String], b: String): List[String] = {
def fun2(x: List[String], y: List[String]): List[String] = x match {
case Nil => y
case x :: xs => fun2(xs, b + x :: y)
}
fun2(x, Nil)
}
}
Upvotes: 0
Views: 194
Reputation: 51271
Is there a reason you don't want to use combinations
?
List("a", "b", "c", "d", "e", "f").combinations(3).map(_.mkString)
// result: Iterator[String] = List(abc, abd, abe, abf, acd, ace, acf, ade, adf, aef, bcd, bce, bcf, bde, bdf, bef, cde, cdf, cef, def)
OK, so if you need to roll your own, would this work?
def combos(level: Int, lst: List[String], acc: String = ""): List[String] = {
if (lst.isEmpty)
Nil
else if (level < 2)
(acc + lst.head) :: combos(level, lst.tail, acc)
else
combos(level-1, lst.tail, acc + lst.head) ::: combos(level, lst.tail, acc)
}
Usage:
combos(4, List("a", "b", "c", "d", "e"))
// res0: List[String] = List(abcd, abce, abde, acde, bcde)
Upvotes: 1