How is the recursion method adding itself? - java

Hello guys I have something that my brain is having a hard time trying to figure out.
My homework is to have "x" bunnies. It recursively calculates the total number of bunny ears.
The even numbered bunnies have the normal two ears, the odd numbered bunnies have 3 ears, but every 5th bunny has 1 ear. My code is complete and work... Here it is...
import java.util.*;
public class bunnies
{
public static int y;
public static void main(String[] args)
{
y = 0;
System.out.println(BunnyEars(3));
}
public static int BunnyEars(int x)
{
if ((x % 5) == 0 && x != 1 && x != 0)
return 1 + BunnyEars(x - 1);
else if ((x % 2) == 0 && x != 0 )
return 2 + BunnyEars(x - 1);
else if ((x % 2) != 0 && x != 0)
return 3 + BunnyEars(x - 1);
else
return 0;
}
}
My question is, how in the world does the first number of ears accumulate to the second number of ears and so on?
I was thinking naming a global variable for int y = 0;
and then
if ((x % 5) == 0 && x != 1 && x != 0)
y += 1;
else if ((x % 2) == 0 && x != 0 )
y += 2;
else if ((x % 2) != 0 && x != 0)
y += 3;
else
return 0;
return y + BunnyEars(x -1);
I think this makes more sense because y is accumulating but it doesn't.
Can you guys please explain how the other one accumulates and not y?
THanks!

Here's your method:
public static int BunnyEars(int x)
{
if ((x % 5) == 0 && x != 1 && x != 0)
return 1 + BunnyEars(x - 1);
else if ((x % 2) == 0 && x != 0 )
return 2 + BunnyEars(x - 1);
else if ((x % 2) != 0 && x != 0
)
return 3 + BunnyEars(x - 1);
else
return 0;
}
Here's a hypothetical example call:
BunnyEars(7)
This then becomes
return 3 + BunnyEars(6)
Which becomes
return 3 + 2 + BunnyEars(5)
return 3 + 2 + 1 + BunnyEars(4)
return 3 + 2 + 1 + 2 + BunnyEars(3)
return 3 + 2 + 1 + 2 + 3 + BunnyEars(2)
return 3 + 2 + 1 + 2 + 3 + 2 + 3 + BunnyEars(0)
return 3 + 2 + 1 + 2 + 3 + 2 + 3 + 0
return 16
Suggested improvement to the code: Add a guard clause to the beginning:
if (x == 0) return 0;
Then you can remove all of the && x != 0s in the if statements. This will clean up the code a lot.
You also have lots of extraneous parenthesis - (x % 2) == 0 is the same as x % 2 == 0.
Improved code:
public static int BunnyEars(int x)
{
if (x < 0) throw new IllegalArgumentException("Bunnies cannot be negative"); // handle bad input
if (x == 0) return 0;
if (x % 5 == 0) // no need for `&& x != 1` because 1 % 5 isn't 0 anyway
return 1 + BunnyEars(x - 1);
else if (x % 2 == 0)
return 2 + BunnyEars(x - 1);
else if (x % 2 != 0)
return 3 + BunnyEars(x - 1);
}

I was thinking naming a global variable for int y = 0 and then
No, global variable should not be used there (although having a local variable could give you slightly more clarity):
if (x == 0) return 0; // Zero bunnies --> zero ears
int y = 0; // Variable y represents the number of ears that bunny number x has
if ((x % 5) == 0 && x != 1 && x != 0)
y = 1;
else if ((x % 2) == 0 && x != 0 )
y = 2;
else if ((x % 2) != 0 && x != 0)
y = 3;
return y + BunnyEars(x -1);
The trick to this (and any other) recursive function is realizing that there's more than one x. Since the function calls itself with a different argument, so each invocation has its own x.
Here is how the sequence of calls and returns looks:
BunnyEars(x==6)
Compute y for x==6 // That's 2
Call BunnyEars(x==5)
Compute y for x==5 // That's 1
Call BunnyEars(x==4)
Compute y for x==4 // That's 2
Call BunnyEars(x==3)
Compute y for x==3 // That's 3
Call BunnyEars(x==2)
Compute y for x==2 // That's 2
Call BunnyEars(x==1)
Compute y for x==1
Call BunnyEars(x==0)
return 0 // Zero bunnies --> zero ears
return 2+0 --> 2
return 3+2 --> 5
return 2+5 --> 7
return 1+7 --> 8
return 2+8 --> 10
Once you see that more than one call to BunnyEars is active at the same time, this should start to make sense: the chain of calls goes on without returning until it hits the x==0 "no bunny - no ears!" clause, at which point the chain starts to unroll, adding the proper number of ears to the return value of the previous invocation.

So for BunnyEars(5) let's trace it.
BunnyEars(5)
1 + BunnyEars(4)
1 + 2 + BunnyEars(3)
1 + 2 + 3 + BunnyEars(2)
1 + 2 + 3 + 2 + BunnyEars(1)
1 + 2 + 3 + 2 + 3 + BunnyEars(0)
1 + 2 + 3 + 2 + 3 + 0
Note that none of the adding actually happens until the last BunnyEars call. Everytime it tries to add to the result of a recursive call it has to wait for the return, which will then call a new one etc. Then it works backwards returning to all of the methods adding the result along the way, before finally returning the result to the caller.

Try breaking it down case-by-case.
Say you have no bunnies
BunnyEars(0) will return 0, because it doesn't go into any of the other cases.
Say you have one bunny
BunnyEars(1) will return 3 + BunnyEars(0), which we already know is 0. So it will evaluate to 3 + 0 which equals 3.
Say you have two bunnies
BunnyEars(2) will return 2 + BunnyEars(1), which we already know is 3. So it will evaluate to 2 + 3 which equals 5.
Continue with this pattern, and it should illustrate how to step through this logic recursively.

I'll give another, easier, recursive example. Say we want the sum of all integer numbers up to n:
public static int sumUpTo(int n) {
if(n == 0) return 0;
return n + sumUpTo(n - 1);
}
Let's call this function for n equals 0. Of course, the check succeeds, and we get 0 as return value.
Let's call this function for n equals 1. The check fails, so we return 1 plus the result of sumUpTo(0). We already know this results in 0, so the final result is 1. We could say the result is 1 + sumUpTo(1 - 1) = 1 + sumUpTo(0) = 1 + 0 = 1.
For 2, we get the call: 2 + sumUpTo(2 - 1) = 2 + sumUpTo(1) = ... = 3. And so on. The accumulation you desired is done on the fly.

Related

How to trace through basic recursive code in java

I'm new to recursion and don't understand how it works.
This was a classwork problem that had the answer 18, but I don't understand how. From what I know, this should return 6 + 5 + 4 + 3 (3 + m-1 on the recursive line)?
Are the subtraction signs not indicative of subtraction? (assuming that m = 5)
public int test(int m)
{
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
return value;
}
6 + 5 + 4 + 3 (3 + m-1 on the recursive line)? Are the subtraction
signs not indicative of subtraction?
No the +3 will happen for every one of the recursive calls, actually what your function is doing is given the value of (m times 3) + 3.
So for m=5 the recursive calls will be like:
Is m = 0 ? No so let us called recursively:
test(4) + 3
m = 4; then test(3) + 3 + 3
m = 3; then test(2) + 3 + 3 + 3
m = 2; then test(1) + 3 + 3 + 3 + 3
m = 1; then test(0) + 3 + 3 + 3 + 3 + 3
m = 0; then exit with 3 + 3 + 3 + 3 + 3 + 3
Hence, for m=5 you get 18.
A side-note you can use the ternary operator to simplify your method to:
static public int test(int m) {
return (m == 0) ? 3 : test(m - 1) + 3;
}
For visualizing what happens, scatter the code with messages:
public int test(int m)
{
System.out.println("entering test("+m+")");
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
System.out.println("returning "+value+" from test("+m+")");
return value;
}
Of course this is just the minimal program, you could also show which branch of the if was taken, m-1, and so on.
JavaScript equivalent, so it can run here in the browser:
function test(m) {
console.log("entering test(" + m + ")");
var value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
console.log("returning " + value + " from test(" + m + ")");
return value;
}
console.log("result: "+test(3));
On the longer run it is a good idea to learn using the debugger of the environment you are using. Among other things, debuggers can step through code line-by-line.

What is returned by the call wacky 4,6? also how to calculate this recursion?

public static int wacky (int x , int y){
if(x <= 1){
return y;
}
else{
return wacky(x - 1, y - 1) + y;
}
}
I had a test a while but I still don't know how to do a recursion step by step and I remember this question by memory and I guess on the test thinking that you maybe calculate this way...
public static = 4 + 6 + 1 + 4 + 4 - 1 + 6 - 1 + 6
but was not of the answer choice I realize i was doing something wrong...
my teacher doesn't help me and don't even care I try to get help but he does not how to explain this...
When you call a function recursively, they add the new function to a stack until have a final result (return). When it occurs, you go back return by return in the stack.
An Execution example:
First Round wacky(4, 6):
4 <= 1? No, so call wacky(4 - 1, 6 - 1)
Second Round wacky(3, 5):
3 <= 1? No, so call wacky(3 - 1, 5 - 1)
Third Round wacky(2, 4):
2 <= 1? No, so call wacky(2 - 1, 4 - 1)
Fourth Round wacky(1, 3):
1 <= 1? Yes
return 3;
return 3 + 4;
return 3 + 4 + 5;
return 3 + 4 + 5 + 6;
Why not let Java tell you what is going on? Insert some print statements so you can see the values when the code runs:
private static int indent = 1;
public static int wacky(int x , int y) {
System.out.printf("%" + (indent++ * 2) + "swacky(%d, %d)%n", "", x, y);
int result;
if (x <= 1)
result = y;
else
result = wacky(x - 1, y - 1) + y;
System.out.printf("%" + (indent-- * 2) + "s-> %d%n", "", result);
return result;
}
Test
wacky(4, 6);
Output
wacky(4, 6)
wacky(3, 5)
wacky(2, 4)
wacky(1, 3)
-> 3
-> 7
-> 12
-> 18

Do two numbers contain same digits [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Ok, so I was wondering how can one check whether two numbers have the same digits, e.g. 21 and 12 are ok, also 1233 and 2313, but 123 and 1233 are not, meaning that the digits are permutation of another number's digits.
I know how to do it with arrays or strings or maps, but the problem is, that I don't want to do it with either of those, if there exists another solution.
The solution with arrays / maps:
Map<int, int> counter = new HashMap<int, int>();
for (int i = 0; i < 10; i++)
counter.put(i, 0);
int x = 2421, y = 4223; // testcase
while (x > 0 || y > 0) {
if (x == 0 || y == 0) // if they are not the same length, one will be 0 and thus they are not permutations
return false;
counter.put(x%10, counter.get(x%10) + 1);
counter.put(y%10, counter.get(y%10) - 1);
x /= 10;
y /= 10;
}
// For each digit we added 1 to the counter if it was found in `x`
// and subtract 1 if it was found in `y`.
return counter.values() == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
Now, the array approach is completely the same, since using a map for digits 0-9 is the same as using the key for map as the index in array. The solution without any data structure looks far from ideal to me:
private static boolean haveSameDigits(int x, int y) {
// Because we are not allowed to use maps, declare 10 vars...
int c0 = 0;
int c1 = 0;
int c2 = 0;
int c3 = 0;
int c4 = 0;
int c5 = 0;
int c6 = 0;
int c7 = 0;
int c8 = 0;
int c9 = 0;
while (x > 0 || y > 0) {
if (x == 0 || y == 0)
return false;
if ((x % 10) == 0)
c0++;
else if ((x % 10) == 1)
c1++;
else if ((x % 10) == 2)
c2++;
else if ((x % 10) == 3)
c3++;
else if ((x % 10) == 4)
c4++;
else if ((x % 10) == 5)
c5++;
else if ((x % 10) == 6)
c6++;
else if ((x % 10) == 7)
c7++;
else if ((x % 10) == 8)
c8++;
else if ((x % 10) == 9)
c9++;
if ((y % 10) == 0)
c0--;
else if ((y % 10) == 1)
c1--;
else if ((y % 10) == 2)
c2--;
else if ((y % 10) == 3)
c3--;
else if ((y % 10) == 4)
c4--;
else if ((y % 10) == 5)
c5--;
else if ((y % 10) == 6)
c6--;
else if ((y % 10) == 7)
c7--;
else if ((y % 10) == 8)
c8--;
else if ((y % 10) == 9)
c9--;
x /= 10;
y /= 10;
}
return c0 == 0 && c1 == 0 && c2 == 0 && c3 == 0 && c4 == 0 && c5 == 0 && c6 == 0 && c7 == 0 && c8 == 0 && c9 == 0
}
I have googled about it but no matter what I typed I ended up with a solution using strings or arrays.
I am not looking for a solution, I actually don't want it, I just need a hint to the approach.
Adding some more information: There is nothing prohibiting me from using any data structure I want, this is my program and nobody will be checking over what I do. I am just that kind of person that likes to learn new stuff, so I was wondering if there is a quick solution to it.
As stated in the comments, one can iterate over both numbers and check for each number in range (0,9) inclusive, how many times they appear in string but that obviously yields time complexity of O(n*n) which is not optimal.
You do not want to convert to string, or to use any helper data structures. How about this then: Create a hash from the numbers, in the form xor(2^d for every digit d in n)?
For example, hash(3112) will be (in binary) 1100.
Since you do not want a solution, here's some pseudocode (aka Python):
def hash(n):
r = 0
while n > 0:
d = n % 10 # last digit
n = n // 10 # remaining digits
r = r ^ 2**d # xor with 2^d
return r
def perm(n, m):
return hash(n) == hash(m)
Update: Turns out that the above does not work properly, as XOR can only keep track of whether a digit appears an even or odd number of times. Instead, you could create a hash using multiples of prime numbers. This way, hash(3112) becomes 7 * 3 * 3 * 5. While this uses a list to keep the first ten prime numbers, it does not create any new lists, arrays or maps while checking individual pairs of numbers. Also, keep in mind that the resulting hash might get very large -- larger than Java's int or long types. (You can probably take the modulo of another large prime number, but I'm not sure about that part.)
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
def hash(n):
r = 1
while n > 0:
d = n % 10 # last digit
n = n // 10 # remaining digits
r = r * primes[d]
return r
You can parse int's to strings and check with .contains
final List<Integer> intsForCheck = new ArrayList<>();
for (int i = 1; i < 180; i++)
intsForCheck.add(i);
final int num = 17;
intsForCheck.forEach(integer -> check(integer,num));
public static void check(int integer,int num)
{
final String _int = String.valueOf(integer);
final String _num = String.valueOf(num);
System.out.println(_int + (_int.contains(_num) ? " contains" : " not contains") + _num);
}

What is a good way to output why an object won't go through all of the "if" statements?

I am making a program that checks to see if an elements positive and negative charges are able to combine to make 0. A thing i want to do is output the reasons why the two elements are not able to combine. But it is more difficult than i expected. for example if sodium were trying to combine with copernicium, it would output this:
Sodium doesn't combine with Copernicium:
Both valence charges have same polarity.
One or more elements is man-made.
but i can not think of a way to implement this into my code.
here is my code:
public void combine(Element element){
if ((element.getValence() > 0 && valence < 0) || (element.getValence() < 0 && valence > 0)) { //one element needs a positive valence, and one needs a negative valence
if (valence != 0 && element.getValence() != 0) { //checks to see if valence is not equal to 0
if (natural == true && element.isNatural() == true) { //checks to see if both elements are natural
for (int x = 1; x <= 4; x++) {//bruteforce the atoms to see if they both add up to 0.
for (int y = 1; y <= 4; y++) {
if ((valence * x) + (element.getValence() * y) == 0) {
System.out.println(name + " combines with " + element.getName() + " to form " + symbol + "" + x + "" + element.getSymbol() + "" + y);
}
}
}
}
}
}
}
Thanks for any help!
The way to do this is to add else clauses for each if that return an appropriate message.
if ((element.getValence() > 0 && valence < 0) || (element.getValence() < 0 && valence > 0)) { //one element needs a positive valence, and one needs a negative valence
{
// the inner tests
}
else
{
System.out.println("The elements are both positive or both negative");
}
}
This should get you started in the right direction.

Result of recursive method

I am trying to understand this recursive method but even with a debugger I couldn't come up to something that makes sense to me so i hope someone here is motivated to explain me what is going on here. I know how recursion works basically but the way this method is written down troubles me.
I know the conditional operator in java and I worked out a new code but still I don't understand it, so what I expect here is.
What is the result for m(5) AND m(15). How did you calculate it? Thanks
Edit after the answers. I made a table with my results for future readers
m(n)::|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|...
result|0|0|1|1|1|2|3|4|6|9|13|19|28|41|60|88|...
I checked only the result of 15 with my program.
public class practice {
/**
* Try to understand the way this works
* #param n
* #return
*/
static long m(long n) {
return n <= 1 ? 0 : n == 2 ? 1 : m(n - 1) + m(n - 3);
}
/**
* This is what i tried so far.
* #param n
* #return
*/
static long ma(long n) {
System.out.println("Method called");
System.out.println("N is: " + n);
if (n <= 1) {
System.out.println("N<=1: " + n);
System.out.println("0 is returned");
return 0;
} else if (n == 2) {
System.out.println("N==2: " + n);
System.out.println("1 is returned");
return 1;
} else {
System.out.println("Inside ELSE, N is: " + n);
return ma(n - 1) + ma(n - 3);
}
}
public static void main(String[] args) {
ma(15);
}
}
Wrote it this way to make it more understandable:
m(0) = 0
m(1) = 0
m(2) = 1
m(n) = m(n - 1) + m(n - 3) // n >= 3
When we know the values for m(0), m(1) and m(2), we can calculate any m(n), where n >= 3, using m(n - 1) + m(n - 3). For any negative input, the result is 0.
For example:
m(3) = m(3 - 1) + m(3 - 3) = m(2) + m(0) = 1 + 0 = 1
m(4) = m(4 - 1) + m(4 - 3) = m(3) + m(1) = 1 + 0 = 1
m(5) = m(5 - 1) + m(5 - 3) = m(4) + m(2) = 1 + 1 = 2
And so on...
Pencil and paper are you friends.
There are 3 cases (two of them are base conditions)
if n <= 1 then return 0
if n == 2 then return 1
else recursive call to m(n-1) + m(n-3)
So you know that on every recursive call we are approaching one of the base conditions.
Here is a stack trace of what happens on m(5)
m(5)
m(4) + m(2)
m(3) + m(1) return 1
m(2) + m(0) return 0
return 1 return 0
Adding all the returns gives 1 + 0 + 0 + 1 which is 2
So
m(5) == 2
Method m in pseudo code. (this is some kind of scala/python mash up)
def m (number n)
if (n <= 1) 0
else if (n == 2) 1
else m(n - 1) + m(n - 3)
Looking at this you can see that anything <= 2 is a terminal operation, returning 0 or 1 based on the input. If n is > 2, the fun begins. Take for example n=3. Since 3 is greater than 2, we need to run the third if. When we look at that line we see that we nee to return m(n - 1) + m(n - 3). Plugging n = 3 in, it looks like this: m(3 - 1) + m(3 - 3), or, more simplified, like this: m(2) + m(0). This will now terminate with 1 because neither 2 or 0 for n will result in more calling of m.
So now we have something we understand we can now workout what m(15) and m(5) will return.
I will only work it out for 5 since the call stack for 15 would be way to long
m(5)
/ \
m(5-1) + m(5-3)
/ \ |
m(4-1) + m(4-3) |
/ \ | |
m(3-1) + m(3-3) | |
| | | |
1 + 0 + 0 + 1
2
Hope it helps!
m(5) = m(4)+m(2) // 5>2, so the third condition
m(4) + m(2) = m(3)+m(1) + 1 // 4>2, so the third condition
m(3) + m(1) + 1 = m(2)+m(0) + 0 + 1 // 3>2, so the third condition
m(2) + m(0) + 0 + 1 = 1 + 0 + 0 + 1 = 2
Now, between transformations, m(2) s instantly replaced with 1, and m(n<=1) is instantly replaced with 0. This is how you can analyze this on paper. Computer, however, would wirst calculate m(4) before calculating m(2) and adding the results in the first line - this happens because of order of poerations within the recursive functions.

Categories