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.
Related
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 version "1.8.0_92"
I have the following code I am trying to understand and trace.
The part I don't understand is the * a at the end. When does that multiplication get called? And what is the return value of power1(a, n - 1);
Is it n - 1 * a
public static double power1(double a, int n) {
double result;
if(n == 0) {
return 1;
}
else {
result = power1(a, n - 1) * a;
return result;
}
}
You can modify the code to print a trace of the recursion. That can help you understand what is going on.
/**
* Print string form of `o`, but indented with n spaces
*/
private static void printIndented(int n, Object o) {
while (n-->0) System.out.print(" ");
System.out.println(o);
}
/*
* Added a third param `d` to keep track of the depth of the recursion
*/
public static double power1(double a, int n, int d) {
// Entering a "possible" recursive call
printIndented(d, "call power1, a=" + a + ", n=" + n + ", d=" + d);
double result;
if(n == 0) {
// Returning from the base case, this should have the largest depth.
printIndented(d, "return 1.0");
return 1;
}
else {
result = power1(a, n - 1, d + 1);
// Return from intermediate recursive calls, we print
// the value of power1(a, n-1) as well.
printIndented(d, "return " + result + " * " + a);
return result * a;
}
}
public static void main(String [] args) {
System.out.println(power1(1.4, 3, 0));
}
Output
call power1, a=1.4, n=3, d=0
call power1, a=1.4, n=2, d=1
call power1, a=1.4, n=1, d=2
call power1, a=1.4, n=0, d=3
return 1.0
return 1.0 * 1.4
return 1.4 * 1.4
return 1.9599999999999997 * 1.4
2.7439999999999993
As you can see, the value from the inner return becomes the result in the outer return statement.
Return value of power1(a,n-1)
We can see that power1 is defined as public static _double_ power1(double a, int n) This means that on the line
result = power1(a, n - 1) * a;
the type will be :
double = double * double;
When the multiplication gets called
We start our function with n and a. a will be constant in this implementation. It's given straight as to the next recursive call.
Yet n varies.
We call power1(a,n). It checks first if n == 0; It is not.
So we go to the else part of the if. Time to calculate result.
To know what the value of result is, we need power1(a,n-1). We proceed. n-1 can be 0 or can not be.
If it's 0, we return 1, and we now know that power1(a,n-1) = 1. We can now multiply it with a.
If it's not 0, then we need a new result, seeing as we're in a completely seperate call of the power1 method. We now need power1(a,n-2). We check again for 0. If n-2 == 0, return 1 to get the caller to calculate power(a,n-1). If not go down another call, now with n-3... Etc
In terms of the timing of calling the multiplication.
It's gonna call all the (n) recursive calls first, before doing n multiplications.
If you call power1 with a = 2 and n = 3, this is what will happen:
result = power1(2, 2) * 2;
power1(2, 2) = power1(2, 1) * 2;
power1(2, 1) = power1(2, 0) * 2;
power1(2, 0) = 1
In the above example, the * a happens three times in total. It is called whenever power1(a, n) returns a value. The first power1(a, n) to return a value will be power1(2, 0) (this is because n = 0 is your "base" case). Then power1(2, 1) will return 2. Then power1(2, 2) will return 4. Then your initial call to power1(2, 3) will return 8.
First you call power (a,n-1) until n == 0 which is your base case .
Then the 1 gets returned and is multiplied by the value of a.
Then a is returned to the previous call where it is multiplied by a . The process is repeated N times and thus you get A^n. I would recommend you go throught one example of this code giving it some initials values and tracing the code using pen and paper.
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
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;
}
}
}
I've read a solution here: JAVA Recursive Program logic that makes some sense but I don't get why when it hits prod(1,1) it goes back to prod(1,2)
It will return the factorial of n with min limit m. Like
n * (n-1) * (n-2) * (n-3) * (n-4) * (n-5) ... till (n-x) != m
Sure. Let's add logging with some formatted output and I'd suggest you use a Conditional Operator ? : like
public static int prod(int m, int n) {
int recurse = (n != m) ? prod(m, n - 1) : 1;
int r = n * recurse;
System.out.printf("m=%d, n=%d, recurse = %d, returning %d%n", m, n,
recurse, r);
return r;
}
Output should explain your result
m=1, n=1, returning 1
m=1, n=2, recurse = 1, returning 2
m=1, n=3, recurse = 2, returning 6
m=1, n=4, recurse = 6, returning 24
24
Because it has prod(1,2) and other methods in the stack. Each time prod(m,n) is called it recursively calls prod(m,n-1) . This continues till m==n , in your case prod(1,1). Here prod(1,1) will return value to the calling method prod(1,2)
//method prod(1,2)
....
int recurse = prod(m, n-1);//here it will get value 1 returned from prod(1,1)
int result = n * recurse; // 2*1
return result; // return 2 to calling method prod(1,3)
So when finally recursive call ends at prod(1,1) and returns values. all the previous prod() present in the call stack will be execute each one getting return from called prod(m,n-1)
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));