Issue with recursion because thread suspension - java

I was playing around with a few practice problems in Java. I wrote a recursive program for program given below. My solution is right except for the suspended (which I believe) gets back to active state and changes the value of the recursive method. I have also added a screenshot of Eclipse in debug mode where the thread stack is shown.
package com.nix.tryout.tests;
/**
* For given two numbers A and B such that 2 <= A <= B,
* Find most number of sqrt operations for a given number such that square root of result is a whole number and it is again square rooted until either the
* number is less than two or has decimals.
* example if A = 6000 and B = 7000, sqrt of 6061 = 81, sqrt of 81 = 9 and sqrt of 9 = 3. Hence, answer is 3
*
* #author nitinramachandran
*
*/
public class TestTwo {
public int solution(int A, int B) {
int count = 0;
for(int i = B; i > A ; --i) {
int tempCount = getSqrtCount(Double.valueOf(i), 0);
if(tempCount > count) {
count = tempCount;
}
}
return count;
}
// Recursively gets count of square roots where the number is whole
private int getSqrtCount(Double value, int count) {
final Double sqrt = Math.sqrt(value);
if((sqrt > 2) && (sqrt % 1 == 0)) {
++count;
getSqrtCount(sqrt, count);
}
return count;
}
public static void main(String[] args) {
TestTwo t2 = new TestTwo();
System.out.println(t2.solution(6550, 6570));
}
}
The above screenshot is from my debugger and I've circled the Thread stack. Can anyone try and run the program and let me know what the problem is and what would be the solution? I could come up with a non recursive solution.

Your recursion is wrong, since the value of count will return in any case 0 or 1 even if it goes deep down into recursive calls. Java is pass by value, meaning that modifying the value of a primitive inside of a method wont be visible outside of that method. In order to correct this, we can write the following recursion:
private int getSqrtCount(Double value) {
final Double sqrt = Math.sqrt(value);
if((sqrt > 2) && (sqrt % 1 == 0)) {
return getSqrtCount(sqrt) + 1;
}
return 0;
}

Your code is wrong, you should have
return getSqrtCount(sqrt, count);
instead of
getSqrtCount(sqrt, count);
Otherwise the recursion is pointless, you're completely ignoring the result of the recursion.

Related

How to exit from a method, i.e how can i return from a function in this recursion in java?

How to exit from a method, i.e how can i return from a function in this recursion in java?
public class solution {
public static int countZerosRec(int input){
int n=0;
int k =0;
int count=0;
//Base case
if(n==0)
{
return; // How can i return the method from here, i.e how can i stop the execution of the recursive program now.
}
k=input%10;
count++;
n=input/10;
countZerosRec(n);
int myans=count;
return myans;
}
}
Please help me getting out of this method.
This is a program to count number of zeroes.
Example, 34029030 ans = 3
You can try below approach:
public class MyClass {
public static void main(String args[]) {
System.out.println("total zeroes = " + returnZeroesCount(40300));
}
public static int returnZeroesCount(int input){
if(input == 0)
return 0;
int n = input % 10;
return n == 0 ? 1 + returnZeroesCount(input / 10) : returnZeroesCount(input / 10);
}
}
How it works: Assuming your input > 0, we try to get the last digit of the number by taking the modulus by 10. If it is equal to zero, we add one to the value that we will return. And what will be the value that we would be returning? It will be the number of zeroes present in the remaining number after taking out the last digit of input.
For example, in the below case, 40300: we take out 0 in first step, so we return 1+number of zeroes in 4030. Again, it appears as if we have called our recursive function for the input 4030 now. So, we again return 1+number of zeroes in 403.
In next step, since last number is 3, we simply return 0+total number of zeroes in 40 or simply as total number of zeroes present in 40 and so on.
For ending condition, we check if the input is itself 0. If it is zero then this means that we have exhausted the input number and there are no further numbers to check for. Hence, we return zero in that case. Hope this helps.
If your main focus is to find number of zeroes in a given number , You can use this alternatively:
int numOfZeroes =0;
long example = 670880930;
String zeroCounter = String.valueOf(example);
for(int i=0; i< example.length();i++){
if(zeroCounter.charAt(i) ==0){
numOfZeroes++;
}
}
System.out.print("Num of Zeros are"+ numOfZeroes);` `
Instead of posting a code answer to your question, I'll post a few pointers to get you moving.
As #jrahhali said, as your code is, it'll not get past the return
statement inside the if block(which is an error BTW, because you have an int return
type).
I'd recommend that you move the last two lines to some calling
function(such as a main method). That way all this function will
need to do is do some basic processing and move forward.
You aren't checking k at all. As it is, your count is going to
always increment.
Hope this much is enough for you to figure things out.
int count =0;
private int getZeroCount(int num){
if(num+"".length == 1){
if(num==0){
count++;
}
return count;
}
if(num%10 == 0){
count++;
}
num /= 10;
getZeroCount();
}
Method1 :
public static int countZero1(int input) {
int count = 0;
//The loop takes the remainder for the value of the input, and if it is divided by 10, then its number of digits is 0.
// When the value of the input is less than 0, the cycle ends
while (input >0){
if (input % 10 == 0){
count ++;
}
input /= 10;
}
return count;
}
Method2 :
private static int count = 0;
public static int countZero2(int input) {
//Recursive call function
if (input % 10 == 0){
count ++;
}
input /= 10;
if (input <= 0){
return count;
}else {
return countZero2(input);
}
}

Sort a number's digits recursively in Java

I'm very new to programming, just learned it in university. I have a task where I have to solve this problem recursively in java (without using arrays, if, else, while, etc...)
So the task is to sort numbers from 13542 to 12345.
public static void main(String[] args) {
System.out.println(sort(13542));
}
public static long sort(long n) {
return n < 10
? n
: sort(n, 0);
}
public static long sort(long n1, long n2) {
return n1 > 10
? xxx
: xxx;
}
The problem is that I have no idea what to do. I think my start is okay, but I have problems with the second method.
Firstly, recursion means, put simply, that you have something call itself repeatedly. The fact that the assignment is on recursion is a hint of how your lecturer wants you to solve it, using a recursive method.
Ignoring the main for now, since while it could be prettied up and made more elegant, that isn't the core of the problem.
public int recursiveSort(int toSort){
}
And for neatness, we'll want a method to check if it is sorted, and to do the sorting.
public Boolean isSorted(int toCheck){
//TODO: Check if input is sorted
}
public int singleSort(int toSort){
//TODO: Sorting algorithm
}
Which gives us a recursive method of
public int recursiveSort(int toSort){
toSort = singleSort(toSort);
return isSorted(toSort) ? toSort : recursiveSort(toSort);
}
The sorting with the constraints imposed is the tricky part, and depends on exactly what you cannot use.
And of course, try to look at different sorting algorithms and consider how you would implement them in this case.
Here's a pure recursion with one function and one argument; without log, power, string conversion or loops. I'd say this is quite a difficult exercise in recursion even for more than a beginner. I hope this helps. Feel free to ask for any clarification. (Simplifications are also welcome.)
JavaScript code:
function main() {
console.log(sort(13542));
}
function sort(n) {
if (n < 10)
return n;
let r = n % 10;
let l = (n - r) / 10 % 10;
let sorted = sort(Math.floor(n / 10) - l + r);
let last = sorted % 10;
if (l < last)
return 10 * sort(sorted - last + l) + last;
else
return 10 * sorted + l;
}
main();
Every recursive method should include 2 main "ingredients":
A termination condition
A step forward
As you've mentioned, the obvious termination condition is that a number has only 1 digit, which means it's sorted (and therefore the recursion should stop).
The necessary progression of the method would be to remove a digit on every run, sort the smaller number and then merge the digits together.
As you can figure, the actual challenge can be either merging correctly, or separating efficiently.
I chose to locate the maximal digit, remove it from the original number and send the newly created number back into the recursive function. Eventually the method merges the sorted digits with the largest digit on their right.
public static void main(String[] args) {
System.out.println(sort(13542));
}
public static long sort(long n) {
// For testing purposes:
// System.out.println("sort(" + n + ")");
if (n < 10) return n; // Termination condition
int numOfDigits = (int)(Math.log10(n)+1);
long largestDigit = n % 10;
long restOfDigits = n / 10;
for(int i=0; i<numOfDigits; i++) {
long current = (long) (n / Math.pow(10, i)) % 10;
if (current > largestDigit) {
largestDigit = current;
restOfDigits = (long) Math.pow(10, i) * (n / (long) Math.pow(10, i + 1))
+ (n % (long) Math.pow(10, i));
}
}
// Merge the largest number on the right
return 10 * sort(restOfDigits) + largestDigit;
}
As you can see, for testing purposes it's best to check the recursive method on its beginning. You can either print or use a debugger to see its progression.
In it's simplest form, recursion is making a method call itself over and over. Here's a simple example.
public void eatAllFoodFromTable(Table tbl, Person prsn) {
if(tbl.hasFood()) {
prsn.sustain(1);
tbl.removeFood(1);
eatAllFoodFromTable(tbl, prsn); /*As you can see here,
the method calls itself. However, because the method has a condition
that can prevent it from running indefinitely (or a way to terminate),
it will repeat until the condition is met, then terminate. This is recursion!*/
} else {
//Do nothing.
}
}
What you want to do is take your long, and feed it into a method called sort, or similar. Then, that method will check to see if some of it is in order (through some kind of iteration), and then call itself (sort()) again with the new long generated from the sorting iteration.
Upon reaching the point where it is sorted, the method will terminate, returning the final sorted value.
Thanks alot for your help. I think I got it now:
public static long sort(long n) {
return n < 10
? n
: shuffle(sort(n / (long) Math.pow(10, count(n) / 2)),
sort(n % (long) (Math.pow(10, count(n) / 2))));
}
public static long count(long n) {
return n < 10
? 1
: 1 + count(n / 10);
}
public static long shuffle(long n1, long n2) {
return (n1 > 0 || n2 > 0)
? (n1 % 10 > n2 % 10)
? shuffle(n1 / 10, n2) * 10 + n1 % 10
: shuffle(n1, n2 / 10) * 10 + n2 % 10
: 0;
}
Sadly we weren't allowed to use if, else or while. This would have been so much easier. But thank you all :)

Java recursion 1234 to 4321 for example

I have a question how to better tackle this task, I have a version, but I am sure there is a better and shorter way to do this maybe. I need to take any int number(return it as an int without turning it into a String), but never with a 0 at the end (100, 120) but like 1234, or 4132. I need to take this number and using recursion rewrite it the other way around example 1234 to 4321, 4132 to 2314, maybe there is a way this is called, i personally don't know about it.
Here is what I got:
public static int reverse(int r, int n, int k){
if(r==0)
return 0;
else
return + (r%10) * (int)Math.pow(10, (n-k-1))+reverse (r/10, n, k+1)
}
public static void main(String[] args) {
System.out.println(reverse(1234, 4, 0));
}
Working with a String representation of the int may make the code more readable.
Try:
Integer.parseInt(new StringBuilder(r+"").reverse().toString());
Current code doesn't compile. Added a ) to this line:
from if(r==0{ change to if(r==0){
and added a ; in this line return + (r%10) * (int)Math.pow(10, (n-k-1))+reverse (r/10, n, k+1);
Your code after this two changes will look like:
public static int reverse(int r, int n, int k){
if(r==0)
{
return 0;
}else{
return + (r%10) * (int)Math.pow(10, (n-k-1))+reverse (r/10, n, k+1);
}
}
if the number ends with 0, the program will not show any special message to the user, i.e 1230 will return 321. In this case, maybe
maybe print a message ("number must not end with a 0) or throw an exception?
Didn't notice the recursion part.
public static void main(String[] args) {
int i = 589;
System.out.println(reverse(i));
}
public static int reverse(int k){
if(k/10 == 0){return k;}
else return (k%10 * (int)Math.pow(10, (int)Math.log10(k))) + reverse(k /10);
}
Explanation:
k%10 gives you the last digit of an int
(int) (Math.log10(k)) returns
number of Digits in an Integer minus one
public static final int reverse(int number) {
final int lastDigit = number % 10;
final int length = (int) Math.log10(number);
return (number < 10) ? number : (int) (Math.pow(10.0, length) * lastDigit + reverse(number / 10));
}
If the number is lower then 10 it's the number itself. Otherwise it's the last digit multiplied with 10^n where n is the length of the number, so it's now at the position for the first digit.
Then add the result of a reverse of the rest number to it (the number without the last digit).
You take advance of the recursion function itself as it would already work to solve the big problem. You only have to think about the trivial end condition and one single step (which mostly is something you would suggest as the last step)
This is the best way that I could make it using recursion and without conversions.
private static int myReverse(int n, int r) {
if(n == 0)
return r;
int newR = r*10 + n%10;
return myReverse(n/10, newR);
}
What I'm doing here is:
Two parameters: n - the number you want to reverse, r - the reversed number
The recursion stops when n equals 0 because it always dividing it by 10
newR - This variable is unnecessary but it´s better for 'understanding' porposes, first I multiply r by 10 so I can sum the last value o n. For example, reverse 123: along the way if r = 12 and n = 3, first 12*10 = 120, n%10 = 3 then r*10 + n%10 = 123
A 'pleasant' way with only one return statement:
private static int myReverse2(int n, int r) {
return n == 0 ? r : myReverse2(n/10, r*10 + n%10);
}

mutually recursive functions

I am trying to understand why the below functions are outputting zero for any input I give them. I would have thought that based on the recursive nature that inputting a 2 to function g, would produce 12. Any integer I seem to use for either function simply outputs 0. Can anyone point to where I am going wrong in my thought process?
public class dsdsfsd {
public static int i(int n) {
if (n == 0) return 0;
return i(n-1) + g(n-1);
}
public static int g(int n) {
if (n == 0) return 0;
return g(n-1) + i(n);
}
public static void main(String[] args) {
int a = 2;
System.out.println(g(a));
System.out.println(i(a));
System.out.println(g(g(a)));
}
}
Sure. The only value these functions can return is 0. That's the base case, and the higher cases do nothing but add up those zeroes. Where do you see another value entering the equation?
If either function has zero as an argument, it returns 0.
If it has any other value, it returns the sum of two recursive calls.
The sum of two zeros is zero.
Where exactly do you expect the function to produce anything but zero?
Your problem is not on the recurrence but on the initialization of your variables.
I reckon that you try to calculate some linked coefficients by the formulas:
g(n) = g(n-1) + i(n)
i(n) = i(n-1) + g(n-1)
g(0) = 0
i(0) = 0
However, as you initialized g and i to 0, i(1) = g(0) + i(0) = 0 + 0 = 0, and any values of g(n) or i(n) will be 0 for the same reason which is: you keep adding 0's and 0's.
Instead if you want to have a non-null result you should change at least one of your initialization, for example:
g(0) = 1
i(0) = 1
That way, you have i(1) = g(0) + i(0) = 1 + 1 = 2 and g(1) = g(0) + i(1) = 1 + 2 = 3.
This is more a mathematical issue in the end.
You could reduce this to a single function for simplicity, since the mutual recursion is irrelevant:
public static int func(int n) {
if (n == 0) return 0;
return func(n-1);
}
Notice there are only 2 ways for this to return:
It can return 0 directly in the base case
It can return the result of recursing.
Think about that. At some point, it must stop recursing (or else it will run forever). What happens when the base case of 0 is returned? Your function turns into something like this (for imagining purposes only of course):
public static int func(int n) {
if (n == 0) return 0;
return 0;
}
Therefore, 0 is the only value your function(s) are capable of returning, since it's the only concrete value ever returned.

Tried Euler's #14 again with recursion, didn't work for me. SPOILERS EULER 14th

I posted earlier trying to bruteforce it, but it didn't work. Here's my attempt #2 with recursion (first time using recursive methods). Please help!
Here's what happens: The code runs fine, with smaller numbers, but when we get up to one million, the code simply will run, and nothint at all happens. In Eclipse, it still gives me the option to end, but I've let it run for a very long time with nothing helping.
/**
* The following iterative sequence is defined for the set of positive
* integers:
*
* n → n/2 (n is even) n → 3n + 1 (n is odd)
*
* Using the rule above and starting with 13, we generate the following
* sequence: 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
*
* It can be seen that this sequence (starting at 13 and finishing at 1)
* contains 10 terms. Although it has not been proved yet (Collatz Problem),
* it is thought that all starting numbers finish at 1.
*
* Which starting number, under one million, produces the longest chain?
*
* NOTE: Once the chain starts the terms are allowed to go above one
* million.
*/
public class Euler14 {
static int desiredMax = 1000000;
static int maxTerm = 0;
static int maxNumberOfTerms = 0;
static int currentNumber = 0;
static int numberOfTerms = 0;
public static void doMath(int startingNumber) {
if(startingNumber == 1) {
System.out.print( maxTerm + " " + maxNumberOfTerms);
}
else {
currentNumber = desiredMax;
while(currentNumber!= 1) {
if(currentNumber%2 == 0) {
currentNumber = currentNumber/2;
numberOfTerms++;
} else {
currentNumber = (3 * currentNumber) + 1;
numberOfTerms++;
}
}
numberOfTerms++;
if(numberOfTerms > maxNumberOfTerms) {
maxNumberOfTerms = numberOfTerms;
maxTerm = startingNumber;
}
desiredMax--;
doMath(desiredMax);
}
}
public static void main(String[] args) {
doMath(desiredMax);
}
}
There are many wrong things with your code :
use of a recursive method which is no more no less than a loop going downward
use of static variables
numberOfTerms never reinitialized
as pointed by azurefrog, you have an integer overflow which is causing an infinite loop.
I was rearranging your code with as few changes as possible when he came up with the answer, so all I can do now is to show you a working code very similar to yours. See how cleaner it is this way :
public class Euler14 {
public static void main(String[] args) {
int maxTerm = 1000000;
int maxNumberOfTerms = 1;
// this loop replaces your recursion, which is not needed here and quite costly even if it is tail-recursion
for (int i = maxTerm ; i >= 2; i--) {
int numberOfTerms = 0;
// declare as long to prevent the overflow
long currentNumber = i;
while (currentNumber != 1) {
if (currentNumber % 2 == 0)
currentNumber = currentNumber / 2;
else
currentNumber = (3 * currentNumber) + 1;
numberOfTerms++;
if (numberOfTerms > maxNumberOfTerms) {
maxNumberOfTerms = numberOfTerms;
maxTerm = i;
}
}
}
System.out.println(maxTerm);
}
}
The main problem is that you are trying to do math on large numbers with ints. When your program gets down to a desiredMax of 999167, you're going into an infinite loop.
In Java, the largest value an int can represent is 2,147,483,647.
When your algorithm gets to 999167, it quickly exceeds that limit.
If you print the value of currentNumber in your inner while-loop, you see this:
...
1330496806
665248403
1995745210
997872605
-1301349480 <-- oops
-650674740
-325337370
...
You are trying to set currentNumber to 2,993,617,816, so your value is going to overflow.
This causes your while-loop to never terminate, since you don't account for negative numbers. You quickly settle into a repeating sequence of
-25
-74
-37
-110
-55
-164
-82
-41
-122
-61
-182
-91
-272
-136
-68
-34
-17
-50
-25
... ad infinitum
You could try switching to a bigger numerical representation (long), but, even if you switch to using long values, the way you are trying to recurse will cause a stack overflow long before you ever finish trying to evaluate a desiredMax of 1000000. (On my box, I get a StackOverflowError when I get down to 997474).
You need to go back and rethink the structure of your program. Recursion can be a useful tool, but it's dangerous to use unless you know that you aren't going to go too deep.
This is a good example of where you can employ Memoization.
Below is a solution that uses recursion, but avoids the need to continually go over paths you've calculated already.
This also separates the chain-calculation code from the searching-for-the-maximum code.
public class Euler14 {
static long[] records = new long[1000000];
// //////////////////////////////////////////////
// Recursively calculates one chain length
//
static long getLength(long n) {
// Terminating condition
if (n == 1) {
return n;
}
// Have we already calculated this?
if ((n < records.length) && (records[(int) n] != 0)) {
return records[(int) n];
}
// Haven't calculated this yet, so calculate it now
long length = getLength(n % 2 == 0 ? n / 2 : 3 * n + 1) + 1;
// Record the result for later use
if (n < records.length) {
records[(int) n] = length;
}
return length;
}
static long calculateQuestionFourteen() {
long maxLength = 0;
long maxStart = 0;
for (long i = 1; i < 1000000; ++i) {
long thisLength = getLength(i);
if (thisLength > maxLength) {
maxLength = thisLength;
maxStart = i;
}
}
return maxStart;
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
System.out.println(calculateQuestionFourteen());
System.out.println(System.currentTimeMillis() - start);
}
}

Categories