Recursive method - Java - java

Addition information:
Chip doesn't support multiplication, only addition. I should work around this problem by creating a recursive method, mult(), that performs multiplication
of x and y by adding x to itself y times. Its arguments are x and y and its return
value is the product of x and y. I should then write the method and a main() to
call it.
It's pure logical thinking, but I get lost every time I try to think what to do.
I am stuck at the math part..
What I have, that doesn't work and I know the math is wrong, but I am not good at this:
public static void mult(int x, int y) {
x = 0;
y = 0;
if (y > 0) {
for (int i = 0; i < y; i++) {
x = x * (x * y);
return mult(x, y);
}
}
}

When I hear "recursion", I expect to see two things:
A function calling itself with modified arguments each time.
A stopping condition right at the top that tells the function when to stop, avoiding an infinite stack.
So where are yours? Start with writing those down in words before you write code.

One possibility is to use an accumulator which will store the current value of the multiplication. I replace missing statements by ??? :
public static void main(String []args){
System.out.println(mult(2,5));
}
public static int mult(int x, int y) {
if(???) return ???;
else return multAcc(???,???,???);
}
private static int multAcc(int x, int y, int acc){
if(???) return ???;
else return multAcc(???, ???, ???);
}

... by adding x to itself y times.
You could actually do that, instead of multiplying. Oh, and maybe if you don't set both x and y to zero, you would have something to add ;-)
One last thing: If you want a recursive solution, you don't need the for-loop.

Java has no TCO by design, so using recursion for linear (not tree-like) processes is very bad idea. Especially for such task, which will most likely become a bottleneck in your program. Use loop instead.
Oh, it must be recursive anyway? Looks like a homework task. Do it yourself then.

All you need to remember is that a multiplication is a repeated addition (assuming that both operands are >= 0), so we have:
The base case is when y is zero
If y is not zero, then add x one more time, and subtract 1 from y
Notice that as long as y is positive, it'll eventually have a value of zero. So basically we keep adding x a total number of y times; this is what I mean:
public static int mult(int x, int y) {
if (y == 0)
return 0;
return x + mult(x, y-1);
}
The same code can be written in a tail-recursive style, too - meaning: there's nothing to do after the recursive call returns, and this is important for certain languages that support a so-called tail-call optimization:
public static int mult(int x, int y, int accumulator) {
if (y == 0)
return accumulator;
return mult(x, y-1, x + accumulator);
}
The above will get called as follows, noticing that the last parameter is always initialized in zero:
mult(10, 5, 0)
=> 50

public static int mult(int x, int y) {
if (y == 0) {
return 0;
}
if (y > 0) {
return x + mult(x, y - 1);
} else {
return -x + mult(x, y + 1);
}
}
this was the solution by the way

Related

reset variable in recursive method back to zero after its done/before its called again?

I was given the task to code the following recursive method. midresult is supposed to be 0 when I call the method. It works if I call the method just once, but because I have this midresult variable, as soon as I call it more than once in a row it returns wrong values because it adds up midresult.
How do I set back midresult to 0 each time after the method is done running? Im not allowed to put it in my main method, but I can't put it into the actual recursive method because this will mess up the recursion right?
eg for x=5, y=9 the result should be 15, which works if I only call the method once. But if I call it with x=5 and y=9 after calling it with other xy values the return value is wrong.
static int value;
public static int recursivemethod(int x, int y) {
// TODO
if(x==0) {
return y + value;
}
else{
if((x+value)%2==0) {
value+= (x/2);
int temp= y;
y=(x/2);
x=temp;
return recursivemethod(x, y);
}
else {
value+= y;
x-=1;
y=(y/2);
return recursivemethod(x, y);
}
}
}
You're storing recursion results in a global variable. It is initialized to 0; this is why your first function call is working; after that, however, whatever value is stored in midresult afterwards is what is used by later function calls. You mentioned you weren't allowed to modify main, so try changing your recursive base case
if(x == 0) {
return y + midresult;
}
to this
if(x == 0) {
int temp = y + midresult;
midresult = 0;
return temp;
}
I would not use a static variable to hold midresult. In some circumstances, that can cause problems. An alternative is to use a helper method to pass midresult as an argument. That value will be passed to the helper when the original method is invoked. Then you don't need to worry about resetting it for subsequent use.
public static int recursivemethod(int a, int b) {
return recursivemethod(a, b, 0);
}
private static int recursivemethod(int x, int y, int midresult) {
// TODO
if (x == 0) {
return y + midresult;
} else {
if ((x + midresult) % 2 == 0) {
midresult += (x / 2);
int temp = y;
y = (x / 2);
x = temp;
return recursivemethod(x, y, midresult);
} else {
midresult += y;
x -= 1;
y = (y / 2);
return recursivemethod(x, y, midresult);
}
}
}
Of course, this might be avoided too if you explain the overall algorithm you are trying to recursively implement. You can edit your question to do this. Just don't change your existing code/approach as answers and comments have been provided based on that code.

java complex if statement causes StackOverflowError [duplicate]

This question already has answers here:
What is a StackOverflowError?
(16 answers)
Closed 4 years ago.
I made a recursive method to find the least number of rallies that could be played before one or another team wins with given points team should score to win - k, current points of two teams - x and y.
So it looked like
public static int scores(int k, int x, int y, int rally) {
if (x==k || y==k)
return rally;
else {
rally++;
return Math.min(scores(k, x + 1, y, rally), scores(k, x,y+1,rally));
}
}
When I called this method with custom values in main method
scores(5,0,0,0)
It worked fine. But when I changed IF statement to check that the winner has at least two-point margin
if ((x==k || y==k) && Math.abs(x-y)>=2)
The program showed java.lang.StackOverflowError
I am extremely bad at this, please help me
Take note that you never increase k value, that means that if x/y == k and difference isn't 2 points, it will pass on and x/y will never equal k again.
I will imagine that something like this, should work
public static int scores(int k, int x, int y, int rally) {
if ((x>=k || y>=k) && (Math.abs(x-y))>=2)
return rally;
else {
rally++;
return Math.min(scores(k, x + 1, y, rally), scores(k, x,y+1,rally));
}
}
Edit: As pointed out in the comments, there is another issue with this code, that causes SO when opposite players get one point each all the time.
You can fix the stack overflow error that occurs when X and y alternate in "winning" by keeping track of the minimum found so far:
public static int scores(int k, int x, int y, int rally) {
return scores(k, x, y, rally, Integer.MIN_VALUE);
}
public static int scores(int k, int x, int y, int rally, int minSoFar) {
if (rally >= minSoFar || ((x>=k || y>=k) && (Math.abs(x-y))>=2))
return rally;
else {
rally++;
minSoFar = Math.min(minSoFar, scores(k, x+1, y, rally));
minSoFar = Math.min(minSoFar, scores(k, x, y+1, rally));
return minSoFar;
}
}
But it should be noted that the minimum path will always be the one where X always wins (or Y always wins). So:
return Math.max(2, k);
Is a much easier way to express the result.

What is wrong with my Java recursive function?

I'm trying to write a relatively straightforward recursive program in Java to compute all the possible ways to traverse a 4x4 matrix (not necessarily traveling through every spot), starting at the top left and ending in the bottom right spaces. I use a 2-D array to do this, marking off visited spaces with "1"s as I go.
It's been a while since I've worked recursively and I can't seem to get the output I expect. The output from the code below is "2" - obviously, the result should be much higher. I know there's something tiny I'm overlooking. Can someone tell me what it is?
public static void main(String[] args) {
int[][] matrix = new int[4][4];
int result = moveRobot(matrix, 0, 0);
System.out.print(result + "");
}
public static int moveRobot(int[][] matrix, int x, int y) {
if (x == 3 && y == 3) {
return 1;
} else if (x < 0 || y < 0 || x > 3 || y > 3) {
return 0;
} else if (matrix[x][y] == 1) {
return 0;
} else {
matrix[x][y] = 1;
return moveRobot(matrix, x, y+1) + moveRobot(matrix, x+1, y) + moveRobot(matrix, x, y-1) +
moveRobot(matrix, x-1, y);
}
}
The problem is that the matrix is not copied but passed by value of the reference to it. Every time you modify it such in matrix[x][y] = 1 other successive code paths will see the modification instead that working on an unmodified state.
For example here:
moveRobot(matrix, x, y+1) + moveRobot(matrix, x+1, y)
Entering the first call will modify matrix, so in second moveRobot call you'd end up with 1 in matrix[x][y+1] while that's not what you want.

Multiplication using increments

My assignment is to write a recursive function to multiply two numbers together, using only an addition function, ++, and --. My addition function is:
public static int peanoplus(int x, int y) {
if(y==0) return x;
else return peanoplus(++x,--y);
}
What I have so far for my multiplication function is:
public static int peanotimes(int x, int y)
{
if(y==0) return x;
else return peanotimes(peanoplus(x,x),--y);
}
I am not exactly sure what to put in the first parameter for the peanotimes function. Right now the issue is that I'm doubling the number, rather than adding it to the original number. I know that I need to maintain the x variable so that the recursive calls can continue adding the original number (instead of doubling every time), but then where would I actually add the numbers?
I found this which is very similar to my question, but even with those tips I am unable to find a solution.
if( y == 0 || x == 0 ) { return 0; }
else { return peanoplus(x, peanotimes(x,--y)); }
This version closest matches the formal Peano axiom of x * S(y) = x + (x * y)
public static int peanotimes(int x, int y)
{
if (y == 0) {
return 0; // terminate recursion, NB: not "x"
} else {
return peanoplus(x, peanotimes(x, --y));
}
}

Java - Recursive function of the Euclidean Algorithm

I can't seem to convert the following algorithm into Java successfully, please forgive the horrible picture quality but a question I'm working on asks:
I have tried to use the following code to represent the Euclidean Algorithm, but it doesn't seem to work. I don't really know how I would go about representing it in Java code. Any help?
public static int gcd(int x, int y) {
if (y == 0) {
return x;
} else if (x >= y && y > 0) {
return gcd(y, (x % y));
}
}
Thank you.
There is no arbitrary order between x and y.
Your code is not complete!
What if x < y? Your code does not return a value then!
What the book fails to mention is that the two parameters to the function do not necessarily need to be in descending order (ie x >= y). What you need to do is compute the gcd considering this fact.
Simply you can do the following:
public static int gcd ( int x , int y )
{
if ( y == 0 )
return x;
else if ( x >= y && y > 0)
return gcd ( y , x % y );
else return gcd ( y , x ); // if x < y then go ahead and switch them around.
}
You are almost there. You need to consider what happens when y > x, and return the result from the final else branch (hint: x and y can freely switch places).
You are almost there.
Your code does not compile, because there is no catch all clause that return from the function.
It really depends on whether you are going to pass negative values of y into this function. If you expect only positive values, just throw an exception.
public static int gcd(int x, int y) {
if (y == 0) {
return x;
} else if (x >= y && y > 0) {
return gcd(y, (x % y));
}
throw
new IllegalArgumentException(
String.format(
"Unexpected values for x(%d) and y(%d)",
Integer.valueOf( x ),
Integer.valueOf( y )
)
);
}
Here's what I have that accounts for negative numbers:
public static int gcd(int x, int y)
{
if (y == 0)
return x;
if (x < 0)
return gcd(x * -1, y); //turns the first parameter to a positive if it's initally negative
if (y < 0)
return gcd(x, y * -1); //turns the second parameter to a positive if it's initally negative
if (y <= x && x % y == 0)
return y;
return gcd(y, x%y);
}
Note with negative numbers, if you try to find the greatest common divisor, and either of the numbers is negative, you can just change it to a positive and the result would be the same.
If both of the numbers are negative, then I'm not sure what the gcd should be. 1? -1? idk so I left that out. The code I have just treats it as if they were both positive.

Categories