Having trouble understanding recursion in Java - java

import java.util.Scanner;
public class findFive {
public static int count = 0;
public static String result = null;
public static void main(String[] args) {
System.out.println("Enter a nonnegative number");
Scanner input = new Scanner(System.in);
int number = input.nextInt();
countFive(number);
System.out.println(count);
}
public static void countFive(int number) {
if (number < 10) {// the base case
if (number == 5) {
count++;
}
} else { // number has two or more digits
countFive(number / 10);
if (number % 10 == 5) {
count++;
}
}
}
}
To put it simply, I do not understand the flow of the countFive(int number) method. I know that if the user enters 5, then the count will simply be equal to 1. However, my confusion comes from where the method is called again inside the method with 'countFive(number/10)'.
EDIT: I would appreciate if someone went through the flow of the code with a number like 552.

If you want to see how this works you should step through the code in your debugger, it will be much more clear when you see it in action
The method is counting how many times the digit 5 occurs in a number. For example if you pass in the number 515 the following will happen
515 is greater than 10
Call countFive(number/10) which evaluates to countFive(51)
51 is greater than 10
Call countFive(number/10) which evaluates to countFive(5)
5 is less than 10
5 equals 5
Increment count
Step out
number%10 == 5 which evaluates to 1%10 == 5 - False
Step out
number%10 == 5 which evaluates to 5%10 == 5 - True
Increment count
countFive(515)
| 515 greater than 10
| countFive(51)
| | 51 greater than 10
| | countFive(5)
| | | count++
| | 51 mod 10 does not equal 5
| 515 mod 10 equals 5
| count++

In recursion base case is created to avoid infinite calls to the same method. That is defined by you below.
if (number < 10) {// the base case
if (number == 5) {
count++;
}
}
If this condition is satisfied, execution comes out of this method. If this isn't true, else block is executed.
else { // number has two or more digits
countFive(number/10); //This is where it is called again
if (number%10 == 5) {
count++;
}
}
In this you have call to countFive(number/10)

Well, the method counts the occurence of 5 in a number. For example, 5123512356 would return 3.
You simply use recursion to remove the last digit of the number until you have reached the highest digit (5 in the example on the left).
Once you have reached it, it will go into number < 10 and see that it indeed is a 5. Then it will leave the method and continues with 51 (51 % 10 = 1), continues with 512, 5123, 51235 (count++) and so on until it is through with the whole number.
To clarify: number/10 is called to reach the highest digit by removing the last digit of the original number until you cannot divide it by 10 any longer. And then the checks go through backwards.
Let's have a look at an easier example: 5050.
1st call: countFive(5050). 5050 > 10, so we call:
2nd call: countFive(5050/10) = countFive(505). Still greater than 10
3rd call: countFive(50)
4th call: countFive(5): counter++, the number is smaller than 10
now we go backwards through these three calls (the last one is finished)
3rd call: 50 % 10 = 0, counter stays the same
2nd call: 505 % 10 = 5, counter++
1st call: 5050 % 10 = 0, counter stays the same
Afterwards: counter = 2.

Let's take the input you proposed: 552 and follow the method.
At the beginning count is 0.
number count number < 10 number == 5 number % 10 == 5
----------- ------- -------------- -------------- ------------------
552 0 false false false
55 0 false false true
1
5 1 true true true
2
And it'll return 2. Basically as you can see the method counts the number of occurrences of the digit 5 in the input.
Your base case checks if it's a digit (< 10) and if so checks if the digit is 5. Otherwise, it chops the right-most digit and calls the method again, as if the input was that new number. It stops once the number is left with only a single digit.

Related

Java help - Output range with increment of 5

Write a program whose input is two integers, and whose output is the first integer and subsequent increments of 5 as long as the value is less than or equal to the second integer.
-15 10
the output is:
-15 -10 -5 0 5 10
Ex: If the second integer is less than the first as in:
20 5
the output is:
Second integer can't be less than the first. For coding simplicity,
output a space after every integer, including the last.
Here is the code I have gotten so far, however, it is producing an error at the bottom I have an example of the input, my output and what was expected. If anyone has any pointers or can show me updated code it would be appreciated.
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int first = in.nextInt(), second = in.nextInt();
if (first > second) {
System.out.println("Second integer can't be less than the first.");
} else {
while (first <= second) {
System.out.print(first + " ");
first += 10;
}
System.out.println();
}
}
}
Here's what kind of error it is showing:
Input
-15 10
Your output
-15 -5 5
Expected output
-15 -10 -5 0 5 10
You can use the range function from IntStream:
IntStream.range(-15, 10).filter(x -> x % 5 == 0);
As suggested by MC Emperor, there also is a faster solution:
IntStream.iterate(-15, i -> i + 5).limit((10+15)/5);
/**
* The algorithm is as follows:
* iterate(start, i -> i + step).limit((stop-start)/step)
*/

Having problems understanding following simple algorithm

public class Test1
{
public static void main (String[]args)
{
int number = 0;
for (int i = 0; i < 5; i++)
{
if (number != 0)
{
number = i * number;
}
else
{
number = i;
}
}
System.out.println (number);
}
}
I'm not quite sure how this algorithm works. My thought process is:
We set number to 0 by default.
In the for loop we are just saying, continue counting i till it's no longer smaller than 5.
We say that if number isn't 0, we update number by multiplying it with i. So in our case, i is 0,1,2,3 and 4.
Else we are saying the number is i and i is what we were counting.
Lastly, we print number.
Am I missing something? Am I wrong somewhere?
If I run this code why do I get 24 as output? I cannot understand how this simple program works.
public class Test
{
public static void main (String[]args)
{
int number = 0;
for (int i = 0; i < 5; i++)
{
if (number != 0)
{
number = i * number;//For i=2, 3, 4
}
else
{
number = i;//This is executed twice - for i=0 and i=1
}
}
System.out.println (number);
}
}
Let's understand this program.
Execution begins from the main() method.
A variable named number is defined and initialized to 0.
A loop control variable named i is defined. Its initial value is 0 and it is increased by 1 at the end of every iteration till it reaches 5. Note that i is never modified inside the loop body.
For i = 0, the condition number != 0 is false, the else block is executed. number = i. The value of number remains 0.
For i = 1, the condition number != 0 is false, the else block is executed. number = i. The value of number changes to 1.
For i = 2, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 2.
For i = 3, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 6.
For i = 4, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 24.
Since i = 5, the loop breaks. The value of number is printed.
This is how we end up getting 24 as the output.
Executing the algorithm step by step will help understanding it.
Let's start with the first line. As you said, this line just sets number to 0.
int number = 0; | number: 0
I included the value of the variable on the right side after the bar.
Second step is to start with the loop. Before the loop starts, the counter variable i is set to zero.
int i = 0; | number: 0, i: 0
As a second step we have to check if the loop criterion is fulfilled, so that the body of the loop will be executed.
The criterion of the loop is i < 5 and since the current value of i is 0 and 0 < 5, the body of the loop is executed:
if (number != 0) {
number = i * number;
} else {
number = i;
}
Since it is an if statement, we have to see if the if-condition is fulfilled. number is currently 0, so number != 0 is not true. This means we go to the else branch with is:
number = i; | i = 0 -> number = 0
Since i is zero, number continues to be zero after this statement was executed.
This is the end of the first execution of the loop. Last thing the loop does before restarting is incrementing the counter:
i++; | number = 0, i = 1
Now i < 5 is still true, so the loop body runs again.
We still have number = 0 therefore number != 0 is still false.
Note that i was updated to 1, but number was not until now. Now:
number = i; | i = 1 -> number = 1
Now the loop increments the counter and starts anew:
i++; | i = 2
Still i < 5, so the body of the loop is executed again.
For the first time number != 0 is true, because number = 1.
So now we execute:
number = i * number; | i = 2 -> number = 2
number used to be 1, i is to, so i * number = 2
Again the loop body ends, the counter is incremented and the loop restarts, since 3 < 5:
i++; | i = 3
Here again number != 0, so we execute
number = i * number;
which yields number = 6 since 2 * 3 = 6.
The same process continues one more time with i = 4.
Now number = 4 * 6 = 24.
We increment the counter
i++; | i = 5, number = 24
Now i < 5 is no longer true, the loop exits and
System.out.println(number);
prints the current value of number, 24 to the screen.
Your thought process was good, but it wasn't exact or detailed enough because the meshing/merging of the sequence of the multiplication (of number) with the sequence of incrementing i is important.
Work it out on paper with a table, one column per variable, one line per instruction executed:
i number
null 0 int number = 0; // i has not been initialized yet.
0 0 int i = 0;
0 0 number = i; // it took the else branch
1 0 i++
1 1 number = i;
2 1 i++
2 2 number = i * number
3 2 i++
3 6 number = i * number
4 6 i++
4 24 number = i * number
5 24 i++
5 24 falls out of loop since i < 5 is now false

Code doesn't print the correct number of repeated digits

So basically this is a method to print numbers from 0 to n but squared. And to return the number of digits "d" contained in the numbers from 0 to n.
So let's say n=10 and d=1, we will have 0 1 4 9 16 25 36 49 64 81 100 and the method should return 4 since there are 4 ones in this set of numbers.
This works fine, but when n is defined with a bigger integer that's where the method starts to return an incorrect number of digits.
for instance, if we have n=5750 and d=0, the method returns 3012 when it's supposed to return 4700. Where did I do wrong?
public static int numberOfDig(int n, int d) {
String output="";
for(int i=0;i<=n;i++){
output+=(int)Math.pow(i, 2)+" ";
}
String[] numbers=output.split(" ");
String digit= Integer.toString(d);
int count =0;
for(int i=0;i<numbers.length;i++){
if(numbers[i].contains(digit))count++;
}
return count;
}
Please don't hesitate to ask questions if you need further explanations.
Your problem is that you only increment your count by one when a number contains the digit d. You need to increment by the number of times d occurs in each number.
The relevant code is:
if (numbers[i].contains(digit))
count++;
So if d == 5 and numbers[i] == 25, you increment count by 1 which is correct.
However, if d == 0 and numbers[i] == 100 you increment count by 1 which is incorrect. You should increment by 2 (as there are two zeroes).
A simple test would be n=10 and d=1, where output will be 0 1 4 9 16 25 36 49 64 81 100 121. Your method will return 5 as there are five numbers that contain a 1, whereas it should return 6 as 121 contains two instances of 1.

for loop makes pause every 8 million iterations - why?

When I run the following code on Intellij with input 1000000000000 the process holds a moment every 8 million loops.
Why is it like this? Why doesn't run in one smoothly flow until the end?
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Please type a number");
long n = in.nextLong();
System.out.println("Thanks.");
long count = 0;
for (long i=0; i<=n; i++) {
if ((n+i) == (n^i)) {
count++;
if (count % 1000000 == 0)
System.out.println(count);
}
}
System.out.println(count);
}
}
The condition
(n + i) == (n ^ i)
will occur mostly when there are no overlapping bits in n and i, since in that case addition and XOR are basically the same thing.
For example, if n == 4 and i == 3, then in binary n == 100 and i == 011, so
n + i == 100 + 011 == 111 == 7
n ^ i == 100 ^ 011 == 111 == 7
I'm not convinced that there are no numbers with bits in common for which the condition also holds; but these are the "obvious" cases for which it is true.
The binary form of 1000000000000 is
1110100011010100101001010001000000000000
The least significant set bit here is the 12th bit (starting from zero-th at the right).
The 12th power of 2 is 4096. So, all of the numbers less than 4096 have no bits in common with n, so you'll count all the numbers 0-4095. From that point on, you'll only count the numbers which don't have the 12th bit set. So, the rate of counting numbers will slow down.
Then, you'll hit the 16th LSB. Now, you'll only count numbers without the 12th and 16th bits set. So, the rate of counting numbers will slow down some more.
etc etc.
The only reason for these "pauses" is the outer for loop naively iterates over all numbers up to n: it doesn't simply skip to the next number for which the condition holds.

Why does this while loop run after the condition is met?

When I do a regular while loop like this
int x = 0;
while (x < 2) {
System.out.println(x);
x = x + 1;
}
it prints
0
1
but this second while loop runs one more time after the condition is met.
class Hobbits {
String name;
public static void main(String [] args) {
Hobbits [] which = new Hobbits[3];
int number = -1;
while (number < 2) {
number = number + 1;
which[number] = new Hobbits();
which[number].name = "bilbo";
if (number == 1) {
which[number].name = "frodo";
}
if (number == 2) {
which[number].name = "sam";
}
System.out.print(which[number].name + " is a ");
System.out.println("good Hobbit name");
}
}
}
so the result is
bilbo is a good Hobbit name
frodo is a good Hobbit name
sam is a good Hobbit name
shouldn't it stop printing at "frodo is a good Hobbit name"
I set the condition for x < 2 so how does "sam" print if the while loop was supposed to stop at x == 1?
Edit: ohhh I get it now lol I was thinking like the increment was at the end of the code and the start was 0
Here's your test case more closely matching your code:
class Test {
public static void main(String[] args) {
int x = -1;
while (x < 2) {
x = x + 1;
System.out.println(x);
}
}
}
It does indeed print:
$ java Test
0
1
2
Your loop is not designed to stop when number is 2, it's designed to stop before the next iteration if the number is 2. Since you increment number early on in the loop, it will continue with that value until it's time to choose whether to iterate again.
Before the first iteration, number = -1 which is <2 so it should iterate.
Before the second iteration, number = 0, which is <2 so iterate.
Before the third iteration, number = 1, which is <2 so iterate.
Before the fourh iteration, number = 2, which is NOT <2 so stop.
You therefore get 3 iterations.
Your original test case had the right idea -- it's better to increment as the last step in the loop. That way, you start at 0 instead of -1, and you stop the loop based on the new value rather than the previous value.
I will try to trace through it for you.
First case this is what happens.
x = 0
is 0 < 2? yes
print 0
0 <- 0 + 1 // here it becomes 1
is 1 < 2? yes
print 1
1 <- 1 + 1 // here it becomes 2
is 2 < 2? no
exit program
second loop works a bit more like this
number = -1
is number < 2? yes
number <- -1 + 1 // here it becomes 0
make hobbit "bilbo" at index 0
0 does not equal either 1 or 2
print hobbit at index 0 who is "bilbo"
is 0 < 2? yes
0 <- 0 + 1 // here it becomes 1
number equals 1 so make "frodo" at index 1
print hobbit at index 1 who is "frodo"
is 1 < 2? yes
1 <- 1 + 1 // becomes 2
number equals 2 so make "sam" at index 2
print hobbit at index 2 who is "sam"
is 2 < 2? no
end program
There's nothing wrong in that behaviour. You set number = -1 and then you do a loop that will iterate while number < 2. So, -1, 0 and 1. Three iterations. What's the problem? Let's do a simple trace:
number = -1
(-1 < 2)? Yes. Execute code inside while.
number = number + 1 (0)
(0 < 2)? Yes. Execute code inside while.
number = number + 1 (1)
(1 < 2)? Yes. Execute code inside while.
number = number + 1 (2)
(2 < 2)? No. Continue with the next instruction after the while block.
you can solve this easily with replace
int number = -1;
to
int number = 0;
Because! -1 + 1 = 0;
Because you have 3 iterations that are true:
-1 < 2 == true
0 < 2 == true
1 < 2 == true
2 < 2 == false
Cheers

Categories

Resources