Recursion and multiplication - java

Is this possible guys? This is homework I have, and my teacher obviously believes it is, but it seems to me that it's impossible not to use addition or multiplication outside of the short-multiplication method.
Write (and provide a tester for) a recursive algorithm:
int multiply(int x, int y)
to multiply two positive integers together without using the *
operator. Do not just add x to itself y times!!!
(Hint: Write a recursive method that will multiply an integer by a
value in the range 0 .. 10. Then write a second recursive method to
implement the multiplication algorithm you learned to multiply
multi-digit numbers in elementary school.)
My issue is that once you break down any multi digit number and starting adding those together you have to use multiplication of numbers greater than 10, i.e 22 * 6 is 2 * 6 + 20 * 6 ... so am I totally missing something?
EDIT
I guess I should have added this is the code I have,
public int mult(int x, int y){
return x == 0 ? 0 : (mult(x-1, y) + y);
}
which is perfect, but as far as I understand the instructions, that's breaking do not just add x to itself y times. I personally believe it isn't, but my teacher hasn't been very clear, and I'd like to know if there's some other way that I havn't thought of, sorry for the confusion.

Yes, it's possible. Yes, I think you're missing something. Try writing down the steps you'd follow to manually multiply two numbers, the way you learned in elementary school.
Then turn those steps into code.

My interpretation of the assignment is that the teacher would like the student to implement a recursive algorithm to perform Grid method multiplication (the kind we learn in elementary school).
For example, multiplying 34 x 13 would be done like so...
34
* 13
====
12
90
40
+300
====
442
I didn't have easy access to a Java development environment, so I wrote the code in C# but the algorithm should be simple enough to convert into Java.
public int Multiply(int x, int y)
{
if (x < 0) throw new ArgumentException("must be positive integer", "x");
if (y < 0) throw new ArgumentException("must be positive integer", "y");
if (x == 0 || y == 0) return 0; // obvious quick-exit condition
// integer division
int xDivBy10 = x / 10;
int yDivBy10 = y / 10;
bool xIsSingleDigit = xDivBy10 == 0;
bool yIsSingleDigit = yDivBy10 == 0;
// base case
if (xIsSingleDigit && yIsSingleDigit)
{
return MultiplySingleDigits(x, y);
}
// otherwise, use grid multiplication recursively
// http://en.wikipedia.org/wiki/Grid_method_multiplication
if (xIsSingleDigit) // y must not be a single digit
{
return (Multiply(x, yDivBy10) * 10) + Multiply(x, y % 10);
}
if (yIsSingleDigit) // x must not be a single digit
{
return (Multiply(xDivBy10, y) * 10) + Multiply(x % 10, y);
}
// else - x and y are both numbers which are not single digits
return (Multiply(x, yDivBy10) * 10) + Multiply(x, y % 10); // the same code as the "if (xIsSingleDigit)" case
}
// technically, this algorith can multiply any positive integers
// but I have restricted it to only single digits as per the assignment's requirements/hint
private int MultiplySingleDigits(int x, int y)
{
if (x < 0 || x > 9) throw new ArgumentException("must be in range 0 - 9 (inclusive)", "x");
if (y < 0 || y > 9) throw new ArgumentException("must be in range 0 - 9 (inclusive)", "y");
if (x == 0 || y == 0) return 0; // base case
return x + MultiplySingleDigits(x, y - 1);
}
NOTES:
This approach still uses the * operator but not for actually multiplying x and y, it is used to increase other sub-products by multiples of 10
Many parts of this code could be simplified/refactored but I specifically left them expanded to make the steps more obvious

Of course you can do it.
First of all, think about the condition. If some number is 0, then the result is? Right.. zero.
So.. You'll have if x is zero or y is zero return 0
Now.. saying X * Y is like saying "X, Y times", which is like writing: X + .... + X (Y times).
So, you'll have something like:
x + multiply(x, y - 1);
You'll have to consider the case in which one of the numbers is negative (But if you understand the basic, I believe you can easily do it).

This solution will work for both when y>=0 and y<0
public int multiply(final int x, final int y) {
if (y != 0 && x != 0) {
if (y > 0) {
return multiply(x, y - 1) + x;
} else {
return multiply(x, y + 1) - x;
}
}
return 0;
}

Easily possible.
int multiply(int x, int y) {
if(y == 0) {
return 0;
}
return x + multiply(x, y - 1);
}
The above fails to take into account the case where y is negative, but you wouldn't want me to do all your work for you . . .

static int Multiply(int x, int y)
{
if (y > 0 && x > 0)
return (x + Multiply(x, y - 1));
if (y < 0 && x > 0)
return -Multiply(x, -y);
if (x < 0 && y > 0)
return -Multiply(-x, y);
if (x < 0 && y < 0)
return Multiply(-x, -y);
return 0;
}

Related

Smarter way to calculate adjacent mines in Minesweeper using Java 8 Streams

Hey guys I started programming a year ago and recently discovered streams. So I decided to complete my old tasks using streams whenever I could just to get used to them. I know it might not be smart to force using them but it's just practice.
One of my old tasks was to program Minesweeper and right now I try to find a better solution for counting adjacent mines whenever I click a field.
Some details:
I saved a bunch of mines in a Mine[] (arsenal.getArsenal()) and each of the mines has an x and y value. Whenever I click on a field I need to count all mines around the clicked field (from x-1,y-1 till x+1,y+1).
My current solutions are:
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> mine.getX() == x + 1 && mine.getY() == y
|| mine.getX() == x && mine.getY() == y + 1
|| mine.getX() == x - 1 && mine.getY() == y
|| mine.getX() == x && mine.getY() == y - 1
|| mine.getX() == x - 1 && mine.getY() == y - 1
|| mine.getX() == x - 1 && mine.getY() == y + 1
|| mine.getX() == x + 1 && mine.getY() == y - 1
|| mine.getX() == x + 1 && mine.getY() == y + 1)
.count();
}
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine ->
{
boolean b = false;
for (int i = -1; i < 2; ++i) {
for (int j = -1; j < 2; ++j) {
if ((x != 0 || y != 0) && mine.getX() == x + i && mine.getY() == y + j) {
b = true;
}
}
}
return b;
})
.count();
}
Both solutions work fine but the first looks "wrong" because of all the cases and the seconds uses for-loops which I basically tried to avoid using.
It would be nice if you could show me a better (ideally shorter) solution using streams. :D
I'm sorry if there's already a thread about this. I really tried to find anything related but there either isn't anything or I searched for the wrong keywords.
You can simplify your stream condition. Instead of checking each case if getX() equals x, x-1 or x+1 you can just check if getX() is greater or equals than x-1 and smaller or equals x+1. The same for getY().
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> mine.getX() >= x - 1 && mine.getX() <= x + 1
&& mine.getY() >= y - 1 && mine.getY() <= y + 1)
.count();
You could also create a method for the check to make the code more readable.
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> inRange(mine.getX(), x)
&& inRange(mine.getY(), y))
.count();
}
private boolean inRange(int actual, int target) {
return actual >= target - 1 && actual <= target + 1;
}
Another way is to check if the absolute distance in each direction is less than or equal to 1:
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> Math.abs(mine.getX() - x) <= 1 && Math.abs(mine.getY() - y) <= 1)
.count();
}
Note that this also counts a mine which is at the point (x, y) which is not the case with the code in the question.
When is a mine adjacent? When its only one field horizontally or vertically away.
Horizontal distance is Math.abs(mine.getX() - x), vertical distance is Math.abs(mine.getY() - y). It doesn't matter if its -1 or 1, just that it is one field away.
But it shouldn't be more than one field, either vertical or horizontal be away, so max(dx, dy) == 1.
Predicate<Mine> isAdjacent = mine ->
Math.max(
Math.abs(mine.getX() - x)
Math.abs(mine.getY() - y)
) == 1;
return (int) Arrays.stream(arsenal.getArsenal())
.filter(isAdjacent)
.count();

Getting stack overflow when trying to have the method repeat when there is an even number inputted

I have this code :
public static int rsnpeasant(int x, int y) {
if ((y & 1) == 0) {
y = y / 2;
x = x * 2;
rsnpeasant(x, y);
} else {
sum = sum + x;
y = y / 2;
y = y - 1 / 2;
x = x * 2;
if (y == 1) {
sum = total;
return total;
} else {
rsnpeasant(x, y);
}
}
total = sum;
return total;
}
The error is happening on the first rsnpeasant(x,y); line in the first if statement. It seems to be forever looping to that line even though it's supposed to go to the else statement if y is odd. If y is divided by 2 it should become odd at some point.
Link is what im trying to code
y=y-1/2...
Order of operations will evaluate the 1/2 and subtract that from y. In integer arithmetic, 1/2 is 0. I think you want y=(y-1)/2.
Your principal problem is that you are trying to divide an int primitive type, if y = 1, dividing that value by 2 will return 0, then you pass it to the method again, it will always be stuck in the first if statement.
You should return a double, float or bigdecimal in your method, and use one of those types for the parameters too.

Can the standard Ackermann be optimized?

The standard Ackermann formula as written in Java:
public static int ack(int x, int y) {
if (x == 0) {
return y + 1;
} else if (y == 0) {
return ack(x-1, 1);
} else {
// perforce (x > 0) && (y > 0)
return ack(x-1, ack(x,y-1));
}
}
I've been wondering - is there a faster version to implement this? I'm thinking maybe there is by using an accumulator or a loop.
Yes, for example by "cheating". If m is 5 or higher, none of the results can be represented by an int. For m = 4, only the n < 2 cases can be represented. For m < 4, there are simple closed formula's based on n.
Everything else would overflow anyway, so let's pretend those cases don't even happen (or you could throw an error or whatever).
Not tested:
int Ackerman(int m, int n) {
switch (m) {
case 0:
return n + 1;
case 1:
return n + 2;
case 2:
return n * 2 + 3;
case 3:
return (int)((1L << (n + 3)) - 3);
case 4:
return n == 0 ? 13 : 65533;
}
}
I can tell you one thing... int will not suffice for very many values of x and y
If you're going to be calling the function repetitively, you can create a int[][] array to store various values so you can look them up the second+ time around and only need to compute it once. But as for speeding up a single execution... not sure.
This variation is faster:
public static int ack(int x, int y) {
while (x != 0) {
y = y == 0 ? 1 : ack(x, y - 1);
x--;
}
return y + 1;
}

float within 3 of each other if else statement?

Is there a way in Java to make it so that if X is within 3 of Y that it will be true (need a if statement).
I tried:
import java.util.*;
import java.io.*;
public class e4 {
public static void main (String arg[]) {
if ( ( (x - 3) <= y ) || ( (x - 3) <= y) || (x >= (y -3) ) || (x >= (y -3) ))
{
System.out.println("Your are within 3 of each other!");
}
else
{
System.out.println("Your NOT within 3 of each other.");
}
} //end main
} //end class
Thanks a lot for any help!
Use something simpler:
if (Math.abs(x - y) < 3.0) {
// within 3
}
You don't need Math.abs. Do this.
if ( x >= y - 3 && x <= y + 3 )
Here's a case where Math.abs gives you a wrong answer, because the subtraction loses the small quantity from the small float. If accuracy is important to you, you should avoid using Math.abs for this reason.
Note that it's possible to concoct an example where a similar thing happens with MY solution; but there are fewer such examples, and they only happen where the "ranges" represented by x and y contain parts that differ by more than 3 and parts that differ by less than 3.
float x = - 0.2500001f;
float y = 2.75f;
System.out.println( x >= y - 3 && x <= y + 3 ); // Prints false (correct)
System.out.println( Math.abs(x-y) <= 3.0); // Prints true (wrong)

Recursive function taking ages to run

I profiled my code and found that my program spent roughly 85% of the time executing this particular recursive function. The function aims to calculate the probability of reaching a set of states in a markov chain, given an initial position (x,y).
private static boolean condition(int n){
int i = 0;
while ( n >= i){
if( n == i*4 || n == (i*4 - 1))
return true;
i++;
}
return false;
}
public static double recursiveVal(int x, int y, double A, double B){
if(x> 6 && (x- 2 >= y)){ return 1;}
if(y> 6 && (y- 2 >= x)){ return 0;}
if(x> 5 && y> 5 && x== y){ return (A*(1-B) / (1 -(A*B) - ((1-A)*(1-B))));}
if(condition(x+ y)){
return (recursiveVal(x+1, y,A,B)*A + recursiveVal(x, y+1,A,B)*(1-A));
}
else{
return (recursiveVal(x+1, y,A,B)*(1-B) + recursiveVal(x,y+1,A,B)*B);
}
}
I was once told that 99% of recursive functions could be replaced by a while loop. I'm having trouble doing this though. Does anyone know how I could improve the execution time or rewrite this as a iterative loop?
Thanks
You could try to use a technique called memoization which basically caches previously computed results for recursive calls.
Wikipedia article on memoization.
As a side note, I recommend reformatting your code a bit. Here is a simplified version of yoru code.
private static boolean condition(int n){
for (int i = 0; i <= n; i++)
if(n == i*4 || n == (i * 4 - 1))
return true;
return false;
}
public static double recursiveVal(int x, int y, double A, double B){
if (x > 6 && (x - 2 >= y))
return 1;
if (y > 6 && (y - 2 >= x))
return 0;
if(x > 5 && y > 5 && x == y)
return A*(1-B) / (1 -(A*B) - ((1-A)*(1-B)));
double val1 = recursiveVal(x+1, y, A, B);
double val2 = recursiveVal(x, y+1, A, B);
return condition(x + y)
? A * val1 + val2 * (1-A)
: (1-B) * val1 + B * val2;
}
If you want to refactor a recursive function to an iterative one the steps are as follows:
1) Determine the base case of the Recursion. Base case, when reached, causes Recursion to end. Every Recursion must have a defined base case. In addition, each recursive call must make a progress towards the base case (otherwise recursive calls would be performed infinitely).
2) Implement a loop that will iterate until the base case is reached.
3) Make a progress towards the base case. Send the new arguments to the top of the loop instead to the recursive method.
Example of how trying to understand what it is doing can make the code faster/simpler...
This method is trying to determine if 'n' is a multiple of 4 or n+1 is a multiple of 4. This can be written much shorter as.
private static boolean condition(int n){
return (n+1) & 3 <= 1;
}
To convert this to an iterative form, note that you are computing a function on two (discrete) variables. You can use a table to store the values of the function, and fill in the table in a specific order so that you have already computed values you need by the time you need them. (in this case, from higher values of x and y).
In this case, the boundary cases (corresponding to the base cases in the original recursion) are:
f(7, y..5), f(8, 6)
f(x..5, 7), f(6, 8)
f(7, 7)
Then we fill in f(7, 6) and f(6, 7) and then proceed "downwards" - i.e.
f(6, 6), f(5, 6) ... f(x, 6), f(6, 5), f(5, 5) ... f(x, 5) ... f(x, y).
Note that what looks like function call syntax corresponds to a table lookup (it really converts to array syntax).

Categories

Resources