recursive function not recognizing initial input in scala - scala

This is an exercise in Functional Programming in Scala.
Implement hasSubsequence for
checking whether a List contains another List as a subsequence. For instance,
List(1,2,3,4) would have List(1,2), List(2,3), and List(4) as
subsequences, among others.
My first try is as below:
def go[A](l: List[A], sub:List[A]): Boolean =
(l, sub) match {
case (_,Nil) => true
case (Nil,_) => false
case (a :: as, x :: xs) if a == x => go(as, xs)
case (a :: as, _) => go(as, sub)
} //> go: [A](l: List[A], sub: List[A])Boolean
go(List(1,2,0), List(1,0)) //> res6: Boolean = true
This is wrong as in recursion the initial sub input was not stored (or not recognized) but replaced at each call.
However, if I used the function as a helper function
def hasSubsequence[A](l: List[A], sub: List[A]): Boolean ={
def go[A](l: List[A], a:List[A]): Boolean =
(l, a) match {
case (_,Nil) => true
case (Nil,_) => false
case (a :: as, x :: xs) if a == x => go(as, xs)
case (a :: as, _) => go(as, sub)
}
go(l,sub)
} //> hasSubsequence: [A](l: List[A], sub: List[A])Boolean
hasSubsequence(List(1,2,0), List(1,0)) //> res5: Boolean = false
Then it is stored as a value and works fine. Question is, are there ways of doing this if I don't want any helper functions?
Update: per #jwvh the second one need to be corrected as below.
def hasSubsequence[A](l: List[A], sub: List[A]): Boolean ={
def go[A](l: List[A], a:List[A]): Boolean =
(l, a) match {
case (_,Nil) => true
case (Nil,_) => false
case (a :: as, x :: xs) if a == x => go(as, xs)
case (a :: as, _) if a == sub.head => go(a::as, sub)
case (a :: as, _) => go(as,sub)
}
go(l,sub)
} //> hasSubsequence: [A](l: List[A], sub: List[A])Boolean
hasSubsequence(List(1,2,0), List(1,0)) //> res0: Boolean = false
hasSubsequence(List(1,1,2,0), List(1,2)) //> res1: Boolean = true

Your 2nd solution isn't correct either.
hasSubsequence(List(1,1,2,0), List(1,2)) // res0: Boolean = false
As #Dima has commented, a 3rd parameter would help keep track of whether we have started a match sequence or not. Also, we need to continue the search if the match sequence starts but fails.
def hasSubsequence[A]( l : List[A]
, sub : List[A]
, inMatch: Boolean = false ): Boolean =
(l, sub) match {
case (_,Nil) => true
case (Nil,_) => false
case (a :: as, x :: xs) if a == x =>
hasSubsequence(as, xs, true) || hasSubsequence(as, sub)
case _ =>
!inMatch && hasSubsequence(l.tail, sub)
}
This is not tail recursive but it is recursive without a helper function.
hasSubsequence(List(1,2,0), List(1,0)) // res0: Boolean = false
hasSubsequence(List(1,2,0), List(1,2)) // res1: Boolean = true
hasSubsequence(List(1,2,0), List(2,0)) // res2: Boolean = true
hasSubsequence(List(1,1,2,0), List(2,1)) // res3: Boolean = false
hasSubsequence(List(1,1,2,0), List(1,2)) // res4: Boolean = true

def hasSubsequence[A](sup: List[A], sub: List[A]): Boolean = {
def isPrefix(pref: List[A], xs: List[A]): Boolean = (pref,xs) match {
case (Cons(h1,t1),Cons(h2,t2)) => h1 == h2 && isPrefix(t1,t2)
case (Nil,_) => true
case _ => false
}
sup match {
case Cons(h, t) => isPrefix(sub,sup) || hasSubsequence(t,sub)
case _ => false
}
}

Related

Filter from Seq less/greater elements and only one equal

I want to implement method in Scala which filters from Seq elements which are for example greater than provided value and additionally returns up to one equal element. For example:
greaterOrEqual(Seq(1,2,3,3,4), 3) shouldBe Seq(3,4)
I ended up with such method:
def greaterOrEqual(
seq: ArrayBuffer[Long],
value: Long
): ArrayBuffer[Long] = {
val greater = seq.filter(_ > value)
val equal = seq.filter(_ == value)
if (equal.isEmpty) {
greater
} else {
equal.tail ++ greater
}
}
but somehow it doesn't look nice to me :) Moreover, I'd like to have generic version of this method where I'd able to use not only Long type but custom case classes.
Do you have any suggestions?
Thanks in advance.
def foo[A : Ordering[A]](seq: Seq[A], value: A) = seq.find(_ == value).toList ++ seq.filter(implicitly[Ordering[A]].gt(_,value))
Or (different style)
def foo[A](seq: Seq[A], value: A)(implicit ord: Ordering[A]) = {
import ord._
seq.find(_ == value).toList ++ seq.filter(_ > value)
}
The code below is deprecated
scala> def foo[A <% Ordered[A]](seq: Seq[A], value: A) = seq.find(_ == value).toList ++ seq.filter(_ > value)
foo: [A](seq: Seq[A], value: A)(implicit evidence$1: A => Ordered[A])List[A]
scala> foo(Seq(1,2,3,3,4,4,5),3)
res8: List[Int] = List(3, 4, 4, 5)
Here's my take on it (preserving original order).
import scala.collection.mutable.ArrayBuffer
def greaterOrEqual[A]( seq :ArrayBuffer[A], value :A
)(implicit ord :Ordering[A]
) : ArrayBuffer[A] =
seq.foldLeft((ArrayBuffer.empty[A],true)){
case (acc, x) if ord.lt(x,value) => acc
case ((acc,bool), x) if ord.gt(x,value) => (acc :+ x, bool)
case ((acc,true), x) => (acc :+ x, false)
case (acc, _) => acc
}._1
testing:
greaterOrEqual(ArrayBuffer.from("xawbaxbt"), 'b')
//res0: ArrayBuffer[Char] = ArrayBuffer(x, w, b, x, t)
This is an excellent problem for a simple tail-recursive algorithm over lists.
def greaterOrEqual[T : Ordering](elements: List[T])(value: T): List[T] = {
import Ordering.Implicits._
#annotation.tailrec
def loop(remaining: List[T], alreadyIncludedEqual: Boolean, acc: List[T]): List[T] =
remaining match {
case x :: xs =>
if (!alreadyIncludedEqual && x == value)
loop(remaining = xs, alreadyIncludedEqual = true, x :: acc)
else if (x > value)
loop(remaining = xs, alreadyIncludedEqual, x :: acc)
else
loop(remaining = xs, alreadyIncludedEqual, acc)
case Nil =>
acc.reverse
}
loop(remaining = elements, alreadyIncludedEqual = false, acc = List.empty)
}
Which you can use like this:
greaterOrEqual(List(1, 3, 2, 3, 4, 0))(3)
// val res: List[Int] = List(3, 4)
You can use the below snippet:
val list = Seq(1,2,3,3,4)
val value = 3
list.partition(_>=3)._1.toSet.toSeq
Here partition method divide the list into two list. First list which satisfy the given condition, and second list contains the remaining elements.
For generic method you can using implicit Ordering. Any type who can compare elements can be handled by greaterOrEqual method.
import scala.math.Ordering._
def greaterOrEqual[T](seq: Seq[T], value: T)(implicit ordering: Ordering[T]): Seq[T] = {
#scala.annotation.tailrec
def go(xs: List[T], value: T, acc: List[T]): List[T] = {
xs match {
case Nil => acc
case head :: rest if ordering.compare(head, value) == 0 => rest.foldLeft(head :: acc){
case (result, x) if ordering.compare(x, value) > 0 => x :: result
case (result, _) => result
}
case head :: rest if ordering.compare(head, value) > 0 => go(rest, value, head :: acc)
case _ :: rest => go(rest, value, acc)
}
}
go(seq.toList, value, List.empty[T]).reverse
}

scala n-arity tree tail recursive evaluation

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))
}

Recursively iterate through a Scala list

I'm trying to recursively iterate through a list in Scala using pattern matching. I cannot use any list functions, or while/for loops. What I need to do is iterate through the list, and remove an element if it matches to be '4'. I'm new to Scala and I cannot find the answer in the textbook I have nor on google. Everyone else uses the filter method, or some other list method.
Here's what I tried to do (which is wrong)
def removeFours(lst: List[Int]): List[Int] = {
val newLst = lst
lst match {
case Nil => Nil
case a if a == 4 => newLst -= 0
case n => removeFours(newLst)
}
newLst
}
See if this works for you.
def removeFours(lst: List[Int], acc: List[Int] = List.empty): List[Int] = {
lst match {
case Nil => acc.reverse
case 4 :: t => removeFours( t, acc )
case h :: t => removeFours( t, h :: acc )
}
}
Usage:
scala> removeFours( List(3,7,4,9,2,4,1) )
res84: List[Int] = List(3, 7, 9, 2, 1)
Using an inner function and pattern matching to de-structure the list. If the head in the list is 4, then do not add it to the accumulator. If it is, append it to the accumulator.
def removeFours(lst: List[Int]): List[Int] = {
def loop(lst: List[Int], acc: List[Int]): List[Int] = lst match {
case Nil => acc
case h :: t =>
if (h == 4) {
loop(t, acc)
}else{
loop(t, acc :+ h)
}
}
loop(lst, List())
}
The preferred way to do this is with guards in the pattern match but the if else statement may look more familiar if you're just getting started with scala.
def removeFours(lst: List[Int]): List[Int] = {
def loop(lst: List[Int], acc: List[Int]): List[Int] = lst match {
case Nil => acc
case h :: t if (h == 4) => loop(t, acc)
case h :: t => loop(t, acc :+ h)
}
loop(lst, List())
}
I am not sure about the execution time. I am also new to scala but I am taking bollean approach to filter any list.
object Main extends App {
//fun that will remove 4
def rm_4(lst: List[Int]) : List[Int] = {
val a = lst.filter(kill_4)
a
}
// boolean fun for conditions
def kill_4(n: Int) : Boolean = {
if (n ==4) false
else true
}
println(rm_4(List(1,2,4,5,4))) // outpur List(1,2,5)
}

How to compare lists of Double using Scalatest Equality type?

Here's what I've tried so far:
implicit val doubleEq = TolerantNumerics.tolerantDoubleEquality(0.1)
implicit val listEq = new Equivalence[List[Double]] {
override def areEquivalent(a: List[Double], b: List[Double]): Boolean = {
(a, b) match {
case (Nil, Nil) => true
case (x :: xs, y :: ys) => x === y && areEquivalent(xs, ys)
case _ => false
}
}
}
The first assert succeeds but the second one fails:
assert(1.0 === 1.01)
assert(List(1.0) === List(1.01))
Is there a way to have collections use the implicits I've defined for their elements as well?
In my case, I redefined are areEqual method by providing a new Equality[List[Double]] which is a subclass of Equivalence[List[Double]] considering that areEqual takes Any as the second type parameter.
implicit val listEq = new Equality[List[Double]] {
def areEqual(a: List[Double], b: Any): Boolean = {
def areEqualRec(a: List[Double], b: List[Double]): Boolean = {
(a, b) match {
case (Nil, Nil) => true
case (x :: xs, y :: ys) => x === y && areEquivalent(xs, ys)
case _ => false
}
}
b match {
case daList: List[Double] => areEqualRec(a, daList)
case _ => false
}
}
}
Equality classes are only used when importing TypeCheckedTripleEquals:
Provides === and !== operators that return Boolean, delegate the equality determination to an Equality type class, and require the types of the two values compared to be in a subtype/supertype relationship.
Here's the base test class I'm using to solve this:
import org.scalactic.{Equivalence, TolerantNumerics, TypeCheckedTripleEquals}
import org.scalatest.FunSuite
abstract class UnitSpec extends FunSuite with TypeCheckedTripleEquals {
implicit val doubleEq = TolerantNumerics.tolerantDoubleEquality(0.001)
implicit val listEq = new Equivalence[List[Double]] {
override def areEquivalent(a: List[Double], b: List[Double]): Boolean = {
(a, b) match {
case (Nil, Nil) => true
case (x :: xs, y :: ys) => x === y && areEquivalent(xs, ys)
case _ => false
}
}
}
}

Return a different type according to an input parameter

Let's see an example (it's a naive example but sufficient to illustrate the problem).
def produce(l: List[Int]) : Any =
l match {
case List(x) => x
case List(x, y) => (x, y)
}
val client1 : Int = produce(List(1)).asInstanceOf[Int]
Drawback : client need to cast !
def produce2[A](l: List[Int])(f: List[Int] => A) = {
f(l)
}
val toOne = (l: List[Int]) => l.head
val toTwo = (l: List[Int]) => (l.head, l.tail.head)
val client2 : Int = produce2(List(1))(toOne)
Drawback : type safety, i.e. we can call toTwo with a singleton List.
Is there a better solution ?
If you only have two possible return values you could use Either:
def produce(l : List[Any]) : Either[Any, (Any, Any)] = l match {
case List(x) => Left(x)
case List(x, y) => Right((x, y))
}
If you don't want to create an Either, you could pass a function to transform each case:
def produce[A](l : List[Int])(sf: Int => A)(pf: (Int, Int) => A): A = l match {
case List(x) => sf(x)
case List(x, y) => pf(x, y)
}
Will this work?
def produce(l: List[Int]) = {
l match {
case List(x) => (x, None)
case List(x,y) => (x,y)
case Nil => (None, None)
}
}
or even better, to avoid match errors on lists longer than 2 elements:
def produce(l: List[Int]) =
l match {
case x :: Nil => (x, None)
case x :: xs => (x,xs.head)
case Nil => (None, None)
}