I have a Tree structure, which is more general than a binary tree structure
sealed trait Tree[+A]
case class Leaf[A](value: Terminal[A]) extends Tree[A]
case class Node[A](op: Function[A], branches: Tree[A]*) extends Tree[A]
As you see, it can have a arbitrary number of branches.
I'm trying to make an evaluation method to be tail recursive but i'm not being able to do it.
def evaluateTree[A](tree: Tree[A]): A = tree match {
case Leaf(terminal) => terminal.value
case Node(op: Function[A], args # _*) => op.operator((for (i <- args) yield evaluateTree(i)))
}
How can i save the stack manually?
If each Node can hold a different op then, no, I don't think tail recursion is possible.
If, on the other hand, you can feed all the Leaf.values to a single op then it might be possible.
def evaluateTree[A](tree: Tree[A]): A = {
#tailrec
def allValues(branches: Seq[Tree[A]], acc: Seq[A] = Seq()): Seq[A] =
if (branches.length < 1) acc
else branches.head match {
case Leaf(term) => allValues(branches.tail, term.value +: acc)
case Node(_, args: Seq[Tree[A]]) => allValues(branches.tail ++ args, acc)
}
tree match {
case Leaf(terminal) => terminal.value
case Node(op: Function[A], args: Seq[Tree[A]]) => op.operator(allValues(args))
}
}
I can't compile this as I don't have definitions for Terminal and Function, but it should be a reasonable outline of one approach to the problem.
Actually it was possible, using deep first search.
def evaluateTree[A](tree: Tree[A]): A = {
#tailrec
def evaluateWhile[C](l: List[Function[C]], arguments: List[List[C]], n_args: List[Int], f: Int => Boolean, acc: C): (List[Function[C]], List[List[C]], List[Int]) =
n_args match {
case h :: t if f(h) =>
evaluateWhile(l.tail, arguments.tail, n_args.tail, f, l.head.operator(arguments.head ::: List(acc)))
case h :: t =>
(l, (List(acc) ::: arguments.head) :: arguments.tail, List(n_args.head - 1) ::: n_args.tail)
case _ =>
(l, List(acc) :: arguments, n_args)
}
#tailrec
def DFS(toVisit: List[Tree[A]], visited: List[String] = Nil, operators: List[Function[A]] = Nil, arguments: List[List[A]] = Nil, n_args: List[Int] = Nil, debug: Int = 0): A = toVisit match {
case Leaf(id, terminal) :: tail if !visited.contains(id) => {
val (operators_to_pass, args_to_pass, n_args_to_pass) =
evaluateWhile[A](operators, arguments, n_args, x => x == 1, terminal.value)
DFS(toVisit.tail, visited ::: List(id), operators_to_pass, args_to_pass, n_args_to_pass, debug + 1)
}
case Node(id, op, args #_*) :: tail if !visited.contains(id) => {
DFS(args.toList ::: toVisit.tail, visited ::: List(id), op :: operators, List(Nil) ::: arguments, List(args.length ) ::: n_args, debug + 1)
}
case _ => arguments.flatten.head
}
DFS(List(tree))
}
Related
I have this iterative function which counts the number of Boolean values in a list.
def countBoolIter[A](test: A=>Boolean, a: List[A]) = {
var count = 0
for(elem <- a){
if(test(elem)) count += 1
}
count
}
The first parameter passed in is an isBool function:
def isBool(i: Any) = i match {
case _: Boolean => true
case _ => false
}
Calling the function looks like this:
countBoolIter(isBool, List(1, true, 3, true, false, "hi"))
// Output: 3
Now, I tried converting it into a tail recursive function like this:
def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match {
case Nil => acc
case h :: t if(test(h)) => countBoolRec(test, a, acc+1)
case h :: t => countBoolRec(test, a, acc)
}
However, I'm getting a runtime error because the function doesn't return anything; no errors are thrown. I presume that it is stuck in an infinite loop that's why nothing is being returned.
Question: How should I fix my attempted recursive implementation?
There is an error in the function countBoolRec:
#tailrec
def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match {
case Nil => acc
case h :: t if(test(h)) => countBoolRec(test, t, acc+1)
case h :: t => countBoolRec(test, t, acc)
}
In the recursive call, use t as the parameter and no again a. If not, basically, you are in an infinite loop.
Also, better to use the #tailrec annotation to be sure that the implementation is "tail recursive".
You're repeatedly recursing with the same list as input.
Consider the case where a.head passes the test:
countBoolRec(test, a, 0)
countBoolRec(test, a, 1)
countBoolRec(test, a, 2)
... and so on
#scala.annotation.tailrec // Not that your original code wasn't tail-recursive, but it's a generally good practice to mark code that isn't tail recursive with this annotation
def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match {
case Nil => acc
case h :: t if (test(h)) => countBoolRec(test, t, acc + 1)
case h :: t => countBoolRec(test, t, acc)
}
Though you could also just as well write:
(0 /: a) { (acc, v) => acc + (if (test(v)) 1 else 0) }
For exercise purposes I've been trying to implement a couple of Scala's List methods in a functional manner, one of them being partition. Assume the following signature:
def partition[T](l: List[T], f: T => Boolean): (List[T], List[T])
It returns a tuple consisting of two lists - the first one contains all the elements from l that fulfill the passed predicate f and another one which contains all the other elements.
I came up with the following recursive solution which is unfortunately not tail-recursive:
def partition[T](l: List[T], f: T => Boolean): (List[T], List[T]) = {
l match {
case Nil => (Nil, Nil)
case head :: rest => {
val (left, right) = partition(rest, f)
if (f(head))
(head :: left, right)
else
(left, head :: right)
}
}
}
In this stack overflow question (Can all recursive functions be re-written as tail-recursions?) it is made clear that an accumulator could be used in some cases. In the given one I would claim that this is not possible since it would return the final lists in a reversed manner.
Could you please give me a tail-recursive solution? Maybe even with continuation passing (I haven't really understood how it works and how it could be applied)?
You can keep a tuple as the accumulator, and make sure to reverse the lists before returning them:
def partition[T](l: List[T])(f: T => Boolean): (List[T], List[T]) = {
#tailrec
def partitionInternal(l: List[T])(acc: (List[T], List[T])): (List[T], List[T]) = {
l match {
case Nil => acc
case head :: tail =>
if (f(head)) partitionInternal(tail)(head :: acc._1, acc._2)
else partitionInternal(tail)(acc._1, head :: acc._2)
}
}
val (lf, r) = partitionInternal(l)((List.empty[T], List.empty[T]))
(lf.reverse, r.reverse)
}
An alternative solution would be to append (:+) instead of prepending (::), but then you pay the price of O(n) for every entry.
Another idea would be to use a ListBuffer[T] instead of List[T] for the internal recursive implementation which has constant time append. All you need to do is call .toList at the end:
def partition[T](l: List[T])(f: T => Boolean): (List[T], List[T]) = {
#tailrec
def partitionInternal(l: List[T])(acc: (ListBuffer[T], ListBuffer[T])): (ListBuffer[T], ListBuffer[T]) = {
l match {
case Nil => acc
case head :: tail =>
val (leftAcc, rightAcc) = acc
if (f(head)) partitionInternal(tail)((leftAcc += head, rightAcc))
else partitionInternal(tail)((leftAcc, rightAcc += head))
}
}
val (lf, r) = partitionInternal(l)((ListBuffer.empty[T], ListBuffer.empty[T]))
(lf.toList, r.toList)
}
Additionaly, notice that I create a separate argument list for the List[T] and the function from T => Boolean. That is in order to help the compiler infer the right type argument when applying the method since type inference flows between parameter lists.
You need to keep two accumulators, one for left and one for right. When you're done going through the input list, simply return both accumulators (reversing them to get back to the original order):
def partition[T](l: List[T], f: T => Boolean): (List[T], List[T]) = {
#annotation.tailrec
def aux(tl: List[T], left: List[T], right: List[T]): (List[T], List[T]) = tl match {
case Nil => (left.reverse, right.reverse)
case head :: rest => {
if (f(head))
aux(rest, head :: left, right)
else
aux(rest, left, head :: right)
}
}
aux(l, List(), List())
}
Using it:
scala> def partition[T](l: List[T], f: T => Boolean): (List[T], List[T]) = {
| #annotation.tailrec
| def aux(tl: List[T], left: List[T], right: List[T]): (List[T], List[T]) = tl match {
| case Nil => (left.reverse, right.reverse)
| case head :: rest => {
| if (f(head))
| aux(rest, head :: left, right)
| else
| aux(rest, left, head :: right)
| }
| }
|
| aux(l, List(), List())
| }
partition: [T](l: List[T], f: T => Boolean)(List[T], List[T])
scala> partition(List(1, 2, 3, 4, 5), (i: Int) => i%2 == 0)
res1: (List[Int], List[Int]) = (List(2, 4),List(1, 3, 5))
I've written the following code, which is actually a dumb merge-sort implementation in scala:
import scala.collection.immutable.List
object MergeSort {
def sort[T,E]( comparator: (E,E) => Int ) (l: List[T]): List[T] = {
def merge[T](first: List[T], second: List[T]): List[T] = (first, second) match {
case (_, List()) => first
case (List(), _) => second
case (f::restFirst, s::restSecond) if comparator(f.asInstanceOf[E],s.asInstanceOf[E]) < 0 => f :: merge(restFirst, second)
case (f::restFirst, s::restSecond) => s :: merge(first, restSecond)
}
l match {
case List() => return l
case List(x) => return l
case _ => {
val (first, second) = l.splitAt( l.length / 2 )
merge( sort(comparator)(first), sort(comparator)(second) )
}
}
}
}
This is instead of the following, more elegant, solution:
import scala.collection.immutable.List
object MergeSort {
def sort[T]( comparator: (T,T) => Int ) (l: List[T]): List[T] = {
def merge[T](first: List[T], second: List[T]): List[T] = (first, second) match {
case (_, List()) => first
case (List(), _) => second
case (f::restFirst, s::restSecond) if comparator(f,s) < 0 => f :: merge(restFirst, second)
case (f::restFirst, s::restSecond) => s :: merge(first, restSecond)
}
l match {
case List() => return l
case List(x) => return l
case _ => {
val (first, second) = l.splitAt( l.length / 2 )
merge( sort(comparator)(first), sort(comparator)(second) )
}
}
}
}
Which doesn't compile, giving me the following error message:
MergeSort.scala:10: type mismatch;
[error] found : f.type (with underlying type T)
[error] required: T
[error] case (f::restFirst, s::restSecond) if comparator(f,s) < 0 => f :: merge(restFirst, second)
Why is the explicit cast necessary since the underlying type is T ?
This is one of the most annoying Scala gotchas I can think of (maybe after semicolon inference-related issues with operators). You're three characters from the correct answer.
The problem is the type parameter on merge. It introduces a new T that shadows the T type parameter on sort. The compiler therefore doesn't know that comparator can be applied to instances of that new T. You can boss it around with a cast, which is why your first version works, but otherwise it sees that T as a blank slate.
Just write def merge(first: List[T], ... and you'll be fine.
I'm having a look at the following code
http://aperiodic.net/phil/scala/s-99/p26.scala
Specifically
def flatMapSublists[A,B](ls: List[A])(f: (List[A]) => List[B]): List[B] =
ls match {
case Nil => Nil
case sublist#(_ :: tail) => f(sublist) ::: flatMapSublists(tail)(f)
}
I'm getting a StackOverflowError for large values presumably because the function is not tail recursive. Is there a way to transform the function to accommodate large numbers?
It is definitely not tail recursive. The f(sublist) ::: is modifying the results of the recursive call, making it a plain-old-stack-blowing recursion instead of a tail recursion.
One way to ensure that your functions are tail recursive is to put the #annotation.tailrec on any function that you expect to be tail recursive. The compiler will report an error if it fails to perform the tail call optimization.
For this, I would add a small helper function that's actually tail recursive:
def flatMapSublistsTR[A,B](ls: List[A])(f: (List[A]) => List[B]): List[B] = {
#annotation.tailrec
def helper(r: List[B], ls: List[A]): List[B] = {
ls match {
case Nil => r
case sublist#(_ :: tail) => helper(r ::: f(sublist), tail)
}
}
helper(Nil, ls)
}
For reasons not immediately obvious to me, the results come out in a different order than the original function. But, it looks like it works :-) Fixed.
Here is another way to implement the function:
scala> def flatMapSublists[A,B](ls: List[A])(f: (List[A]) => List[B]): List[B] =
| List.iterate(ls, ls.size)(_.tail).flatMap(f)
flatMapSublists: [A, B](ls: List[A])(f: List[A] => List[B])List[B]
A simply comparison between dave's flatMapSublistsTR and mine:
scala> def time(count: Int)(call : => Unit):Long = {
| val start = System.currentTimeMillis
| var cnt = count
| while(cnt > 0) {
| cnt -= 1
| call
| }
| System.currentTimeMillis - start
| }
time: (count: Int)(call: => Unit)Long
scala> val xs = List.range(0,100)
scala> val fn = identity[List[Int]] _
fn: List[Int] => List[Int] = <function1>
scala> time(10000){ flatMapSublists(xs)(fn) }
res1: Long = 5732
scala> time(10000){ flatMapSublistsTR(xs)(fn) }
res2: Long = 347232
Where the method flatMapSublistsTR is implemented as:
def flatMapSublistsTR[A,B](ls: List[A])(f: (List[A]) => List[B]): List[B] = {
#annotation.tailrec
def helper(r: List[B], ls: List[A]): List[B] = {
ls match {
case Nil => r
case sublist#(_ :: tail) => helper(r ::: f(sublist), tail)
}
}
helper(Nil, ls)
}
def flatMapSublists2[A,B](ls: List[A], result: List[B] = Nil)(f: (List[A]) => List[B]): List[B] =
ls match {
case Nil => result
case sublist#(_ :: tail) => flatMapSublists2(tail, result ++ f(sublist))(f)
}
You generally just need to add a result result parameter to carry from one iteration to the next, and spit out the result at the end instead of adding the end to the list.
Also that confusting sublist# thing can be simplified to
case _ :: tail => flatMapSublists2(tail, result ++ f(ls))(f)
Off-topic: here's how I solved problem 26, without the need for helper methods like the one above. If you can make this tail-recursive, have a gold star.
def combinations[A](n: Int, lst: List[A]): List[List[A]] = n match {
case 1 => lst.map(List(_))
case _ => lst.flatMap(i => combinations (n - 1, lst.dropWhile(_ != i).tail) map (i :: _))
}
I am trying to do some examples programs in scala to get more familiar with the language, For that I am trying to re-implement some of the built in methods in Haskell, Most of these methods I am sure are also implemented in Scala too, But these are just for my practice. I think I can post some of code snippets (not all of them) to get a better way of doing things and to validate my understanding of scala. So please let me know if this is not the place to do these things.
Here is my scala implementation to get the last element of any list. Is this the right way of doing things, By using Any am I loosing the type of the object containing in the list? Is this how this kind of things implemented in scala?
def getLast(xs: List[Any]): Any = xs match {
case List() => null
case x :: List() => x
case _ :: ys => getLast(ys)
}
Parameterize the type of your function and use "Nil" instead of List() like so:
def getLast[T](xs: List[T]): T = xs match {
case Nil => null.asInstanceOf[T]
case x :: Nil => x
case _ :: ys => getLast(ys)
}
Also, consider making it return an Option type:
def getLast[T](xs: List[T]): Option[T] = xs match {
case Nil => None
case x :: Nil => Some(x)
case _ :: ys => getLast(ys)
}
Usage:
val listOfInts = List(1,2,3)
assert(getLast(listOfInts).isInstanceOf[Int])
val listOfStrings = List("one","two","three")
assert(getLast(listOfStrings).isInstanceOf[String])
Firstly, avoid the null, and especially null.asInstanceOf[T]. Observe the danger with primitives:
scala> null.asInstanceOf[Int]
res19: Int = 0
scala> null.asInstanceOf[Boolean]
res20: Boolean = false
So the signature should either be List[T] => T, whereby last on an empty iterator throws an exception:
def last[T](ts: List[T]): T = ts match {
case Nil => throw new NoSuchElementException
case t :: Nil => t
case t :: ts => last(ts)
}
Or instead: List[T] => Option[T]
def lastOption[T](ts: List[T]): Option[T] = ts match {
case Nil => None
case t :: Nil => Some(t)
case t :: ts => lastOption(ts)
}
def lastOption1[T](ts: List[T]): Option[T] = ts.reverse.headOption
def lastOptionInScala28[T](ts: List[T]): Option[T] = ts.lastOption // :)