import scala.annotation.tailrec // Complexity: O(n) @tailrec def last[T](list: List[T]): T = { list.tail match { case Nil => list.head case _ => last(list.tail) } } def init[T](list: List[T]): List[T] = { list.tail match { case Nil => Nil case _ => list.head::init(list.tail) } } // Complexity: O(n) def concat[T](l1: List[T], l2: List[T]): List[T] = { l1 match { case Nil => l2 case _ => l1.head::concat(l1.tail, l2) } } // Complexity: O(n²) def reverse[T](list: List[T]): List[T] = { list match { case Nil => Nil case _ => last(list)::reverse(init(list)) } } // Better -> O(n) /* def reverse[T](list: List[T], res: List[T] = Nil): List[T] = { list match { case Nil => res case _ => reverse(list.tail, list.head::res) } } */ def take[T](list: List[T], n: Int): List[T] = { if (n <= 0) Nil else list match { case Nil => Nil case _ => list.head::take(list.tail, n - 1) } } @tailrec def drop[T](list: List[T], n: Int): List[T] = { if (n <= 0) list else list match { case Nil => list case _ => drop(list.tail, n - 1) } } @tailrec def apply[T](list: List[T], n: Int): T = { n match { case 0 => list.head case _ => apply(list.tail, n - 1) } } assert(last(List(1,2,3)) == 3) assert(init(List(1,2,3)) == List(1,2)) assert(concat(List(1,2,3), List(4,5,6)) == List(1,2,3,4,5,6)) assert(reverse(List(1,2,3)) == List(3,2,1)) assert(take(List(1,2,3), 2) == List(1,2)) assert(drop(List(1,2,3), 2) == List(3)) assert(drop(List(1,2,3), 4) == Nil) assert(apply(List(1,2,3), 2) == 3)