Learning Java Recursion, Ackerman function - java

I'm working on a recursive Ackermann function in Java. I am getting an error at may recursive line, 23.
return Ack(m - 1, Ack(m, n - 1));
Thanks so much if anyone could point out what's wrong.
-Kyle
/*enter code here
Ackerman's function, A(m, n) is defined:
A(0 , n) = n + 1 for n >= 0
A(m , 0) = A(m – 1 , 1) for m > 0
A(m , n) = A(m – 1 , A(m , n - 1)) for n >= 0
*/
public class AckFun {
public static int Ack(int m, int n) {
if (m == 0) {
return 2 * n;
} else if (m >= 1) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 2;
} else {
return Ack(m - 1, Ack(m, n - 1));
}
}
return n; // Not sure what to return here, Eclipse suggested this.
}
public static void main(String args[]) {
System.out.println(Ack(3, 4));
}
}

You need to make your stack larger:
http://thilinamb.wordpress.com/2008/12/22/how-to-increase-the-java-stack-size/
With larger stack it runs without stackoverflow, but gives 0.
EDIT: Your code is wrong, that is why it gives the error. Try to rewrite the code exactly as the definition says:
//I assume that you check that n and m are non-negative before you run this
if (m == 0) {
return n + 1;
} else if (n == 0) {
return Ack(m - 1, 1);
} else {
return Ack(m - 1, Ack(m, n - 1));
}
PS. Don't blame me for posting source code for homework problems. I believe that the best way to learn programming is by reading and understanding someone else's code.

You've exceeded the maximum recursion depth. That's one of the features of the Ackermann function. :)
If you call it with smaller numbers, like Ack(3,3), then it doesn't overflow the stack.
It's possible to increase Java's recursion depth limit, but that's not necessarily a good solution. This may be an exercise in transforming the program so that it doesn't use Java's built-in call stack, but keeps track of each call in a data structure (perhaps a Stack). You can also use memoization, where you record the result of the function call so you don't have to compute the same result over and over.

With a return in front, you don't need 'else'.
if (m == 0) return n + 1;
if (n == 0) return ack (m - 1, 1);
return ack (m - 1, ack (m, n - 1));

Related

Shortest path algorithm on an integer matrix grid does not return the expected value

I have an assignment to submit and I need help I will appreciate it a lot!!
I need to write a method that gets an integer matrix grid with numbers from 0 and above. 1 value in the matrix is different and contains -1. the function also gets the starting x and y in the matrix.
I need to write a recursive function that finds the shortest path from the starting x, y to the -1 value.
you can "jump" to the left' right' up and down. the condition to "jump" from one index to another is if the absolute value between the subtraction of the the 2 pairing is either 0, 1 or 2
The shortest path is 4
I cannot use while and for loops, and global variables
The function signature should be: public static int shortestPath(int[][] drm, int i, int j)
Thanks a lot!
Here is my try:
package assignment1;
import java.util.*;
public class run {
static Scanner reader = new Scanner(System.in);
public static int shortestPath(int[][] drm, int i, int j) {
if (drm.length == 0 || i >= drm.length || j >= drm.length || i < 0 || j < 0)
return 0;
if (i > 0 && j > 0 && i < drm.length - 1 && j < drm[i].length - 1) {
if (drm[i][j - 1] == -1) {
System.out.print("Got it! the target is on the left");
return 2;
}
if (drm[i][j + 1] == -1) {
System.out.print("Got it! the target is on the right");
return 2;
}
if (drm[i - 1][j] == -1) {
System.out.print("Got it! the target is up");
return 2;
}
if (drm[i + 1][j] == -1) {
System.out.print("Got it! the target is down");
return 2;
}
}
int temp = drm[i][j];
int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE, up = Integer.MAX_VALUE, down = Integer.MAX_VALUE;
if (isValidJump(drm, i, j, i + 1, j)) {
System.out.print("down ");
drm[i][j] = Integer.MIN_VALUE;
down = shortestPath(drm, i + 1, j) + 1;
}
if (isValidJump(drm, i, j, i, j + 1)) {
System.out.print("right ");
drm[i][j] = Integer.MIN_VALUE;
right = shortestPath(drm, i, j + 1) + 1;
}
if (isValidJump(drm, i, j, i, j - 1)) {
System.out.print("left ");
drm[i][j] = Integer.MIN_VALUE;
left = shortestPath(drm, i, j - 1) + 1;
}
if (isValidJump(drm, i, j, i - 1, j)) {
System.out.print("up ");
drm[i][j] = Integer.MIN_VALUE;
up = shortestPath(drm, i - 1, j) + 1;
}
drm[i][j] = temp;
return Math.min(Math.min(Math.min(up, down), left), right);
}
public static boolean isValidJump(int[][] drm, int i, int j, int m, int n) {
if (m < drm.length && m >= 0 && n < drm.length && n >= 0 && drm[m][n] != Integer.MIN_VALUE) {
int jump = drm[m][n] - drm[i][j];
if (jump == 0 || jump == 1 || jump == -1 || jump == -2) {
return true;
}
}
return false;
}
public static void main(String[] args) {
int[][] drm = { { 2, 0, 1, 2, 3 }, { 2, 3, 5, 5, 4 }, { 8, -1, 6, 8, 7 }, { 3, 4, 7, 2, 4 },
{ 2, 4, 3, 1, 2 } };
System.out.println(shortestPath(drm, 0, 0));
}
}
It supposed to return 4 (shortest path)
Given this is for a class I advise you to notify your professor that you received assistance from this post on stack overflow. Neglecting to do this would be considered academic dishonestly at most universities.
Second thing is as David suggested this is a good opportunity for you to learn how to use a debugger. This is a skill that will be incredibly valuable in your academic career and in a engineering role.
Your Code
Now looking at your code it does give the solution "4" for the case you presented which is correct. Problem is if you change the inputs the output may not give the correct answer.
This is because your code as written gives the FIRST path it finds and not the SHORTEST path.
Your logic as far as the recursion is sound and based on this code it looks like you understand the basics of recursion. Your problem is a minor logical flaw with how your are masking your data when you call your function recursively.
You should have everything you need to solve this. If you are still having problems please try to use a debugger and examine the area where you make your recursive calls.
Solution
I advise you to try to figure this out yourself before looking at the spoilers below.
In the code where you make your recursive calls you mask by setting drm[i][j] = Integer.MIN_VALUE. The problem is after each of your recursive calls return you do not set it back to the previous value with drm[i][j] = temp before doing the tests for your next recursive call.
What is happening is when you next call isValidJump() it will always return false because drm[i][j] will always be Integer.MIN_VALUE after your have made your first recursive call on this iteration.
How to fix:
Put drm[i][j] = temp immediately after each recursive call to shortestPath().

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 :)

How to calculate number of swaps in permutations?

I have this code below, I would like to know how to calculate the number of swaps. I used a count variable to figure it out, but I was getting different number than the computer. I figure the number of swaps would be 2 * (n - 1)(n - 2)...(n - n + 1). For n == 4, the computer got 128, and I got 48. What am I doing wrong?
public void permute(int n) {
if (n == 1) {
printOutPut();
}
for (int i = 1; i <= n; i++){
swap(i, n);
permute1(n-1);
swap(i, n);
}
}
The code defines a recursion:
num_swaps(0) = 0
num_swaps(i) = i * (num_swaps(i - 1) + 2)
or with more math-like symbols:
s_{n+1} = (n + 1) (s_n + 2)
s_0 = 0
s_1 = 2
s_2 = 8
s_3 = 30
s_4 = 128
You can probably solve that recursion for a general n using techniques from maths, but this verifies that the computer is right
Edit: I was trying to find a solution for general n, ended up on wolfram alpha and the solution presented had incomplete gamma functions and stuff. So, don't expect the calculation to be easy!

recursive to iterative (java)

as a beginner in programming I am trying to convert the following recursive method to an iterative one but I just don't get the hang of it. The method or function has a binary tree like recursion and I would like to use an array for the iterative solution.. unfortunately I am very confused how to do it.
I have already checked the way of converting the fibonnaci recursive method to an iterative one. But I think this is not the same here. Also I am not sure if a tree search method is useful?! Any help, hint, idea would be appreciated. Thanks.
public static int funct(int n) {
if (n == 0) return 1;
if (n == 1) return 2;
if n > 1 return funct(n-2)*funct(n/2);
}
Since every n-th member is computed by others before if you can cache all in a list. You start by adding the first 2 known members. Fibonacci its easier because you always need only previous value.
private static int func(int n) {
List<Integer> values = new ArrayList<>(n+1);
values.add(1);
values.add(2);
for (int i = 2; i <= n; i++) {
values.add(values.get(i - 2) * values.get(i / 2));
}
return values.get(n);
}
Now the real function is without last if:
public static int funct(int n) {
if (n == 0) return 1;
if (n == 1) return 2;
return funct(n-2) * funct(n/2);
}
As the recursive calls refer to smaller parameters one can cache all return values upto n.
Unfortunately this already spoils the pleasure, as the resulting code is complete:
public static int funct(int n) {
int[] results = new int[n+1];
results[0] = 1;
results[1] = 2;
int i = 2;
while (i <= n) {
results[i] = results[i-2] * results[i/2];
++i;
}
return results[n];
}
It indeed looks like fibonacci.
In general one would not need to fill all items of results. like probably results[n - 1].
Unfortunately you should have learnt prior to this problem:
Solving tail recursion.
Using a stack (like here) to use inner results of a recurive call.
You might look into those topics.
Math afterlude
The initial values are powers of 2. As the result is a product of earlier results, all results will be powers of 2.
f(0) = 1 = 2^0
f(1) = 2 = 2^1
f(n) = f(n - 2) * f(n / 2)
Hence you can introduce:
g(0) = 0
g(1) = 1
g(n) = g(n - 2) + g(n / 2)
f(n) = 2^g(n)
This will enlarge the range you can calculate as say 2100.
You will also see:
g(2k + 1) = g(2k) + 1
So you will only need a domain of even numbers:
g(2k) = g(2(k-1)) + g(k - k%2) + k%2

JAVA Recursive Program logic

public class Prod {
public static void main(String[] args) {
System.out.println(prod(1, 4));
}
public static int prod(int m, int n) {
if (m == n) {
return n;
} else {
int recurse = prod(m, n-1);
int result = n * recurse;
return result;
}
}
}
On running the above code , I get 24 ?
I don't quite understand how?
My doubts:
1. When m =1 , n=4 , we call prod until m and n become equal to 1.
Then the output should be n and else block should not be executed??
Someone please help me understand the logic.
Just run through this with the numbers, you need to write it down to see the behavior exactly (in the future, I suggest adding lots of prints to your code to check variables and how they change with each pass through).
prod(1,4)
m=1,n=4
m != n so, recurse = prod(1, 3)
prod(1, 3)
m=1,n=3
m != n so, recurse = prod(1, 2)
prod(1, 2)
m=1,n=2
m != n so, recurse = prod(1, 1)
prod(1, 1)
m=1,n=1
m == n so,
return 1
returns to prod(1, 2)
recurse = 1
result = 2 * 1
return 2
returns to prod(1, 3)
recurse = 2
result = 3 * 2
return 6
returns to prod(1, 4)
recurse = 6
result = 4 * 6
return 24
Thus, your program prints 24.
Sometimes the best way to figure out a program is to mechanically go through the steps line by line, executing them in your head (or on paper to track things).
To understand any program with functions, you assume the called functions do their job right, and check that the calling function calls them in the correct order with the correct arguments, and combines the results correctly.
For recursive functions you need to check that each recursive call gets you closer to the case in which there is no recursion.
Here nobody told us what is the result supposed to be. The recursion ends whenever m == n, and the recursive call is with n = n - 1, so this will work only if m <= n.
Consider a string of calls, each one reduces n by 1, while m stays fixed. Say n == m + 3 for finding out what happens: The first call gets m + 2, the second m + 1, the third m, and returns m. The second takes n == m + 1 by m returned by the third, the second takes n == m + 2 and multiplies by the previous result, and finally the result is (m + 3) * (m + 2) * (m + 1) * m. This function computes n! / (m - 1)!, if n >= m. Knowing that this is what is going on, it is easy to check that our (up to now just) hunch is right.
prod(1, 4);
public static int prod(int m, int n) {
if (m == n) {
return n;
} else {
int recurse = prod(m, n-1);
int result = n * recurse;
return result;
}
}
can be transformed with m == 1 to:
prodA(4);
public static int prodA(int n) {
if (1 == n) {
return n;
} else {
int recurse = prodA(n-1);
int result = n * recurse;
return result;
}
}
which has a transformation (head recursion):
public static int prodA(int n) {
int result = 1;
while (n > 1) { // Actually n != 1
result *= n;
--n;
}
return result;
}
which is the factorial function.

Categories