How to compare elements of an array in scala (using tail recursive) - scala

I'm trying to solve the following problem and cannot find any solutions, could you please help with this:
Implement a higher order function that checks if an Array[A] is sorted given a comparison function as an argument:
def isSorted[A](as: Array[A], comparison: (A, A) => Boolean): Boolean
Ensure that your implementation is tail recursive, and use an appropriate annotation.
Example1:
isSorted[Int](Array(1, 2, 3), (x, y) => x <= y)
should be true
Example2:
isSorted[Int](Array(2, 2, 2), (x, y) => x == y)
should be true
Example3:
isSorted[Int](Array(2, 2, 2), (x, y) => x < y)
should be false
def isSorted[A](as: Array[A], comparison: (A, A) => Boolean): Boolean = {
#scala.annotation.tailrec
def iterator(as: Array[A], a: Int, b: Int): Boolean =
if (as.size == 0 || as.size == 1)
true
else if (b + 1 < as.size)
if (comparison(as(a), as(b)))
iterator(as, b, b + 1)
else
false
else
true
iterator(as, 0, 1)
}

How would you solve it without the extra constraints? You would have to check that
For all indices i in the range 0 until arr.size - 1
the condition comparison(arr(i), arr(i + 1)) holds.
That is:
def isSorted[A](arr: Array[A])(cmp: (A, A) => Boolean) =
(0 until (arr.size - 1)).forall(i => cmp(arr(i), arr(i + 1)))
Now, where's the iteration/recursion hidden? It's inside of the forall
method for the range. So, reimplement the forall on your own,
obeying the constraints of the task:
def rangeForall(r: Range, p: Int => Boolean): Boolean = {
#annotation.tailrec
def rec(idx: Int): Boolean =
if (idx >= r.end) {
true
} else if (p(idx)) {
rec(idx + 1)
} else {
false
}
rec(r.start)
}
Note how it can be tested separately, and that it requires neither nested functions nor generics or anything like that.
Use that instead of the built-in forall:
def isSorted[A](as: Array[A])(cmp: (A, A) => Boolean) =
rangeForall(0 until (as.size - 1), i => cmp(as(i), as(i + 1)))
Sanity check:
println(isSorted(Array(1, 2, 3))(_ <= _)) // true
println(isSorted(Array(2, 2, 2))(_ == _)) // true
println(isSorted(Array(2, 2, 2))(_ < _)) // false
Note that the function signature has two argument lists: this is necessary so that the type parameter is inferred from the array only, before the type checker gets to the second argument list. In this way, you don't have to write out the [Int] every time.

Short and sweet.
#annotation.tailrec
def isSorted[A](as: Seq[A], comparison: (A,A)=>Boolean): Boolean = as match {
case Seq() => true
case Seq(_) => true
case a+:b+:z => if (comparison(a,b)) isSorted(b+:z, comparison)
else false
}

Related

Scala Removing Item from List - Comparison of Methods

I am starting the Scala programming course on Coursera, coming from 2 years experience with Java/Python/C#.
I am working through a problem where you must check to see if a list of characters has balanced paranthesis.
/**
* Exercise 2
*/
def balance(chars: List[Char]): Boolean = {
def recursiveBalance(chars: List[Char]): Boolean = {
if (!chars.contains('(') && !chars.contains(')')) true
else {
val openIndex = chars.indexOf('(')
if (openIndex == -1) false
else {
val chars2 = dropFirstMatch(chars, '(')
val closeIndex = chars2.indexOf(')')
if(closeIndex == -1 || openIndex > closeIndex) false
else recursiveBalance(dropFirstMatch(chars2, ')'))
}
}
}
def remove(index: Int, list: List[Char]): List[Char] = {
list.take(index) ++ list.drop(index)
}
def dropFirstMatch[A](ls: List[A], value: A): List[A] = {
val index = ls.indexOf(value) //index is -1 if there is no match
if (index < 0) {
ls
} else if (index == 0) {
ls.tail
} else {
// splitAt keeps the matching element in the second group
val (a, b) = ls.splitAt(index)
a ++ b.tail
}
}
recursiveBalance(chars)
}
So this solution is working (if a little ugly). As part of the solution I attempted to remove an object from a list at a specific index. I've learned that in Scala Lists are immutable.
My attempt at doing this was to provide the index, the list, and use this example, which is the remove function. This works in the REPL, I made a list, ran the function and a new list was returned without the specified index.
But this did not work in my balance solution. Everytime the list was returned it was unchanged, causing infinite recursion. Eventually I stumbled on this article and borrowed their dropFirstMatch function, and upon substituting it, bam, working solution.
I am very new to Scala, and I must be overlooking something - can someone point out what it might be?
take(n) selects the first n elements in your list, where drop(n) selects all elements of the list except the first n ones.
To illustrate:
scala> val xs = List(0,1,2,3,4,5)
xs: List[Int] = List(0, 1, 2, 3, 4, 5)
scala> xs.take(2)
res0: List[Int] = List(0, 1)
scala> xs.drop(2)
res1: List[Int] = List(2, 3, 4, 5)
scala> xs.take(2) ++ xs.drop(2)
res2: List[Int] = List(0, 1, 2, 3, 4, 5)
In other words, your remove function simply returns the same list because it takes the first n elements of the original list, then adds that to the elements of the original list except the first n ones (drop). In order to remove the element at the given index in your list, you merely need to increment the index by one in your call to drop:
def remove(index: Int, list: List[Char]): List[Char] = {
list.take(index) ++ list.drop(index+1)
}
Checking for balanced parenthesis is way easier than what you are doing:
def balanced(list: Seq[Char]): Boolean = list.foldLeft(0) {
case (n, _) if (n < 0) => return false
case (n, '(') => n + 1
case (n, ')') => n - 1
case (n, _) => n
} == 0
Or, if you are a purist, like some commenters, and insist on recursion:
#tailrec
def balanced(chars: Seq[Char], n: Int = 0): Boolean = (n, chars) match {
case (-1, _) => false
case (n, Nil) => n == 0
case ('(' :: tail, n) => balanced(tail, n+1)
case (')' :: tail, n) => balanced(tail, n-1)
case (_ :: tail, n) => balanced(tail, n)
}

how to check whether given List[Int] is sorted in scala?

I would like to know whether is there any isSorted() function exist or not in scala.
Question: check whether List[Int] is sorted or not, If not remove smallest number and do again till List[Int] become sorted?
I want only 1 or 2 line program.
You can compare each pair in the input sequence for lists containing more than 1 item:
def isSorted[T](s: Seq[T])(implicit ord: Ordering[T]): Boolean = s match {
case Seq() => true
case Seq(_) => true
case _ => s.sliding(2).forall { case Seq(x, y) => ord.lteq(x, y) }
}
It's not the best solution but you can use sorted method on list and then compare it with original one;
def sorted(l: List[Int]): Boolean = l == l.sorted
With some lazyness:
def isSorted(l:List[Int]):Boolean = {
val list = l.view
!list.zip(list.tail).exists {case (x,y) => x>y}
}
Performing a sort just to check if the list is already sorted is a bit of an overkill. The optimal solution here seems to be the most obvious one, which is just describing the problem in human language and transferring it into code:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list match {
case Nil => true // an empty list is sorted
case x :: Nil => true // a single-element list is sorted
case x :: xs => ord.lteq(x, xs.head) && isSorted(xs) // if the first two elements are ordered and the rest are sorted, the full list is sorted too
}
If you want it shorter, you could trade the 2nd case for a bit of readability:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list match {
case Nil => true
case x :: xs => xs.headOption.fold(true)(ord.lteq(x, _)) && isSorted(xs)
}
If you want a one-liner, that would be not readable at all:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list.headOption.fold(true)(a => list.tail.headOption.fold(true)(ord.lteq(a, _) && isSorted(list.tail.tail)))
def isSorted(xs: List[Int]): Boolean = (xs.tail zip xs).forall(pair => pair._1 - pair._2 > 0)
Using `zip`
Lets do it without actually sorting the list.
Drop the head element in the intermediate list and then compare in pairs with original list. This way, ith element compares with i+1th element of the original list.
scala> val originalList = List(10, 20, 30, 40)
val originalList: List[Int] = List(10, 20, 30, 40)
scala> val intermediate = originalList.drop(1)
val intermediate: List[Int] = List(20, 30, 40)
scala> originalList.zip(intermediate)
val res5: List[(Int, Int)] = List((10,20), (20,30), (30,40))
scala> originalList.zip(intermediate).forall { case (orig, in) => orig <= in }
val res17: Boolean = true
A inefficient but easy to understand answer:
def specialSort(a: List[Int]): List[Int] =
if (a == a.sorted) a
else specialSort(a.filterNot(_ == a.min))
l == l.sorted didn't work for me, managed to do it with l sameElements l.sorted
Here your one-line homework solution
def removeMinWhileNotSorted[A: Ordering](xs: List[A]): List[A] = if (xs == xs.sorted) xs else xs.splitAt(xs.indexOf(xs.min)) match {case (prefix, m :: postfix) => removeMinWhileNotSorted(prefix ++ postfix)}
It does not exists. But it is easy to do: create a list with the joined version of the list and the same list sorted as you want and verify both elements of the joined list are the same.
Something like this:
import org.junit.Assert._
val sortedList = List(1, 3, 5, 7)
val unsortedList = List(10, 1, 8, 3, 5, 5, 2, 9)
// detailed test. It passes.
sortedList
.zip(sortedList.sortWith((a,b) => a.compareTo(b) < 0)) // this is the required sorting criteria.
.foreach(x => assertEquals("collection is not sorted", x._1, x._2))
// easier to read but similar test. It fails.
unsortedList
.zip(unsortedList.sorted) // this is the required sorting criteria.
.foreach(x => assertEquals("collection is not sorted", x._1, x._2))
a function could be:
def isSorted(list: List[Int]): Boolean = !list.zip(list.sortWith((a, b) => a.compareTo(b) < 0)).exists(p => !p._1.equals(p._2))
def isSorted[T <% Ordered[T]](list: List[T]): Boolean =
list.sliding(2).forall(p => (p.size==1) || p(0) < p(1))
I assumed that if two neighbor elements are equal it is legal too.
def isSorted[T <% Ordered[T]](l: List[T]):Boolean ={
val a = l.toArray
(1 until a.length).forall(i => a(i-1) <= a(i))
}
Another possibility (not necessarily any better than some of the other suggestions)
def isSorted[T <% Ordered[T]](a: List[T]): Boolean =
if (a == Nil) true // an empty list is sorted
else a.foldLeft((true, a.head))(
(prev, v1) => {
val (p, v0) = prev
(p && v0 <= v1, v1)
})._1
Results for a few test cases:
isSorted(Nil) -> true
isSorted(1 :: Nil) -> true
isSorted(2 :: 3 :: Nil) -> true
isSorted(1 :: 2 :: 5 :: 8 :: Nil) -> true
isSorted(1 :: 1 :: 2 :: 2 :: Nil) -> true
isSorted(3 :: 2 :: Nil) -> false
isSorted(1 :: 2 :: 3 :: 1 :: Nil) -> false
You can use tail recursion to less create objects and to avoid stack overflow for long lists. This version is lazy, function return value instantly after a first unordered pair.
#scala.annotation.tailrec
def isSorted[T : Ordering](values: List[T]): Boolean = {
import scala.math.Ordering.Implicits._
values match {
case fst :: snd :: _ if fst <= snd => isSorted(values.tail)
case _ :: _ :: _ => false
case _ => true
}
}
This works.
def check(list: List[Int]) = {
#tailrec
def isSorted(list: List[Int], no: Int, acc: Boolean): Boolean = {
if (list.tail == Nil) acc
else if (list.head > no) {
isSorted(list.tail, list.head, acc = true)
}
else isSorted(list.tail, list.head, acc=false)
}
isSorted(list, Integer.MIN_VALUE, acc = false)
}

Conditionally apply a function in Scala - How to write this function?

I need to conditionally apply a function f1 to the elements in a collection depending on the result of a function f2 that takes each element as an argument and returns a boolean. If f2(e) is true, f1(e) will be applied otherwise 'e' will be returned "as is".
My intent is to write a general-purpose function able to work on any kind of collection.
c: C[E] // My collection
f1 = ( E => E ) // transformation function
f2 = ( E => Boolean ) // conditional function
I cannot come to a solution. Here's my idea, but I'm afraid I'm in high-waters
/* Notice this code doesn't compile ~ partially pseudo-code */
conditionallyApply[E,C[_](c: C[E], f2: E => Boolean, f1: E => E): C[E] = {
#scala.annotation.tailrec
def loop(a: C[E], c: C[E]): C[E] = {
c match {
case Nil => a // Here head / tail just express the idea, but I want to use a generic collection
case head :: tail => go(a ++ (if f2(head) f1(head) else head ), tail)
}
}
loop(??, c) // how to get an empty collection of the same type as the one from the input?
}
Could any of you enlighten me?
This looks like a simple map of a Functor. Using scalaz:
def condMap[F[_],A](fa: F[A])(f: A => A, p: A => Boolean)(implicit F:Functor[F]) =
F.map(fa)(x => if (p(x)) f(x) else x)
Not sure why you would need scalaz for something so pedestrian.
// example collection and functions
val xs = 1 :: 2 :: 3 :: 4 :: Nil
def f1(v: Int) = v + 1
def f2(v: Int) = v % 2 == 0
// just conditionally transform inside a map
val transformed = xs.map(x => if (f2(x)) f1(x) else x)
Without using scalaz, you can use the CanBuildFrom pattern. This is exactly what is used in the standard collections library. Of course, in your specific case, this is probably over-engineered as a simple call to map is enough.
import scala.collection.generic._
def cmap[A, C[A] <: Traversable[A]](col: C[A])(f: A ⇒ A, p: A ⇒ Boolean)(implicit bf: CanBuildFrom[C[A], A, C[A]]): C[A] = {
val b = bf(col)
b.sizeHint(col)
for (x <- col) if(p(x)) b += f(x) else b += x
b.result
}
And now the usage:
scala> def f(i: Int) = 0
f: (i: Int)Int
scala> def p(i: Int) = i % 2 == 0
p: (i: Int)Boolean
scala> cmap(Seq(1, 2, 3, 4))(f, p)
res0: Seq[Int] = List(1, 0, 3, 0)
scala> cmap(List(1, 2, 3, 4))(f, p)
res1: List[Int] = List(1, 0, 3, 0)
scala> cmap(Set(1, 2, 3, 4))(f, p)
res2: scala.collection.immutable.Set[Int] = Set(1, 0, 3)
Observe how the return type is always the same as the one provided.
The function could be nicely encapsulated in an implicit class, using the "pimp my library" pattern.
For something like this you can use an implicit class. They were added just for this reason, to enhance libraries you can't change.
It would work like this:
object ImplicitStuff {
implicit class SeqEnhancer[A](s:Seq[A]) {
def transformIf( cond : A => Boolean)( f : A => A ):Seq[A] =
s.map{ x => if(cond(x)) f(x) else x }
}
def main(a:Array[String]) = {
val s = Seq(1,2,3,4,5,6,7)
println(s.transformIf(_ % 2 ==0){ _ * 2})
// result is (1, 4, 3, 8, 5, 12, 7)
}
}
Basically if you call a method that does not exists in the object you're calling it in (in this case, Seq), it will check if there's an implicit class that implements it, but it looks like a built in method.

Is there a generic way to memoize in Scala?

I wanted to memoize this:
def fib(n: Int) = if(n <= 1) 1 else fib(n-1) + fib(n-2)
println(fib(100)) // times out
So I wrote this and this surprisingly compiles and works (I am surprised because fib references itself in its declaration):
case class Memo[A,B](f: A => B) extends (A => B) {
private val cache = mutable.Map.empty[A, B]
def apply(x: A) = cache getOrElseUpdate (x, f(x))
}
val fib: Memo[Int, BigInt] = Memo {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
println(fib(100)) // prints 100th fibonacci number instantly
But when I try to declare fib inside of a def, I get a compiler error:
def foo(n: Int) = {
val fib: Memo[Int, BigInt] = Memo {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
fib(n)
}
Above fails to compile error: forward reference extends over definition of value fib
case n => fib(n-1) + fib(n-2)
Why does declaring the val fib inside a def fails but outside in the class/object scope works?
To clarify, why I might want to declare the recursive memoized function in the def scope - here is my solution to the subset sum problem:
/**
* Subset sum algorithm - can we achieve sum t using elements from s?
*
* #param s set of integers
* #param t target
* #return true iff there exists a subset of s that sums to t
*/
def subsetSum(s: Seq[Int], t: Int): Boolean = {
val max = s.scanLeft(0)((sum, i) => (sum + i) max sum) //max(i) = largest sum achievable from first i elements
val min = s.scanLeft(0)((sum, i) => (sum + i) min sum) //min(i) = smallest sum achievable from first i elements
val dp: Memo[(Int, Int), Boolean] = Memo { // dp(i,x) = can we achieve x using the first i elements?
case (_, 0) => true // 0 can always be achieved using empty set
case (0, _) => false // if empty set, non-zero cannot be achieved
case (i, x) if min(i) <= x && x <= max(i) => dp(i-1, x - s(i-1)) || dp(i-1, x) // try with/without s(i-1)
case _ => false // outside range otherwise
}
dp(s.length, t)
}
I found a better way to memoize using Scala:
def memoize[I, O](f: I => O): I => O = new mutable.HashMap[I, O]() {
override def apply(key: I) = getOrElseUpdate(key, f(key))
}
Now you can write fibonacci as follows:
lazy val fib: Int => BigInt = memoize {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
Here's one with multiple arguments (the choose function):
lazy val c: ((Int, Int)) => BigInt = memoize {
case (_, 0) => 1
case (n, r) if r > n/2 => c(n, n - r)
case (n, r) => c(n - 1, r - 1) + c(n - 1, r)
}
And here's the subset sum problem:
// is there a subset of s which has sum = t
def isSubsetSumAchievable(s: Vector[Int], t: Int) = {
// f is (i, j) => Boolean i.e. can the first i elements of s add up to j
lazy val f: ((Int, Int)) => Boolean = memoize {
case (_, 0) => true // 0 can always be achieved using empty list
case (0, _) => false // we can never achieve non-zero if we have empty list
case (i, j) =>
val k = i - 1 // try the kth element
f(k, j - s(k)) || f(k, j)
}
f(s.length, t)
}
EDIT: As discussed below, here is a thread-safe version
def memoize[I, O](f: I => O): I => O = new mutable.HashMap[I, O]() {self =>
override def apply(key: I) = self.synchronized(getOrElseUpdate(key, f(key)))
}
Class/trait level val compiles to a combination of a method and a private variable. Hence a recursive definition is allowed.
Local vals on the other hand are just regular variables, and thus recursive definition is not allowed.
By the way, even if the def you defined worked, it wouldn't do what you expect. On every invocation of foo a new function object fib will be created and it will have its own backing map. What you should be doing instead is this (if you really want a def to be your public interface):
private val fib: Memo[Int, BigInt] = Memo {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
def foo(n: Int) = {
fib(n)
}
Scalaz has a solution for that, why not reuse it?
import scalaz.Memo
lazy val fib: Int => BigInt = Memo.mutableHashMapMemo {
case 0 => 0
case 1 => 1
case n => fib(n-2) + fib(n-1)
}
You can read more about memoization in Scalaz.
Mutable HashMap isn't thread safe. Also defining case statements separately for base conditions seems unnecessary special handling, rather Map can be loaded with initial values and passed to Memoizer. Following would be the signature of Memoizer where it accepts a memo(immutable Map) and formula and returns a recursive function.
Memoizer would look like
def memoize[I,O](memo: Map[I, O], formula: (I => O, I) => O): I => O
Now given a following Fibonacci formula,
def fib(f: Int => Int, n: Int) = f(n-1) + f(n-2)
fibonacci with Memoizer can be defined as
val fibonacci = memoize( Map(0 -> 0, 1 -> 1), fib)
where context agnostic general purpose Memoizer is defined as
def memoize[I, O](map: Map[I, O], formula: (I => O, I) => O): I => O = {
var memo = map
def recur(n: I): O = {
if( memo contains n) {
memo(n)
} else {
val result = formula(recur, n)
memo += (n -> result)
result
}
}
recur
}
Similarly, for factorial, a formula is
def fac(f: Int => Int, n: Int): Int = n * f(n-1)
and factorial with Memoizer is
val factorial = memoize( Map(0 -> 1, 1 -> 1), fac)
Inspiration: Memoization, Chapter 4 of Javascript good parts by Douglas Crockford

Can a range be matched in Scala?

Is it possible to match a range of values in Scala?
For example:
val t = 5
val m = t match {
0 until 10 => true
_ => false
}
m would be true if t was between 0 and 10, but false otherwise. This little bit doesn't work of course, but is there any way to achieve something like it?
Guard using Range:
val m = t match {
case x if 0 until 10 contains x => true
case _ => false
}
You can use guards:
val m = t match {
case x if (0 <= x && x < 10) => true
case _ => false
}
With these definitions:
trait Inspector[-C, -T] {
def contains(collection: C, value: T): Boolean
}
implicit def seqInspector[T, C <: SeqLike[Any, _]] = new Inspector[C, T]{
override def contains(collection: C, value: T): Boolean = collection.contains(value)
}
implicit def setInspector[T, C <: Set[T]] = new Inspector[C, T] {
override def contains(collection: C, value: T): Boolean = collection.contains(value)
}
implicit class MemberOps[T](t: T) {
def in[C](coll: C)(implicit inspector: Inspector[C, T]) =
inspector.contains(coll, t)
}
You can do checks like these:
2 in List(1, 2, 4) // true
2 in List("foo", 2) // true
2 in Set("foo", 2) // true
2 in Set(1, 3) // false
2 in Set("foo", "foo") // does not compile
2 in List("foo", "foo") // false (contains on a list is not the same as contains on a set)
2 in (0 to 10) // true
So the code you need would be:
val m = x in (0 to 10)
Here's another way to match using a range:
val m = t match {
case x if ((0 to 10).contains(x)) => true
case _ => false
}
Another option would be to actually add this to the language using implicits, i added two variations for int and Range
object ComparisonExt {
implicit class IntComparisonOps(private val x : Int) extends AnyVal {
def between(range: Range) = x >= range.head && x < range.last
def between(from: Int, to: Int) = x >= from && x < to
}
}
object CallSite {
import ComparisonExt._
val t = 5
if (t between(0 until 10)) println("matched")
if (!(20 between(0 until 10))) println("not matched")
if (t between(0, 10)) println("matched")
if (!(20 between(0, 10))) println("not matched")
}