// P17 (*) Split a list into two parts.
// The length of the first part is given. Use a Tuple for your result.
//
// Example:
// scala> split(3, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))
// res0: (List[Symbol], List[Symbol]) = (List('a, 'b, 'c),List('d, 'e, 'f, 'g, 'h, 'i, 'j, 'k))
object P17 {
// Builtin.
def splitBuiltin[A](n: Int, ls: List[A]): (List[A], List[A]) = ls.splitAt(n)
// Simple recursion.
def splitRecursive[A](n: Int, ls: List[A]): (List[A], List[A]) = (n, ls) match {
case (_, Nil) => (Nil, Nil)
case (0, list) => (Nil, list)
case (n, h :: tail) => {
val (pre, post) = splitRecursive(n - 1, tail)
(h :: pre, post)
}
}
// Tail recursive.
def splitTailRecursive[A](n: Int, ls: List[A]): (List[A], List[A]) = {
def splitR(curN: Int, curL: List[A], pre: List[A]): (List[A], List[A]) =
(curN, curL) match {
case (_, Nil) => (pre.reverse, Nil)
case (0, list) => (pre.reverse, list)
case (n, h :: tail) => splitR(n - 1, tail, h :: pre)
}
splitR(n, ls, Nil)
}
// Functional (barely not "builtin").
def splitFunctional[A](n: Int, ls: List[A]): (List[A], List[A]) =
(ls.take(n), ls.drop(n))
}