I am trying to write a recursive function in scala that takes in a list of Strings and returns a list with alternating elements from original list:
For example:
List a = {"a","b","c"}
List b = {"a","c"}
the head should always be included.
def removeAlt(list:List[String], str:String):List[String]=lst match{
case Nil=> List()
case => head::tail
if(head == true)
removeAlternating(list,head)
else
head::removeAlternating(list,head)
I get a stack overflow error.
I understand that the code is incorrect but I am trying to understand the logic on how to accomplish this with only recursion and no built in classes.
def remove[A](xs:List[A]):List[A] = xs match {
case Nil => Nil
case x::Nil => List(x)
case x::y::t => x :: remove(t)
}
if the list is empty, return a empty list.
If we're at the last element of the list, return that.
Otherwise, there must be two or more elements. Add to the first element the alternate elements of the rest of the list (and omit the second element)
Great exercise. This is what I came up with. It is not super optimized or anything:
def altList[T](rest: List[T], skip: Boolean): List[T] = {
rest match {
case Nil => Nil
case a :: tail if skip == false => a :: altList(tail, true)
case a :: tail if skip == true => altList(tail, false)
}
}
A bit shorter alternative:
def remove[A](xs:List[A]):List[A] = xs match {
case x::_::t => x :: remove(t)
case _ => xs
}
UPDATE
What is not so good with the above approach is eventual stack overflow for long lists, so I would suggest tail recursion:
import scala.annotation.tailrec
def remove[A](xs:List[A]):List[A] = {
#tailrec
def remove_r(xs:List[A], ys:List[A]):List[A] = xs match {
case x::_::t => remove_r(t, x::ys)
case _ => xs ++ ys
}
remove_r(xs, Nil).reverse
}
Related
Been trying to solve this for a while now. I need a recursive function that removes all None's from a list of Option[Int]'s, without using if-statements or using other functions.
def RemoveNone2(input: List[Option[Int]]) : List[Int] = {
input.head match {
case None => RemoveNone2(input.tail)
case _ => (input.head.get::RemoveNone2(input.tail))
}
}
val optional: List[Option[Int]] = List(Some(13), None, Some(32), None, Some(51), None, Some(17), None)
RemoveNone2(optional)
But when trying to execute the code, I get the following error:
java.util.NoSuchElementException: head of empty list
I suck at Scala, could anyone offer some insight?
You want headOption:
def RemoveNone2(input: List[Option[Int]]) : List[Int] = input.headOption match {
case None => RemoveNone2(input.tail)
case Some(head) => head :: RemoveNone2(input.tail)
}
A better way to write this is:
def removeNone(input: List[Option[Int]]) : List[Int] = input match {
case Nil => Nil
case Some(head) :: tail => head :: removeNone(tail)
case None :: tail => removeNone(tail)
An even better way is to use an accumulator, so that you can take advantage of tail-recursion:
def removeNone(input: List[Option[Int]], out: List[Int]=Nil) : List[Int] = input match {
case Nil => out.reverse
case Some(head) :: tail => removeNone(tail, head :: out)
case None :: tail => removeNone(tail, out)
}
You need to check that input list is empty to break the recursion. One of the options is to match against the list itself:
def RemoveNone2(input: List[Option[Int]]) : List[Int] = input match {
case head :: tail => head match {
case Some(value) => value :: RemoveNone2(tail)
case _ => RemoveNone2(tail)
}
case _ => Nil
}
Also note, that this implementation is not tail-recursive, whcih can lead to errors or poor performance for big collections. Tail-recursive implementation can look like that:
def RemoveNone2(input: List[Option[Int]]) : List[Int] = {
#annotation.tailrec
def inner(innerInput: List[Option[Int]], acc: List[Int]): List[Int] = innerInput match {
case head :: tail => head match {
case Some(value) => inner(tail, value::acc)
case _ => inner(tail, acc)
}
case _ => acc
}
inner(input, Nil)
}
def checkPeq[A,B](list1: List[(A, List[B])])( P: (A,B) => Boolean): List[Boolean] = {
def helper[A,B](list2: List[(A, List[B])], list3: List[B], acc1: Boolean, acc2: List[Boolean])(leq:(A,B) => Boolean): List[Boolean] = {
list2 match {
case h1::t1 => {
list3 match {
case Nil if t1!=Nil => helper(t1, t1.head._2, true, acc1::acc2)(leq)
case Nil => (acc1::acc2).reverse
case h2::t2 if(leq(h1._1, h2)) => helper(list2, t2, acc1, acc2)(leq)
case h2::t2 => helper(list2, t2, false, acc2)(leq)
}
}
}
}
helper(list1, list1.head._2, true, List())(P)
}
val list1 = List((1,List(1,2,3)), (2, List(2,3)), (3, List(3,2)), (4, List(4,5,6,3)))
println(checkPeq(list1)(_<=_))
I have a tail recursive function which returns List[Boolean], in this case List(true, true, false, false). It's working, but the problem is I need to do it without ._ or .head and preferably without indexes(bcz I can easily replace .head in this function with (0)). I need to do it with pattern matching and I don't have an idea how to start. I also got a tip from my teacher replacing it should be pretty fast. I'd appreciate any tips on how to deal with the problem.
One solution is to simply pattern match both the outer A list and the inner B list at the same time, i.e. as part of a single pattern.
def checkPeq[A,B](in: List[(A,List[B])])(pred: (A,B) => Boolean): List[Boolean] = {
#annotation.tailrec
def loop(aLst :List[(A,List[B])], acc :List[Boolean]) :List[Boolean] =
aLst match {
case Nil => acc.reverse //A list done
case (_,Nil) :: aTl => loop(aTl, true::acc) //B list done
case (a,b::bTl) :: aTl => //test a and b
if (pred(a,b)) loop((a,bTl) :: aTl, acc)
else loop(aTl, false::acc)
}
loop(in, List.empty[Boolean])
}
Here are missing pieces that should help you solve the rest of the problem:
Pattern matching a list
val l = List(2,3)
l match {
case Nil => "the list is empty"
case head :: Nil => "the least has one element"
case head :: tail => "thie list has a head element and a tail of at least one element"
}
Pattern matching a tuple
val t = (75, "picard")
t match {
case (age, name) => s"$name is $age years old"
}
Pattern matching a list of tuples
val lt = List((75, "picard"))
lt match {
case Nil => "the list is empty"
case (name, age) :: Nil => "the list has one tuple"
case (name, age) :: tail => "the list has head tuple and a tail of at least another tuple"
}
Pattern matching a tuple of list of tuples
val lt = List((75, "picard"))
val ct = List((150, "Data"))
(lt, ct) match {
case (Nil, Nil) => "tuple of two empty lists"
case ((name, age) :: Nil, Nil) => "tuple of a list with one tuple and another empty list"
case (Nil, (name, age) :: Nil) => "tuple of an empty list and another list with one tuple"
case ((name, age) :: tail, Nil) => "tuple of list with head tuple and a tail of at least another tuple, and another empty list"
case _ => "and so on"
}
Note how patterns can be composed.
I am trying to write a recursive function in SCALA that take sin a list and sorts it.
However, the code seems to run for a long time. It doesn't even give me an error message.
def sort(list:List[Int]):List[Int] = list match{
case Nil => Nil
case h::t => insert (h, sort(t))
def insert(num:Int, list:List[Int]): List[Int]=list match{
case Nil => List()
case head::tail=>
if(head>=num)
num::list
else
head::insert(num,tail)
}
sort(list)
}
You had 2 problems:
1) you are calling sort recursively from sort function directly - remove sort(list) because insert already calls it. This will make it terminate.
2) you return an empty list in one of the cases instead of constructing a list with 1 elem - base case is wrong.
This version works:
def sort(list: List[Int]): List[Int] = {
def insert(num: Int, list: List[Int]): List[Int] = list match {
case Nil => num :: Nil
case head::tail =>
if(head >= num)
num::list
else
head::insert(num, tail)
}
list match {
case Nil => Nil
case h::t => insert(h, sort(t))
}
}
I have the following recursive function which I want to use tail recursion on it. But compiler complains about my implementation with this error:Error:(79, 7) could not optimize #tailrec annotated method loop: it contains a recursive call not in tail position
n match {
^
is it because of for loop that it assumes it's not in tail position?
def dsl[N,E](qNodes:QNodeLike[N,E]*) = {
val markers = scala.collection.mutable.Map.empty[String, N]
#tailrec
def loop(n:QNodeLike[N,E]):Unit = {
n match {
case QNode(head, kids:Seq[HalfEdgeLike[E,N]]) => {
for(kid <- kids){
kid match {
case EmptyHalfEdge() =>
case HalfEdge(e, n) => loop(n)
}
}
}
case QNodeMarker(head, marker, kids:Seq[HalfEdgeLike[E,N]]) => {
markers.update(marker,head)
for(kid <- kids){
kid match {
case EmptyHalfEdge() =>
case HalfEdge(e, n) => loop(n)
}
}
}
}
}
loop(qNodes.head)
}
Yes, that's right. To make it tail recursive, you should use an explicit accumulator which is passed into the recursion.
However, unless you have very deep and narrow trees, you are unlikely to need tail recursive optimization, as the run time will grow very large well before you end up with a stack overflow.
Here's a rough idea of how to make it tail optimized:
#tailrec
def loop(n:List[QNodeLike[N,E]]):Unit = {
n match {
case QNode(head, kids:Seq[HalfEdgeLike[E,N]]) :: rem => {
kids match {
case Nil =>
case EmptyHalfEdge() :: rem2 => loop(rem2 ::: rem)
case HalfEdge(e, n) :: rem2 => loop(n :: rem2 ::: rem)
}
}
case QNodeMarker(head, marker, kids:Seq[HalfEdgeLike[E,N]]) :: rem => {
markers.update(marker,head)
kids match {
case Nil =>
case EmptyHalfEdge() :: rem2 => loop(rem2 ::: rem)
case HalfEdge(e, n) :: rem2 => loop(n :: rem2 ::: rem)
}
}
case Nil =>
}
}
Yes it is because of the loop. The result of a tailrec funtion has to be the result of the recursive call. In your case the result is the result of the for statement.
Code to determine the lat element of a list, using pattern matching:
#tailrec
def last_rec[A](list : List[A]) : A = {
list match {
case (x :: Nil) => x
case (_ :: xs) => last_rec(xs)
case Nil => throw new NoSuchElementException
}
}
I want to compile the code, I am getting "yelled" by the compiler:
PS D:\workspace\scala\P99> scalac .\P01.scala
.\P01.scala:18: error: could not optimize #tailrec annotated method last2: it contains a recursive call not in tail position
case Nil => throw new NoSuchElementException
^
one error found
If I remove the #tailrec annotation - the code compiles . How can I modify the code in order to do the tail rec optimization ?
You got a typo their. Your method is called last_rec and you are calling last which is clearly undefined. So just rename it to last. And by the way you should return Option[A] instead of A. That way you can return None when nothing is found instead of throwing the ugly NoSuchElementException.
After removing the typo and adding agilesteel's suggestion:
#tailrec
def last_rec[A](list : List[A]) : Option[A] = {
list match {
case (x :: Nil) => Some(x)
case Nil => None
case (_ :: xs) => last_rec(xs)
}
}
In this case I would do what agilesteel suggested.
However, if you really wanted to throw an exception (in another different use case), you could do it in a statically typed way:
#tailrec
def last_rec[A](list : List[A]) : Either[NoSuchElementException,A] = {
list match {
case (x :: Nil) => Right(x)
case (_ :: xs) => last_rec(xs)
case Nil => Left(new NoSuchElementException)
}
}
where later you could:
last_rec(Nil) match {
case Right(s) => println("Got a value")
case Left(e) => println("Got an exception")
}