Scala, Exercise with recursive function - scala

Trying to solve the exercises in the book "Scala for the Impatient", I have a little problem. (Below are my solutions)
1: Write a for loop for computing the product of the Unicode codes of all letters in a string. For example, the product of the characters in "Hello" is 825152896
var p = 1; val S = "Hello"
for (i <- S) p*= i
println(p)
2: Solve the preceding exercise without writing a loop. (Hint: look at the String0ps Scaladoc.)
val St="Hello".map(_.toInt).product ; println(St)
3: Write a function product(s : String) that computes the product, as described in the preceding exercises.
def product(s: String)={
val S=s; println(S.map(_.toInt).product)
}
product("Hello")
Make the function of the preceding exercise a recursive function.
??? I do not know how to do it
I hope that someone can help me.
Best regards,
Francesco

Using well-known recursive functions and modifying them to comply with a different problem may prove quite a helpful approach.
Consider as a start-up pattern the factorial recursive function,
def factorial(n: Int): Int =
if (n <= 1) 1 else n * factorial (n-1)
Consider now the factorial recursive function where the input is assumed to be a list of integers from 1 to n, and so note the way the input list is reduced to the base case,
def factorial(xs: List[Int]): Int =
if (xs.isEmpty) 1 else xs.head * factorial (xs.tail)
This transformation is now closer to a solution for the original problem on string input.

Ok...finally my code works:
def prodRec(s: String): Int = {
if (s.toList.isEmpty) 1
else {
s.toList.head * prodRec(s.tail)
}
}
println(prodRec("Hello"))
I hope that this code snippet might help someone else...
best regards
francesco

Here is another way of writing the recursive solution to the product:
def getProduct(s: String):Int = {
def accumulate(acc:Int,ch:Array[Char]):Int = {
ch.headOption match {
case None => acc
case Some(x) => accumulate(acc*x.toInt,ch.tail)
}
}
accumulate(1,s.toArray)
}

Maybe I solved with:
def prodRec(s: String): Int = {
var s2 =s.toList
if (s2.isEmpty) 1
else {
s2.head * prodRec (s.tail)
}
}

My variant of tail recursive function. No vars used, which is a plus.
def product(s: String): Unit = {
#tailrec
def help(z: Long, array: Array[Char]): Long = {
if (array.isEmpty) z else help(z * array.head.toInt, array.tail)
}
print(help(1L, s.toCharArray))
}

def product (s:String): Long ={
if (s.length==1) s(0) else s.head * s.product (s.tail)
}

Related

Tail recursion and call by name / value

Learning Scala and functional programming in general. In the following tail-recursive factorial implementation:
def factorialTailRec(n: Int) : Int = {
#tailrec
def factorialRec(n: Int, f: => Int): Int = {
if (n == 0) f else factorialRec(n - 1, n * f)
}
factorialRec(n, 1)
}
I wonder whether there is any benefit to having the second parameter called by value vs called by name (as I have done). In the first case, every stack frame is burdened with a product. In the second case, if my understanding is correct, the entire chain of products will be carried over to the case if ( n== 0) at the nth stack frame, so we will still have to perform the same number of multiplications. Unfortunately, this is not a product of form a^n, which can be calculated in log_2n steps through repeated squaring, but a product of terms that differ by 1 every time. So I can't see any possible way of optimizing the final product: it will still require the multiplication of O(n) terms.
Is this correct? Is call by value equivalent to call by name here, in terms of complexity?
Let me just expand a little bit what you've already been told in comments.
That's how by-name parameters are desugared by the compiler:
#tailrec
def factorialTailRec(n: Int, f: => Int): Int = {
if (n == 0) {
val fEvaluated = f
fEvaluated
} else {
val fEvaluated = f // <-- here we are going deeper into stack.
factorialTailRec(n - 1, n * fEvaluated)
}
}
Through experimentation I found out that with the call by name formalism, the method becomes... non-tail recursive! I made this example code to compare factorial tail-recursively, and factorial non-tail-recursively:
package example
import scala.annotation.tailrec
object Factorial extends App {
val ITERS = 100000
def factorialTailRec(n: Int) : Int = {
#tailrec
def factorialTailRec(n: Int, f: => Int): Int = {
if (n == 0) f else factorialTailRec(n - 1, n * f)
}
factorialTailRec(n, 1)
}
for(i <-1 to ITERS) println("factorialTailRec(" + i + ") = " + factorialTailRec(i))
def factorial(n:Int) : Int = {
if(n == 0) 1 else n * factorial(n-1)
}
for(i <-1 to ITERS) println("factorial(" + i + ") = " + factorial(i))
}
Observe that the inner tailRec function calls the second argument by name. for which the #tailRec annotation still does NOT throw a compile-time error!
I've been playing around with different values for the ITERS variable, and for a value of 100,000, I receive a... StackOverflowError!
(The result of zero is there because of overflow of Int.)
So I went ahead and changed the signature of factorialTailRec/2, to:
def factorialTailRec(n: Int, f: Int): Int
i.e call by value for the argument f. This time, the portion of main that runs factorialTailRec finishes absolutely fine, whereas, of course, factorial/1 crashes at the exact same integer.
Very, very interesting. It seems as if call by name in this situation maintains the stack frames because of the need of computation of the products themselves all the way back to the call chain.

How do you call a function which takes a tuple of two as an argument and returns a tuple of two as a result in Scala?

I am very new to Scala. I have been assigned the task of coding the Fast Fibonacci algorithm. I am finding it difficult when it comes to actually calling the function. The function takes a tuple of two and returns a tuple of two as a result. I don't know if my logic for fibStep is correct but I will get to that as soon as I can actually test the function. The following is what I have so far:
def fastFib(x: Long ): Long = {
def fibStep(x:(Long, Long)): (Long, Long) = {
//setting temporary variables a and b
def a = x._1
def b = x._2
//applying the fast Fibonacci algorithm
def c = a * (b * 2 - a)
def d = a * a + b * b
if (c+d % 2 == 0) return (c,d)
else return (d, c+d)
}
def tuple = (x-1,x-2)
return fibStep(tuple)
}
I need to pass the tuple (x-1,x-2) to fibStep. How do I do it? Thanks
The problem is in return statement. You trying to return tuple, instead of Long.
Fix:
def fastFib(x: Long ): Long = {
...
return fibStep(tuple)._1 // or ._2
}
Note: I'm not sure if your algorithm is correct
You've got a number of problems here.
def is used to define functions
val should be used to define variables
return should not be used. You 'return' a result simply by it being the last value in an expression.
A tuple is defined simply using parenthesis:
val myTuple = (1,2)
With this information you should be able to make a better attempt at it.

Is it possible to create a linear progression in ScalaCheck generator

I have a newbie question for ScalaCheck which I am playing around with for the first time.
Is it possible to create a Gen[Int] which will progress linearly from say 0 to N.
Such that when I use forAll in ScalaCheck it will increase the input Int by 1.
I would like this example to test with an increasing value
"Increase" should "always increase" in {
forAll(validNumbers){ i:Int =>
increase(i) should be (i + 1)
}
}
Maybe this destroys ScalaChecks purpose and I should just test this way in ScalaTest.
You could do something like this:
def validNumbers(n: Int): Gen[Int] = Gen.resultOf[Int, Int] {
new (Int => Int) {
val current = (0 to n).iterator
def apply(i: Int): Int = {
if(current.hasNext) current.next else sys.error("No more numbers")
}
}
}
However I think you are indeed right, that this destroys ScalaChecks purpose. A simple for-loop would do better in this case.

Scala tail recursion error

Below is a simple 'repeat' method I am trying to write using tail recursion. The sole purpose of this function is to just repeat the giving string back to back 'n' amount of times.
I.e. repeat("Hello",3) = "HelloHelloHello"
But for whatever reason I am getting a 'java.lang.UnsupportedOperationException' and I am not sure why.
P.S. This is a homework assignment so if I could just be pointed in the right direction instead of a straight answer that would be cool!
def repeat(s: String, n: Int): String = {
def tailRepeat(str: String, x: Int): String = x match {
case `n` => str
case _ => val repeatString = s + str
tailRepeat(repeatString, (x + 1))
}
tailRepeat(s, 0)
}
I think you are making this a little too complex. For one thing you don't really need pattern matching at all, you have a counting variable that tells you how many times to repeat your string, using that would simplify your code greatly. Also it is usually more straightforward to count down and not up:
def repeat(s: String, n: Int): String = {
def tailRepeat(str: String, x: Int): String = {
if(x == 0) str
else tailRepeat(str + s, x - 1)
}
tailRepeat(s, n - 1)
}
println( repeat("hello", 3) );
// hellohellohello

How to yield a single element from for loop in scala?

Much like this question:
Functional code for looping with early exit
Say the code is
def findFirst[T](objects: List[T]):T = {
for (obj <- objects) {
if (expensiveFunc(obj) != null) return /*???*/ Some(obj)
}
None
}
How to yield a single element from a for loop like this in scala?
I do not want to use find, as proposed in the original question, i am curious about if and how it could be implemented using the for loop.
* UPDATE *
First, thanks for all the comments, but i guess i was not clear in the question. I am shooting for something like this:
val seven = for {
x <- 1 to 10
if x == 7
} return x
And that does not compile. The two errors are:
- return outside method definition
- method main has return statement; needs result type
I know find() would be better in this case, i am just learning and exploring the language. And in a more complex case with several iterators, i think finding with for can actually be usefull.
Thanks commenters, i'll start a bounty to make up for the bad posing of the question :)
If you want to use a for loop, which uses a nicer syntax than chained invocations of .find, .filter, etc., there is a neat trick. Instead of iterating over strict collections like list, iterate over lazy ones like iterators or streams. If you're starting with a strict collection, make it lazy with, e.g. .toIterator.
Let's see an example.
First let's define a "noisy" int, that will show us when it is invoked
def noisyInt(i : Int) = () => { println("Getting %d!".format(i)); i }
Now let's fill a list with some of these:
val l = List(1, 2, 3, 4).map(noisyInt)
We want to look for the first element which is even.
val r1 = for(e <- l; val v = e() ; if v % 2 == 0) yield v
The above line results in:
Getting 1!
Getting 2!
Getting 3!
Getting 4!
r1: List[Int] = List(2, 4)
...meaning that all elements were accessed. That makes sense, given that the resulting list contains all even numbers. Let's iterate over an iterator this time:
val r2 = (for(e <- l.toIterator; val v = e() ; if v % 2 == 0) yield v)
This results in:
Getting 1!
Getting 2!
r2: Iterator[Int] = non-empty iterator
Notice that the loop was executed only up to the point were it could figure out whether the result was an empty or non-empty iterator.
To get the first result, you can now simply call r2.next.
If you want a result of an Option type, use:
if(r2.hasNext) Some(r2.next) else None
Edit Your second example in this encoding is just:
val seven = (for {
x <- (1 to 10).toIterator
if x == 7
} yield x).next
...of course, you should be sure that there is always at least a solution if you're going to use .next. Alternatively, use headOption, defined for all Traversables, to get an Option[Int].
You can turn your list into a stream, so that any filters that the for-loop contains are only evaluated on-demand. However, yielding from the stream will always return a stream, and what you want is I suppose an option, so, as a final step you can check whether the resulting stream has at least one element, and return its head as a option. The headOption function does exactly that.
def findFirst[T](objects: List[T], expensiveFunc: T => Boolean): Option[T] =
(for (obj <- objects.toStream if expensiveFunc(obj)) yield obj).headOption
Why not do exactly what you sketched above, that is, return from the loop early? If you are interested in what Scala actually does under the hood, run your code with -print. Scala desugares the loop into a foreach and then uses an exception to leave the foreach prematurely.
So what you are trying to do is to break out a loop after your condition is satisfied. Answer here might be what you are looking for. How do I break out of a loop in Scala?.
Overall, for comprehension in Scala is translated into map, flatmap and filter operations. So it will not be possible to break out of these functions unless you throw an exception.
If you are wondering, this is how find is implemented in LineerSeqOptimized.scala; which List inherits
override /*IterableLike*/
def find(p: A => Boolean): Option[A] = {
var these = this
while (!these.isEmpty) {
if (p(these.head)) return Some(these.head)
these = these.tail
}
None
}
This is a horrible hack. But it would get you the result you wished for.
Idiomatically you'd use a Stream or View and just compute the parts you need.
def findFirst[T](objects: List[T]): T = {
def expensiveFunc(o : T) = // unclear what should be returned here
case class MissusedException(val data: T) extends Exception
try {
(for (obj <- objects) {
if (expensiveFunc(obj) != null) throw new MissusedException(obj)
})
objects.head // T must be returned from loop, dummy
} catch {
case MissusedException(obj) => obj
}
}
Why not something like
object Main {
def main(args: Array[String]): Unit = {
val seven = (for (
x <- 1 to 10
if x == 7
) yield x).headOption
}
}
Variable seven will be an Option holding Some(value) if value satisfies condition
I hope to help you.
I think ... no 'return' impl.
object TakeWhileLoop extends App {
println("first non-null: " + func(Seq(null, null, "x", "y", "z")))
def func[T](seq: Seq[T]): T = if (seq.isEmpty) null.asInstanceOf[T] else
seq(seq.takeWhile(_ == null).size)
}
object OptionLoop extends App {
println("first non-null: " + func(Seq(null, null, "x", "y", "z")))
def func[T](seq: Seq[T], index: Int = 0): T = if (seq.isEmpty) null.asInstanceOf[T] else
Option(seq(index)) getOrElse func(seq, index + 1)
}
object WhileLoop extends App {
println("first non-null: " + func(Seq(null, null, "x", "y", "z")))
def func[T](seq: Seq[T]): T = if (seq.isEmpty) null.asInstanceOf[T] else {
var i = 0
def obj = seq(i)
while (obj == null)
i += 1
obj
}
}
objects iterator filter { obj => (expensiveFunc(obj) != null } next
The trick is to get some lazy evaluated view on the colelction, either an iterator or a Stream, or objects.view. The filter will only execute as far as needed.