How to understand the principles of recursions in practice? - java

I started learning recursions and it seemed like I understood how they work. But as soon as I tried to pass a quiz, I found that I actually didn't. Here is some code from latest task I tried to pass. Here I tried to find a factorial. To do this I have to multiply all the numbers from 1 till the N number.
Here is some code:
public class App {
public static void main(String[] args) {
f(1);
}
private static void f(int n) {
System.out.print(n);
if (n < 7) {
f(2 * n);
}
}
}
I tried to multiply these nums and to multiply the product for 2. But I failed when saw that the result isn't 5040. The actual output is 1248. Maybe I was doing actions in wrong order?

Let's take a look how to multiply numbers from 1 to n using recurrency:
public static void main(String[] args) {
long result = mulFromOneTo(30);
}
private long mulFromOneTo(int number) {
if (number == 1) {
return 1;
} else {
return number * mulFromOneTo(number - 1);
}
}
I don't want to give you completely prepared source code - but I hope it'll help you a bit.

Andrezej's answer is a good top-down approach. Let's have a look at why your code doesn't work:
If we summarize what f is doing, it prints n and it will call itself recursively with 2 * n when n is less than 7.
So in your example, you first call f(1) so it prints 1 and calls f(2), which prints 2 and calls f(4), prints 4, calls f(8), prints 8 and stop.
So your function is not printing the number 1248, but it's printing 1, 2, 4 and 8 independently.
The total computation done by your recursive function is (2 * (2 * (2 * 1)))

Related

Getting the number factors of 2 in the given value using recursion

I'm trying to make a program where a method takes a single positive integer as its argument and returns the number of factors of 2 in the number, an example being numbers that are twice an odd number returns one, numbers that are four times an odd returns two, etc.
public int twos(int n){
int twos=0;
if(n%2!=0){
return(0);
}
if(n/3>=1){
System.out.println("\n"+n);;
return twos(n/3)+1;
}
else{
return(0);
}
// return(twos);
}
The code I have above only works for the integers 6 and 12, but not for all integers. How would you make this work for all digits?
While creating a recursive implementation, you need always define Base case and Recursive case (every recursive method would contain these two parts, either implicitly or explicitly).
Base case - represents a condition (or group of conditions) under which recursion should terminate. The result for base case is trivial and known in advance. For this task, Base case is when the number is not even, return value is 0.
Recursive case - is the place where the main logic of the recursive method resides and where recursive calls are made. In the Recursive case we need to perform a recursive call with n / 2 passed as an argument, and return the result of this call +1 (because the received argument is even, and we need to add one power of 2 to the total count).
That's how implementation might look like:
public int twos(int n) {
if (n % 2 != 0) return 0; // base case
// recursive case
return 1 + twos(n / 2);
}
Or if you would use a so-called ternary operator (which is an equivalent of if-else) it can be written as:
public int twos(int n) {
return n % 2 != 0 ? 0 : 1 + twos(n / 2);
}
Usage example (in order to be able to call twos() from the main() add static modifier to it):
public static void main(String[] args) {
System.out.println(twos(2));
System.out.println(twos(4));
System.out.println(twos(12));
System.out.println(twos(38));
System.out.println(twos(128));
}
Output:
1 // 2
2 // 4
2 // 12
1 // 38
7 // 128

Encountered Java.lang.StackOverflowError: null while executing the following code

class Generate // to print all numbers from 1000 to 9999 whose digits are in ascending order
{
private boolean order(int n, int i) // checks if the digits of given number are in ascending order
{
if (n == 0) return true;
if (n % 10 < i) return (order(n / 10, n % 10));
return false;
}
void show(int n) // recursive function to generate numbers from 1000 to 9999
{
if (n > 9999) // base case for recursor
System.out.print("");
else
{
if (order(n, 10)) // if digits are in ascending order, prints the number
System.out.println(n);
show(n + 1); // recursive call
}
}
}
The above code was supposed to print all numbers from 1000 to 9999. Code compiled and run but received a runtime exception: java.lang.StackOverflowError: null. Would a try-catch block fix my problem? This is my first time posting here hence I am not familiar with the question etiquette, please correct me if I'm wrong.
Java (and most of the programming languages) provides finite number of memory slot to be used for stack-frame, when your program/code reaches that limit it throws the StackOverFlow error.
In your case, your program reaches that limit before coming to base condition.
My take on this -
Do not use Recursive approach until and unless you are splitting your problem into acceptable sub-problems.
this shows you how you can increase stack-frame-size to be used by the JVM for a particular thread.
In my opinion StackOverFlow is due to double recursion i.e both show(), and order() are recursive... I think show() does not need to be recursive. modified your code as under:
public static void main(String[] args) {
/
new Generate().show(); // added main function to get output or exception.. you can omit it and call Generate().show() at the point u require.
}
}
class Generate//to print all numbers from 1000 to 9999 whose digits are in ascending order
{
private boolean order(int n, int i)//checks if the digits of given number are in ascending order
{
if(n==0)
return true;
if(n%10<i)
return(order(n/10,n%10));
return false;
}
void show()//function to generate numbers from 1000 to 9999 - WITHOUT Recursion
{
int n = 1000;
while(n<=9999)
{ if(order(n,10))//if digits are in ascending order, prints the number
System.out.println(n);
n++;
}
}
}
and here is output: (showing first 7 iterations only)
1234
1235
1236
1237
1238
1239
1245 .......

Validating an Armstrong number using Recursion in Java

I have to check whether a number is an Armstrong number or not, using a recursive method.
public class ArmStrong {
public static void main(String[] args) {
System.out.println(isArm(407, 0, 0));
}
static boolean isArm(int n,int last,int sum) {
if (n <= 0 ) {
if (sum == n) {
return true;
} else {
return false;
}
}
return isArm(n / 10, n % 10,sum + last * last * last);
}
}
When I debug, in the last call of isArm when n is 4, the base statement is skipped.
Your code will instantly jump to the answer (if (n <= 0)) before applying the cube of the last digit.
For example, trivially, let's try 9, which obviously isn't armstrong.
Your code will first check if 9 is 0 - it's not. So, we recurse, which will go with self(0, 9, 0+0). The next run is supposed to then recurse once more, so that the sum + last*last*last can actually get some cubing done. But it'll never get there - n is 0, so, you jump into the if.
As your variable name kinda gives away last is referring to the digit that the previous run lopped off, and yet you aren't cubing it.
The solution is to simply get the cubing in before checking if n is null:
The first thing your method should do is
sum += last*last*last;
Then, the second problem shows up: This correctly calculates your sum to be 407, but you check this against n, which is, obviously, 0 - you are 'destroying' n as you go through. One trivial way to solve that is to pass the original n, unmolested, through, as a 4th parameter. I'll leave that as an exercise for the reader.
Although #rzwitserloot has pointed at an issue which is rooted in the way you've designed the recursion, the problem is still not resolved.
Yes, the recursive calls go "one step ahead" the calculation of the sum of digits, which happens in the Recursive case, and the left-most digit of the given number doesn't contribute the sum, since n is zero and recursion hits the Base case. That's true, but it's not the only thing you need to fix.
Here's the definition of so-called Narcissistic numbers (aka Armstrong numbers):
In number theory, a narcissistic number (also known as a pluperfect digital invariant (PPDI), an Armstrong number (after Michael F. Armstrong)or a plus perfect number) in a given number base b b is a number that is the sum of its own digits each raised to the power of the number of digits.
Therefore, a method with hard-coded power of 3 is capable to validate only three-digit Armstrong numbers. There are only few of them, for other valid Armstrong numbers it would produce an incorrect result.
So, before calculating the sum you need to know the numbers of digits there's no workaround. If you want to address the problem only by using Recursion, the numbers of digits can be also calculated recursively. If we take this route, the solution boils down to implementing two recursive methods.
That's how it might look like:
public static boolean isArm(int n) {
return n == getSum(n, getDigitCount(n));
}
public static int getSum(int n, int power) {
return n == 0 ? 0 : (int) Math.pow(n % 10, power) + getSum(n / 10, power);
}
public static int getDigitCount(int n) {
return n == 0 ? 0 : 1 + getDigitCount(n / 10);
}
main()
public static void main(String[] args) {
System.out.println(isArm(10)); // is not an Armstrong number
System.out.println(isArm(21)); // is not an Armstrong number
System.out.println(isArm(407)); // is an Armstrong number
System.out.println(isArm(153)); // is an Armstrong number
System.out.println(isArm(9)); // is an Armstrong number
}
Output:
false // 10
false // 21
true // 407
true // 153
true // 9

Learning Java - Do not fully understand how this sequence is calculated (Fibonacci) in for loop [duplicate]

This question already has answers here:
Java recursive Fibonacci sequence
(37 answers)
Closed 8 years ago.
I am learning Java and I have this code from the internet and running it in Eclipse:
public class Fibonacci {
public static void main (String [] args) {
for (int counter = 0; counter <= 3; counter++){
System.out.printf("Fibonacci of %d is: %d\n", counter, fibonacci(counter));
}
public static long fibonacci(long number) {
if ((number == 0) || (number == 1))
return number;
else
return fibonacci(number - 1) + fibonacci(number - 2);
}
}
I've tried to understand it but cannot get it. So I run through the code and counter gets passed in through the fibonacci method. As counter starts at 0 and this is what gets passed first, then 1 and I understand the method passes back 0 and then 1.
When it reaches 2: it will return 2-1 + 2-2 = 2 and it does return this.
When it reaches 3: it will return 3-1 + 3-2 = 3 but it does not return 3 it returns 2.
Please can someone explain to me why as I cannot figure this out?
Thanks
First, I have to tell you that this recursive version has a dramatic exponential cost. Once you understand how it works, my advice for you would be to learn about tail recursivity, write a tail-recursive solution, an iterative solution, and compare them to your current method for high values of "number".
Then, your function basically uses the mathematical definition of the Fibonacci sequence :
f0 = 1, f1 = 1, fn = fn-1 + fn-2 for all n >= 2
For example if we call fibonacci(3), this will return fibonacci(2) + fibonacci(1). fibonacci(2) will be executed first and will return fibonacci(1) + fibonnacci(0). Then fibonacci(1) will return immediately 1 since it is a terminal case. It happens the same thing with fibonnacci(0), so now we have computed fibonnacci(2) = 1 + 0 = 1. Let's go back to fibonacci(3) which has been partially evaluated at this point : 1 + fibonnacci(1). We just have to compute fibonnacci(1) and we can finally return 1 + 1 = 2.
Even in this little example, you can see that we evaluated twice fibonacci(1), that is why this version is so slow, it computes many times the same values of the sequence, and it gets worth when "number" is high.

Recursive definition solution

im studying for my final exam from the text book. I need an answer for this question since i couldn't solve it.
1)Write a recursive definition of the function multiply(int a, int b) that takes two integers and return the result of their multiplication.
I answered:
Multiply(a, b) :
0 - if a or b is equal to zero. (I got -1 here. Reason written: only 1)
a * b - (I didn't know what to write here)
2)
Write a recursive method that takes a linked list of integers and returns the sum of it's elements.
My solution was:
int sumList(Node<Integer> list) {
int temp = list.getInfo();
if(temp == null) {
return 0;
} else {
return temp + sumList(temp.getNext);
}
}
I fixed it, i think:
public int sumList(Node<Integer> list) {
Node<Integer> temp = list;
if(temp == null) {
return 0;
} else {
return temp.getInfo() + sumList(temp.getNext());
}
}
Is the solution for question 2 right?
Since this is for exam preparation, I don't want to give you the code for doing this. Instead I will give you some ideas.
For the question no 1. Since multiplication is repeated summation, you can use that as the base for recursion here.
If you want to find 3 * 4, use recursion to calculate and return 4 + 4 + 4.
In other words, you can see a pattern emerge below.
4 * 3 = 4 + (4 * 2)
4 * 3 = 4 + 4 + (4 * 1)
To get a working recursive solution you need a base case, for example a == 0, and then work yourself down towards the base case by recursively calling yourself.
The solution for question 1 could be something along the lines of this, that decreases the a argument until it reaches 0:
int multiply(int a, int b) {
if (a == 0 || b == 0) {
return 0;
}
return b + multiply(a - 1, b);
}
For example, multiply(2, 5) would become 5 + multiply(1, 5) -> 5 + 5 + multiply(0, 5) -> 5 + 5 + 0.
Note that this particular solution doesn't work for negative numbers, but you get the idea. You should be able to easily add support for that yourself.
A) well, you really need to reread that chapter on recursion.
The mathematical principle is this:
http://en.wikipedia.org/wiki/Mathematical_induction
and the Wikipedia article will step you through a much more complicated task.
B) No, it won't compile at all. There are multiple syntax errors.
Try using a Java compiler for excersising your programming skills.

Categories