The below function is overflowing, and I don't understand why. When run with x as 0, y as 0 and dim as 2, the result should be 6. However, I am getting an error indicating that some Long value in the function (either x or y) is 554 at the time of overflow. This should not be possible as x and y are both bounded by the dim value, which in my test is set to 2.
Here is the code:
def lattice(dim: Long, x: Long, y: Long): Long = {
if (x == dim && y == dim) {
1
}
if (x >= dim) {
lattice(dim,x,y+1L)
}
if (y >= dim) {
lattice(dim,x+1L,y)
}
else {
lattice(dim,x+1L,y) + lattice(dim,x,y+1L)
}
}
You are missing else in two places. This means that your final line runs even when x >= dim, causing x to exceed dim. Try this instead:
if (x == dim && y == dim) {
1
} else if (x >= dim) {
lattice(dim,x,y+1L)
} else if (y >= dim) {
lattice(dim,x+1L,y)
} else {
lattice(dim,x+1L,y) + lattice(dim,x,y+1L)
}
Chris:
Youd function is not tail recursive because in your last statement you have a sum. By chance this sum involves two calls to lattice. However, to be tail recursive your last statament must be a constant (like you did in your first if) or just a call to function itself (such as your 2 else ifs.
I admit that I don't know how to change your function to be tail recursive. Depending of your alghoritm, perhaps it is not possible to do your function tail recursive.
Thanks,
Rafael Afonso
Related
I've been working on the scala recursion problem. I used to develop the program using loops and then use the concept of recursion to convert the existing loop problem in a recursive solution.
So I have written the following code to find the perfect number using loops.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
while ( {
i * i <= n
}) {
if (n % i == 0) if (i * i != n) sum = sum + i + n / i
else sum = sum + i
i += 1
}
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum == n && n != 1) return true
false
}
Here is my attempt to convert it into a recursive solution. But I'm getting the incorrect result.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
def loop(i:Int, n:Int): Any ={
if(n%i == 0) if (i * i != n) return sum + i + n / i
else
return loop(i+1, sum+i)
}
val sum_ = loop(2, n)
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum_ == n && n != 1) return true
false
}
Thank you in advance.
Here is a tail-recursive solution
def isPerfectNumber(n: Int): Boolean = {
#tailrec def loop(d: Int, acc: List[Int]): List[Int] = {
if (d == 1) 1 :: acc
else if (n % d == 0) loop(d - 1, d :: acc)
else loop(d - 1, acc)
}
loop(n-1, Nil).sum == n
}
As a side-note, functions that have side-effects such as state mutation scoped locally are still considered pure functions as long as the mutation is not visible externally, hence having while loops in such functions might be acceptable.
I tried to write a function for fast power in scala, but I keep getting java.lang.StackOverflowError. I think it has something to do with two slashes that use in the third line when I recursively called this function for n/2.
Can someone explain why is this happening
def fast_power(x:Double, n:Int):Double = {
if(n % 2 == 0 && n > 1)
fast_power(x, n/2) * fast_power(x, n /2)
else if(n % 2 == 1 && n > 1)
x * fast_power(x, n - 1)
else if(n == 0) 1
else 1 / fast_power(x, n)
}
Your code doesn't terminate, because there was no case for n = 1.
Moreover, your fast_power has linear runtime.
If you write it down like this instead:
def fast_power(x:Double, n:Int):Double = {
if(n < 0) {
1 / fast_power(x, -n)
} else if (n == 0) {
1.0
} else if (n == 1) {
x
} else if (n % 2 == 0) {
val s = fast_power(x, n / 2)
s * s
} else {
val s = fast_power(x, n / 2)
x * s * s
}
}
then it is immediately obvious that the runtime is logarithmic, because
n is at least halved in every recursive invocation.
I don't have any strong opinions on if-vs-match, so I just sorted all the cases in ascending order.
Prefer the match construct instead of multiple if/else blocks. This will help you isolate the problem you have (wrong recursive call), and write more understandable recursive functions. Always put the termination conditions first.
def fastPower(x:Double, m:Int):Double = m match {
case 0 => 1
case 1 => x
case n if n%2 == 0 => fastPower(x, n/2) * fastPower(x, n/2)
case n => x * fastPower(x, n - 1)
}
I went step by step looking at this function and it seems to me that it should avoid calling sortedCoins(0-1) by using only sortedCoins(0) and terminating when y == -1, but somehow it doesn't. Why?
def countChange(amount: Int, coins: List[Int]): Int = {
var x = coins.length
var y = x
val sortedCoins = coins.sortWith(_ < _)
def cc(amount: Int, x: Int): Int = {
y -= 1
if (amount == 0) 1
else if (y == 0) cc(amount - x, sortedCoins(y))
else if (amount < 0 || y == -1) 0
else cc(amount, sortedCoins(y - 1)) + cc(amount - x, sortedCoins(y))
}
cc(amount, x)
}
You need to rethink way in which you are writing this algorithm. You see your y variable is "global" scope in your recursive function, when you execute your function it will go to
cc(amount, sortedCoins(y - 1)) + cc(amount - x, sortedCoins(y))
multiple times, and it will execute first side of equation and it will decrement y every time. Then, y will become 0 and your
else if (y == 0) cc(amount - x, sortedCoins(y))
line will be executed, next because y=-1 your
else if (amount < 0 || y < 0) 0
line will be executed. And here we come to exception, because this line returned 0, recursively second part of equation of last else will be executed, which is
cc(amount - x, sortedCoins(y))
, and right now y=-1, that is why you have this exception. I hope this is understandable.
I've created this simple anonymous function
var b = (x : Int) => if(x % 2 == 0) x + 1 else x
and it works great. After that I tried to add another statement after the if and before the x+1 statement.
var b = (x : Int) => if(x % 2 == 0) println(x) x + 1 else x
and a that point I received the following compiler error
Cannot resolve symbol x
Please can anyone let me know why this happen?
The reason this happens is that although Scala does not require the use of semi-colons most of the time (unlike Java), since the compiler is more equipped to infer where statements/expressions end, if you have 2 statements/expressions on 1 line then you need to separate them for the compiler.
Your first anonymous function works since if(x % 2 == 0) x + 1 else x is 1 expression.
The compiler is complaining with the second one though since if(x % 2 == 0) println(x) is considered 1 statement. Hence, the next statement starts and there is now no context for x.
Other posters have given you a solution to break the right-side of the function down into separate statements so I won't duplicate - just adding an explanation of why the compilation error occurs since you said you are learning the language. Google about the use of semi-colons in Scala to find out more.
Use this. You need the braces to indicate these are multiple lines:
var b = (x : Int) => if(x % 2 == 0) {
println(x)
x + 1
} else x
Or you can do this.. you need to put that semi colon to indicate to compiler they are separate statements:
var b = (x : Int) => if(x % 2 == 0) { println(x); x + 1 } else x
I hope this question is not a dupe. It seems most questions refer to multiple recursive calls in one statement, ie.:return func(n - 1) * func(n - 2). My question involves multiple recursive calls inside an if/else statement. THis is what I have (from doing a Project Euler problem):
def multOfThreeAndFive(n: Double): Double = {
def loop(next: Double, acc: Double): Double = {
if (next < 0) acc
else if (next % 3 == 0 || next % 5 == 0) loop(next - 1, acc + next)
else loop(next - 1, acc)
}
loop(n - 1, 0)
}
My question is, since I'm making two separate recursive calls, one inside else if and the other inside the last else, is this still considered tail recursive?
It's easy to check by yourself with special annotation. Compilation will fail if compiler isn't able to optimize code down to tail-recursion emulation:
def multOfThreeAndFive(n: Double): Double = {
#annotation.tailrec
def loop(next: Double, acc: Double): Double = {
if (next < 0) acc
else if (next % 3 == 0 || next % 5 == 0) loop(next - 1, acc + next)
else loop(next - 1, acc)
}
loop(n - 1, 0)
}
And yes, it is considered as a tail recursive function.