// P18 (**) Extract a slice from a list. // Given two indices, I and K, the slice is the list containing the elements // from and including the Ith element up to but not including the Kth // element of the original list. Start counting the elements with 0. // // Example: // scala> slice(3, 7, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k)) // res0: List[Symbol] = List('d, 'e, 'f, 'g) object P18 { // Builtin. def sliceBuiltin[A](start: Int, end: Int, ls: List[A]): List[A] = ls.slice(start, end) // Simple recursive. def sliceRecursive[A](start: Int, end: Int, ls: List[A]): List[A] = (start, end, ls) match { case (_, _, Nil) => Nil case (_, e, _) if e <= 0 => Nil case (s, e, h :: tail) if s <= 0 => h :: sliceRecursive(0, e - 1, tail) case (s, e, h :: tail) => sliceRecursive(s - 1, e - 1, tail) } // Tail recursive, using pattern matching. def sliceTailRecursive[A](start: Int, end: Int, ls: List[A]): List[A] = { def sliceR(count: Int, curList: List[A], result: List[A]): List[A] = (count, curList) match { case (_, Nil) => result.reverse case (c, h :: tail) if end <= c => result.reverse case (c, h :: tail) if start <= c => sliceR(c + 1, tail, h :: result) case (c, _ :: tail) => sliceR(c + 1, tail, result) } sliceR(0, ls, Nil) } // Since several of the patterns are similar, we can condense the tail recursive // solution a little. def sliceTailRecursive2[A](start: Int, end: Int, ls: List[A]): List[A] = { def sliceR(count: Int, curList: List[A], result: List[A]): List[A] = { if (curList.isEmpty || count >= end) result.reverse else sliceR(count + 1, curList.tail, if (count >= start) curList.head :: result else result) } sliceR(0, ls, Nil) } // Functional. def sliceFunctional[A](s: Int, e: Int, ls: List[A]): List[A] = ls drop s take (e - (s max 0)) }