Recursive to Tail-recursive in scala - scala

I have the following code
object TailRec
{
def func1(n:Int) : Int =
{
if (n < 10)
func2(n)
else
func1(n/10) + func2(n % 10)
}
def func2(n: Int) : Int =
{
#tailrec def _func2(n: Int, result: Int): Int =
{
if (n <= 1)
result
else
_func2(n-1,n*result)
}
_func2(n,1)
}
def test(n: Int) : Boolean =
{
if (n > 2)
n == func1(n)
else
false
}
}
I managed to rewrite func2 but I am not quite sure how to convert the bool function. I thought about match and case but I still need to call func1 to get the result for comparison. The other problem is how to break up the double function call in func1 itself. Any hints?

You have already converted func2 into tail-recursive form.
Similarly, using an additional accumulator, you can convert func1 into a tail-recursive form (I have modified the interface of func1, but you could also create another inner helper function). Since test isn't recursive, nothing has to be done here.
import scala.annotation.tailrec
object TailRec {
#tailrec def func1(n:Int, acc: Int): Int = {
if (n < 10) func2(n)
else func1(n / 10, acc + func2(n % 10))
}
def func2(n: Int): Int = {
#tailrec def _func2(n: Int, result: Int): Int = {
if (n <= 1) result
else _func2(n-1,n*result)
}
_func2(n,1)
}
def test(n: Int): Boolean = (n > 2) && (n == func1(n, 0))
}

Related

Non-numerical type returned by curried function

New to Scala and functional programming in general. Have the following code snippet which means to calculate the sum over a closed interval of Ints. Have implemented both tail-recursive method (sum1) and non-tail-recursive method (sum2).
package test
import scala.annotation.tailrec
object Currying extends App{
def sum1(f:Int=>Int)(a:Int, b:Int): (Int, Int) => Int = {
require(a <= b, "Received a=" + a + " and b=" + b)
#tailrec
def sum(a:Int, acc:Int) : Int = {
if(a > b) acc
else sum(a+1, acc + f(a))
}
sum
}
println("sum1(x=>x*x)(1, 4)=" + sum1(x=>x*x)(1, 4))
println("sum1(x=>x*x*x)(1, 4)=" + sum1(x=>x*x*x)(1, 4))
def sum2(f:Int=>Int)(a:Int, b:Int): Int => Int = {
def sum(a:Int) : Int = {
if(a > b) 0
else f(a) + sum(a+1)
}
sum
}
println("sum2(x=>x*x)(1, 4)=" + sum2(x=>x*x)(1, 4))
println("sum2(x=>x*x*x)(1, 4)=" + sum2(x=>x*x*x)(1, 4))
}
The print-outs, however, do not return actual Ints, but what appears to be a function itself:
sum(x=>x*x)(1, 4)=week2.Currying$$$Lambda$12/1468177767#3d24753a
sum(x=>x*x*x)(1, 4)=week2.Currying$$$Lambda$12/1468177767#67b64c45
sum2(x=>x*x)(1, 4)=week2.Currying$$$Lambda$15/1626877848#2f7a2457
sum2(x=>x*x*x)(1, 4)=week2.Currying$$$Lambda$15/1626877848#6108b2d7
Process finished with exit code 0
Clearly I'm doing something dumb in the currying, but I can't for the life of me figure it out.

Scala Implicit class (using implicits inside implicit class) - Not a member of Int error

I want to write a totient-function with scala (recursive).
Euler's totient function counts the positive integers up to a given integer n that are relatively prime to n
I came up with:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
private def isDividable(divisor: Int) = number % divisor == 0
}
}
For readability I created a small function isDividable.
This function I want to use in my recursive helper-method.
Unfortunately I get the following error:
Error:(12, 22) value isDividable is not a member of Int
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
Question: Can someone explain to me, what I did wrong and how I can fix it?
Edit:
for completeness I will add the valid implementation of the totient function:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 0) accumulator
else {
if (number.isCoprimeTo(currentN)) helper(currentN - 1, accumulator + 1)
else helper(currentN - 1, accumulator)
}
helper(number, 0)
}
private[Totient] def isCoprimeTo(otherNumber: Int): Boolean = {
gcd(number, otherNumber) == 1
}
private def gcd(firstNumber: Int, secondNumber: Int): Int =
if (secondNumber == 0) firstNumber else gcd(secondNumber, firstNumber % secondNumber)
}
}
private without extra information mean here "accessible only by other methods of Improvements but for the same instance of Improvements".
That means you can call isDividable to get the result for the same number for which you call totient/helper, but it doesn't becomes an extension method (because it is not visible outside of Improvements).
To fix that you can change the scope of the method, e.g. to make it visible to all methods defined within Totient:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
// notice [Totient] after private
private[Totient] def isDividable(divisor: Int) = number % divisor == 0
}
}
This compiles in my ammonite and works:
# import Totient._
import Totient._
# 12.totient
res2: Int = 6
Another option is to call isDividable/isCoprimeTo from this instead of number. This way, the compiler doesn't have to perform an implicit resolution at all to get the method. With your original code:
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (this.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
(You can even leave out the call to this entirely and simply have isDividable(currentN), but that makes the code less clear.)

Structure to allow #tailrec when multiple recursive calls are invoked

The following logic identifies the combination of integers summing to n that produces the maximum product:
def bestProd(n: Int) = {
type AType = (Vector[Int], Long)
import annotation._
// #tailrec (umm .. nope ..)
def bestProd0(n: Int, accum : AType): AType = {
if (n<=1) accum
else {
var cmax = accum
for (k <- 2 to n) {
val tmpacc = bestProd0(n-k, (accum._1 :+ k, accum._2 * k))
if (tmpacc._2 > cmax._2) {
cmax = tmpacc
}
}
cmax
}
}
bestProd0(n, (Vector(), 1))
}
This code does work:
scala> bestProd(11)
res22: (Vector[Int], Long) = (Vector(2, 3, 3, 3),54)
Now it was not a surprise to me that #tailrec did not work. After all the recursive invocation is not in the tail position. Is is possible to reformulate the for loop to instead do a proper single-call to achieve the tail recursion?
I don't think it's possible if you're trying to stick close to the stated algorithm. Rethinking the approach you could do something like this.
import scala.annotation.tailrec
def bestProd1(n: Int) = {
#tailrec
def nums(acc: Vector[Int]): Vector[Int] = {
if (acc.head > 4)
nums( (acc.head - 3) +: 3 +: acc.tail )
else
acc
}
val result = nums( Vector(n) )
(result, result.product)
}
It comes up with the same results (as far as I can tell) except for I don't split 4 into 2,2.

Sum of Factorials from a to b in scala

I'm trying to write a function in scala that finds the Sum of any (passed) function from a to b. Additionally , I'm trying to do it in a tail-wise recursive manner. I managed a tailwise recursive factorial function , so now i want to pass it to the "Summation" function and have it find the sum of all factorials from lower-bound a to upper-bound b . Here's what i have so far
object Sum {
def Summation( f : Double => Double , a: Double , b: Double):Double = {
def tailwiseSummation(accumulator:Double , count:Double):Double = {
if(count > b) accumulator
else tailwiseSummation(accumulator + f, a+1) // i dont know what to do here
}
}
def Factorial(num: Double): Double = { // i want to pass this function to `Summation`
def tailwise(accumulator: Double, deprecator: Double): Double = {
if (deprecator == 0) accumulator
else tailwise(accumulator * deprecator, deprecator - 1) // deprecator deprecating 1 unit at a time
}
tailwise(1, num)
}
}
can someone please help ?
You almost have it. Call f with count and add 1 to count in the recursive call tailwiseSummation. Also, you need the initialization function tailwiseSummation(f(a), a + 1) just like Factorial.
object Sum {
def Summation( f : Double => Double , a: Double , b: Double):Double = {
def tailwiseSummation(accumulator:Double , count:Double):Double = {
if(count > b) accumulator
else tailwiseSummation(accumulator + f(count), count+1)
}
// accumulator starts with f(a) , so count starts from a+1 to remove off-by-one error
tailwiseSummation(f(a), a + 1)
}
def Factorial(num: Double): Double = {
def tailwise(accumulator: Double, deprecator: Double): Double = {
if (deprecator == 0) accumulator
else tailwise(accumulator * deprecator, deprecator - 1) // deprecator deprecating 1 unit at a time
}
tailwise(1, num)
}
}
Run it:
scala> Sum.Summation(Sum.Factorial(_), 1, 5)
res0: Double = 153.0
Generic recursion over the range could be something like that :
def makeSum(f: Double => Double, a:Double, b:Double, step:Double = 1.0):Double = {
def makeSumAcc(f:Double =>Double, a:Double, b:Double, acc:Double) = {
if (a>=b) acc
else makeSumAcc(f, a+step, b, acc+f(a))
}
makeSum(f, a, b, 0)
}

StackOverflowError for coin change in Scala?

I'm writing a recursive function for the Coin (change) problem in Scala.
My implementation breaks with StackOverflowError and I can't figure out why it happens.
Exception in thread "main" java.lang.StackOverflowError
at scala.collection.immutable.$colon$colon.tail(List.scala:358)
at scala.collection.immutable.$colon$colon.tail(List.scala:356)
at recfun.Main$.recurs$1(Main.scala:58) // repeat this line over and over
this is my call:
println(countChange(20, List(1,5,10)))
this is my definition:
def countChange(money: Int, coins: List[Int]): Int = {
def recurs(money: Int, coins: List[Int], combos: Int): Int =
{
if (coins.isEmpty)
combos
else if (money==0)
combos + 1
else
recurs(money,coins.tail,combos+1) + recurs(money-coins.head,coins,combos+1)
}
recurs(money, coins, 0)
}
Edit: I just added the else if statement in the mix:
else if(money<0)
combos
it got rid of the error but my output is 1500 something :( what is wrong with my logic?
The first solution in the accepted answer has a redundant last parameter as noted by Paaro so I wanted to get rid of it. The second solution uses map which I wanted to avoid since it wasn't covered yet in the Week 1 or the Scala course I assume you're taking. Also, the second solution, as rightly noted by the author, would be way slower, unless it uses some memoization. Finally, Paaro's solution seems to have an unnecessary nested function.
So here's what I ended up with:
def countChange(money: Int, coins: List[Int]): Int =
if (money < 0)
0
else if (coins.isEmpty)
if (money == 0) 1 else 0
else
countChange(money, coins.tail) + countChange(money - coins.head, coins)
There is no need for braces here, as you can see.
I wonder if it could be further simplified.
Here is the correct solution based on your codes:
def countChange(money: Int, coins: List[Int]): Int = {
def recurs(m: Int, cs: List[Int], cnt: Int): Int =
if(m < 0) cnt //Not a change, keep cnt
else if(cs.isEmpty) {
if(m == 0) cnt + 1 else cnt // plus cnt if find a change
}
else recurs(m, cs.tail, cnt) + recurs(m-cs.head, cs, cnt)
recurs(money, coins, 0)
}
Anyway, there is a short solution(But not efficient, you can cache the middle result to make it efficient.)
def countChange(m: Int, cs: List[Int]): Int = cs match {
case Nil => if(m == 0) 1 else 0
case c::rs => (0 to m/c) map (k => countChange(m-k*c,rs)) sum
}
One can omit the cnt parameter, which is, in fact, never accumulated. The recurs function always returns either 0 or 1, so the optimized algorithm would be:
def countChange(money: Int, coins: List[Int]): Int = {
def recurs(m: Int, cs: List[Int]): Int =
if(m < 0) 0 //Not a change, return 0
else if(cs.isEmpty) {
if(m == 0) 1 else 0 // 1 if change found, otherwise 0
}
else recurs(m, cs.tail) + recurs(m-cs.head, cs)
if(money>0) recurs(money, coins) else 0
}
The #Eastsun solution is good but it fails when money=0 due to it returns 1 instead of 0, but you can fix it easily:
def countChange(money: Int, coins: List[Int]): Int = {
def recurs(m: Int, cs: List[Int], cnt: Int): Int =
if(m < 0) cnt //Not a change, keep cnt
else if(cs.isEmpty) {
if(m == 0) cnt + 1 else cnt // plus cnt if find a change
}
else recurs(m, cs.tail, cnt) + recurs(m-cs.head, cs, cnt)
if(money>0) recurs(money, coins, 0) else 0
}
here is a DP approach to reduce a lot of re-calculation in recursive approach
object DP {
implicit val possibleCoins = List(1, 5, 10, 25, 100)
import collection.mutable.Map
def countChange(amount: Int)(implicit possibleCoins: List[Int]) = {
val min = Map((1 to amount).map (_->Int.MaxValue): _*)
min(0) = 0
for {
i <- 1 to amount
coin <- possibleCoins
if coin <= i && min(i - coin) + 1 < min(i)
} min(i) = min(i-coin) + 1
min(amount)
}
def main(args: Array[String]) = println(countChange(97))
}
see DP from novice to advanced for algorithm
Idea from https://github.com/pathikrit/scalgos/blob/9e99f73b4241f42cc40a1fd890e72dbeda2df54f/src/main/scala/com/github/pathikrit/scalgos/DynamicProgramming.scala#L44
case class Memo[K,I,O](f: I => O)(implicit i2k:I=>K ) extends (I => O) {
import scala.collection.mutable.{Map => Dict}
val cache = Dict.empty[K, O]
override def apply(x: I) = cache getOrElseUpdate (x, f(x))
}
def coinchange(s: List[Int], t: Int) = {
type DP = Memo[ (Int, Int), (List[Int], Int),Seq[Seq[Int]]]
implicit def encode(key: (List[Int], Int)):(Int,Int) = (key._1.length, key._2)
lazy val f: DP = Memo {
case (Nil, 0) => Seq(Nil)
case (Nil, _) => Nil
case (_, x) if x< 0 => Nil
case (a :: as, x) => f(a::as, x - a).map(_ :+ a) ++ f(as, x)
}
f(s, t)
}