Stackoverflow error on factorial using recursion on ktolin - recursion

This is my code
This gives stack overflow error 30 times on the output console
fun main(args:Array<String>){
var no:Int=Integer.parseInt(readLine())//read input from user and convert to Integer
var ans:Int=calculateFact(no) //call function and store to ans variable
println("Factorial of "+no+" is "+ans) //print result
}
fun calculateFact(no:Int):Int //function for recursion
{
if(no==0) {
return 1 }
return (no*calculateFact(no))
}
I don't know what is error
solve plz

You should return
no*calculateFact(no - 1)
not
no*calculateFact(no)
otherwise the recursion can never end.

Other than the mistake in the recursion that was already pointed out, it's worth mentioning that your method will still only work correctly for numbers up to 12, since 13! is larger than the maximum value that you can store in an Int. Therefore, for numbers 13 and up, you'll essentially get "random" results due to overflow.
If you just use BigInteger instead, it will work until the call stack gets too deep and causes a stack overflow, this happens around 8000 on my machine.
fun calculateFact(no: BigInteger): BigInteger {
if (no == BigInteger.ZERO) {
return BigInteger.ONE
}
return (no * calculateFact(no - BigInteger.ONE))
}
fun main(args: Array<String>) {
val no: BigInteger = BigInteger(readLine())
val ans: BigInteger = calculateFact(no)
println("Factorial of $no is $ans")
}
If you want to handle numbers larger than that, you can use a tailrec function (this specific solution is taken from this article):
tailrec fun calculateFact(acc: BigInteger, n: BigInteger): BigInteger {
if (n == BigInteger.ZERO) {
return acc
}
return calculateFact(n * acc, n - BigInteger.ONE)
}
fun calculateFact(n: BigInteger) : BigInteger {
return calculateFact(BigInteger.ONE, n)
}
fun main(args: Array<String>) {
val n: BigInteger = BigInteger(readLine())
val ans: BigInteger = calculateFact(n)
println("Factorial of $n is $ans")
}
This will work for numbers up to a couple hundred thousand, your problem with this one will become the time it takes to run instead of the memory constraints.

fun main(args:Array<String>) {
var no:Int = Integer.parseInt(readLine()) //read input from user and convert to Integer
var ans:Int=calculateFact(no) //call function and store to ans variable
println("Factorial of "+no+" is "+ans) //print result
}
fun calculateFact(no:Int):Int { //function for recursion
if(no==0) {
return 1
}
return (no*calculateFact(no - 1)) // you forgot to decrease the no here.
}
If you didnot decrease no then it will call the calculateFact() method all the time. Please check the code, it will work.

Related

how to create kotlin infix function with 2 words?

fun main(args: Array<String>) {
var arr = IntArray(10)
println(arr get size) // prints size of arr
arr print all //prints all elements of arr
I think "get size" is 2 infix function, get and size, and get function takes argument of size function result, and prints take argument of "all" function result, any solutions?
What you are trying to achieve doesn't make much sense and you shouldn't implement such things in production. Just for educational propose, something similar can be achieved:
infix fun <T> Array<T>.get(parameter: String): Int {
when(parameter) {
"size" -> return this.size
}
throw NotImplementedError()
}
and usage would be:
println(array get "size")
Edit:
The version where you would call array get size will look the following:
enum class GetType { size }
infix fun <T> Array<T>.get(parameter: GetType): Int {
when(parameter) {
GetType.size -> return this.size
}
However if you want to call size instead of GetType.size then you need to import everything in the enum class:
import GetType.*

Correctly returning Int from Hashmap in a function

I have a function in Kotlin which takes in an Int argument and return a value based on a formula. To speed things up I store intermediate results in a HashMap<Int, Int>
private val calculatedResults = HashMap<Int, Int>()
private fun q2(n: Int): Int {
if(calculatedResults.containsKey(n)) {
return calculatedResults[n]
}
val q = ...
calculatedResults[n] = q
return q
}
I'm getting a type mismatch of Int found but Int? required at
return calculatedResults[n]
Im not sure how to correctly write this. I had
return calculatedResults[n]!!
But I'm not sure, if it's a bit hacky.
Should the return type of the function be Int? because while the HashMap might contain the key n the value could be null? Wouldn't that mean the HashMap should be <Int, Int?>?
getOrPut will check if a value exists for n. If the value exists, it will be returned. If the values does not exist the value returned by the lambda will be assigned and afterwards returned by getOrPut.
Take a look at this example:
fun calculate(n: Int) = n * 5 // some calculation
private fun q2(n: Int) = calculatedResults.getOrPut(n) {
calculate(n)
}
Should the return type of the function be Int? because while the
HashMap might contain the key n the value could be null? Wouldn't that
mean the HashMap should be ?
In this case the answer to the question is obviously "no" because if the value is missing you just add it. So, the value returned by q2 can never be null.
The underlying problem is that calculatedResults could have been modified by an other thread between contains (if(calculatedResults.containsKey(n))) and get (return calculatedResults[n]).
Even after checking with containsKey calculatedResults[n] could therefore possibly return a wrong result, including null, and this way of checking should be avoided.
Using !! should generally only be used when absolutely necessary, because it can cause a NPE. It definitely is hacky.
Use the following syntax to overcome the problem:
calculatedResults[n]?.let {
return it
}
Basically this is a nice way of saying
val result = calculatedResults[n]
if(result != null) {
return result
}
see https://kotlinlang.org/docs/reference/null-safety.html#safe-calls
Even better is to use the built-in getOrPut:
private fun q2(n: Int): Int {
return calculatedResults.getOrPut(n) { calcQ() }
}
private fun calcQ(): Int {
val q = ...
return q
}
Should the return type of the function be Int? because while the HashMap might contain the key n the value could be null? Wouldn't that mean the HashMap should be <Int, Int?>?
No, you did exactly the right thing when you defined the method signature. The compiler only complained because what happened within the method did not fit it. If you change the method signature you just move the problem to the function calling q2 without handling it.
You should consider re-writing this to more idiomatic code. It's a rather basic task to compute a value if it is not set in the map already:
fun q2(n: Int): Int {
return calculatedResults.getOrPut(n) {
42 //q
}
}

Recursive anonymus function in kotlin

Im making this anonymus function, and i need it to call itself. Is there any way to do it? I tried the code below, which didnt work...
val example:Char = fun () : Char {
//Some code
if(condition) {
return this();
}
}
What should i replace 'this()' with?
Im pretty new to kotlin, so it would be really helpful with a response
You can't name anonymous functions (either with this syntax, or as a lambda) in Kotlin, and therefore you can't make them recursive either, because you have know way to reference themselves.
If you need recursion, you'll have to create a regular function, and call that:
fun helper() : Char {
if (condition) {
return helper();
}
...
}
val example = helper()
The good news is that you can basically create a regular, named function in any scope. They can be top level outside classes, class members, or just local functions nested within other functions. Wherever you can write down val example = ..., you can also create a function.
Calling an anonymous function sound complicated as there is no name to call it with :)
As I'm learning Kotlin myself at the moment, I tried something and came up with this, hope it helps:
import kotlin.test.Test
import kotlin.test.assertEquals
class StackOverflow51233329 {
#Test
fun test() {
var letter = 'A'
lateinit var example: () -> Char
example = {
letter++
if (letter >= 'C') letter else example()
}
assertEquals('C', example())
}
}
If you want to avoid using lateinit, you could use the Y combinator, which can be used to enable recursion when recursion is impossible directly. Declare this globally:
class RecursiveFunc<T, R>(val f: (RecursiveFunc<T, R>) -> (T) -> R)
fun <T, R> y(f: ((T) -> R) -> (T) -> R): (T) -> R {
val rec = RecursiveFunc<T, R> { r -> f { r.f(r)(it) } }
return rec.f(rec)
}
This code was taken from Rosetta Code. You use it like this:
val fac = y { f: ((Int) -> Int) ->
{ n: Int ->
if (n <= 1) 1 else n * f(n - 1)
}
}
println(fac(10))
f is the recursive function here, with a signature of (Int) -> Int. The rest of the function is pretty much the same as usual, but in lambda form. You can even use the usual function syntax if that's more familiar:
val fac = y { f: (Int) -> Int ->
fun(n: Int): Int {
return if (n <= 1) 1 else n * f(n - 1)
}
}

Recursive factorial returns 0 for large input

The answer returned by the following Java code is 0. Can anyone help me find the error?
public class ComplexityOrder {
public static void main(String[] args) {
ComplexityOrder co = new ComplexityOrder();
co.Order(1000);
}
public double Order(int n) {
int[] a = new int[10];
a[0] = Fact(n);
System.out.println("Factorial " + a[0]);
return a[0];
}
public static int Fact(int n) {
if (n == 0 || n ==1) {
return 1;
} else {
return n * Fact(n - 1);
}
}
}
The max value int can contain is 2^32 and 1000! is too big for int to contain it. You can use java.math.BigInteger for the purpose. The BigInteger class allocates as much memory as it needs to hold all the bits of data it is asked to hold. There are, however, some practical limits, dictated by the memory available.
Using BigInteger your code will somewhat look like:
import java.math.BigInteger;
public class ComplexityOrder {
public static void main(String[] args) {
ComplexityOrder co = new ComplexityOrder();
co.Order(1000);
}
public BigInteger Order(int n) {
BigInteger[] a = new BigInteger[10];
a[0] = fact(n);
System.out.println("Factorial " + a[0]);
return a[0];
}
public static BigInteger fact(int n) {
if (n == 0 || n ==1) {
return BigInteger.ONE;
} else {
return fact(n-1).multiply(BigInteger.valueOf(n));
}
}
}
Also, I don't see any point using the array.
that is because of the overflow of int variable that maximum contain number = 2^32 , and Fact(1000) is more than Max int, if you don't acquire numbers leas than 100 you can use BigInteger class instead of int , if you acquire big numbers you have to implement your string addition function to avoid overflow .
To be more specific ...
You are using standard integers, an n-bit signed binary number. You then compute 1000! This is a very large number compared to any standard integer representation. The prime factorization includes 2^994. This means that the resulting number, in binary, ends with a string of 994 zeroes.
When integer overflow isn't handled as an exception, the condition is a highly informal way of reducing your result mod 2^n, where n is the length of the internal representation, usually 32 or 64 bits, and then mapping the higher half of the range to negative numbers. A number that ends in at least n zeroes will get reduced to 0 (mod 2^n). That's what happened in your case, as your computer does not have 1024-bit integers. :-)
As others have already suggested, you can handle this capacity by switching to BigInteger and adjusting your class to deal with the expanded range. Do note that it will be much slower, as you are beyond the hardware's native integer range, and the processing resembles doing all operations by hand in base 2^n. "Write down the 00110111001010010110110001010110, carry the 1, and on to the next column." :-)

Issue with Recursive Methods ("missing return statement")

so I have a program that is running a bunch of different recursive methods, and I cannot get it to compile/run. The error is in this method, according to my computer:
public static int fibo(int n)
// returns the nth Fibonacci number
{
if (n==0)
{
return 0;
}
else if (n==1)
{
return 1;
}
else if (n>1)
{
return fibo(n-1) + fibo(n-2);
}
}
I have this method called correctly in my main method, so the issue is in this bit of code.
I think I can help you in this. Add return n; after your else if. Outside of the code but before the last curlicue.
The code will work as long as n ≥ 0 btw; another poster here is right in that you may want to add something to catch that error.
Make sure all possible paths have a return statement. In your code, if n < 0, there is no return statement, the compiler recognizes this, and throws the error.
public static int fibo(int n)
// returns the nth Fibonacci number
{
if (n<=0)
{
return 0;
}
else if (n==1)
{
return 1;
}
else // All other cases, i.e. n >= 1
{
return fibo(n-1) + fibo(n-2);
}
}

Resources