Recursion multiply method correct way to think about it? - java

public static void main(String[]args){
multiply(2,4);
}
public static int multiply(int a, int b) {
if (b == 0) {
return 0;
}
return a + multiply(a, b - 1);
}
}
I have this recursive statement, and I am wondering how it works, is this the correct way to think about it?
return 2 + (2, 3);
return 2 + (2,2);
return 2 + (2,1);
return 2 + (2,0);
return 2 + 6;
return 2 + 4;
return 2 + 2;
return 2 + 0;

The easiest way is to try it:
public static int multiply(int a, int b) {
System.out.println("-->multiply("+a+", "+b+")");
if (b == 0) {
System.out.println("<--returning zero for "+a+"*"+b);
return 0;
}
int ret = a + multiply(a, b - 1);
System.out.println("<--returning "+a+"*"+b+" = "+ret);
return ret;
}
Your output will be:
-->multiply(2, 4)
-->multiply(2, 3)
-->multiply(2, 2)
-->multiply(2, 1)
-->multiply(2, 0)
<--returning zero for 2*0
<--returning 2*1 = 2
<--returning 2*2 = 4
<--returning 2*3 = 6
<--returning 2*4 = 8
The arrows show you when the stack grows (-->) and when it shrinks (<--). This is a useful technique to visualise recursive calls in general: log the input after you enter the method, and log your result before returning it.

I'm not exactly clear on what you are showing, though it looks fairly correct (if I'm interpreting it correctly). You need to work through each call of the method until you hit the base case (in this instance, it is when b == 0). Then, you can work your way back up, substituting in the values that are returned.
multiply(2,4) returns 2 + multiply(2,3).
multiply(2,3) returns 2 + multiply(2,2).
multiply(2,2) returns 2 + multiply(2,1).
multiply(2,1) returns 2 + multiply(2,0).
multiply(2,0) returns 0.
So, if we substitute in the return values, working from the bottom up, you get:
return 2 + 2 + 2 + 2 + 0;
which equals 8. 2 x 4 = 8.

You are almost perfect, just... Bear in mind that returning from recurence seems for us, poor humans, to revert the order of instructions as we tend to think about them.
Therefore:
YES, you are perfectly correct when analyzing nested calls.
NO, you make the mistake when analyzing returns, which happen in the following order (reverted compared to your feeling, but this makes sense if you think about the LAST function call returning FIRST):
Returning: 2+0
Returning: 2+2
Returning: 2+4
Returning: 2+6
As a general solution is better than a specific one, here is your original program which employs 2 additional printfs() and one additional variable (res). You can track any recurrence this way. :-)
public static void main(String[] args){
multiply(2,4);
}
public static int multiply(int a, int b) {
int res;
if (b == 0) {
return 0;
}
System.out.printf("Calling: %d+multiply(%d, %d)\n", a, a, b-1);
res = multiply(a, b - 1);
System.out.printf("Returning: %d+%d\n", a, res);
return a + res;
}

Related

Would anyone know how to do an algorithm iteratively (using while) for the following definition?

(Note: "en otro caso" means in another case; click in "enter image descriptioon here to view de image")
I want to make an iterative algorithm from the definition they have given me. I have it done with memory recursion, I share it if it helps:
public static Integer eje4ConMemoria(Integer d1, Integer d2, Map<Tuple2<Integer, Integer>, Integer> memoria) {
Integer result = null;
Integer a = d1;
Integer b = d2;
Tuple2<Integer, Integer> t = Tuple.create(a, b);
if (memoria.containsKey(t)) {
result = memoria.get(t);
} else if (a < 2 && b < 2) {
result = a + b * b;
memoria.put(t, result);
} else if (a < 2 || b < 2) {
result = a * a + b;
memoria.put(t, result);
} else {
result = eje4ConMemoria(a / 2, b - 1, memoria) + eje4ConMemoria(a / 3, b - 2, memoria)
+ eje4ConMemoria(a - 2, b / 4, memoria);
}
return result;
}
A simple list system should work here. The end result, if you expand any given g(a, b), is simply a long list of 'things to add together'. It'll be a gigantic chain of simple values (e.g. g(6, 2) becomes g(3, 1) + g(2, 0) + g(4, 0.5) and that becomes (6^2 + 2) + (2 + 0) + (4^2 + 0.5).
Thus, you can reconstrue the job as generating a list of terms that still need processing, plus keeping a count going for 'processed out' nodes.
NB: Some notes first; Integer is incorrect, use int. I have no idea why you are passing in a 'map of tuple2', Tuple2 is silly; it's not idiomatic at all, nobody* in the java community writes code like this.
NB2: You are doing integer division, i.e. you're saying that 3 divided by 2 is 1, not 1.5. Presumably that's intentional. If it is not, replace ALL occurences of int with double.
public static int eje4(int a, int b) {
class Node {
final int a, b;
Node(int a, int b) { this.a = a; this.b = b; }
}
Queue<Node> queue = new ArrayDeque<>();
queue.push(new Node(a, b));
int result = 0;
while (!queue.isEmpty()) {
Node n = queue.pop();
if (n.a < 2 && n.b < 2) {
result += (n.a + n.b * n.b);
continue;
}
if (n.a < 2 || n.b < 2) {
result += (n.a * n.a + n.b);
continue;
}
queue.push(new Node(n.a / 2, n.b - 1));
queue.push(new Node(n.a / 3, n.b - 2));
queue.push(new Node(n.a - 2, n.b / 4));
}
return result;
}
*) Some clowns do, like vavr, which is cool, but it's not what the vast majority of java code out there is like. If you love that sort of thing, scala will be more to your liking.

How to find the third largest number out of 4 inputs without using arrays and only using three comparators or comparisons

The code that I have written is as follows :
/*
Program to find the 3rd largest no from 4 nos without using arrays and
only using 3 comparators or comparisons
*/
package d;
public class thirdlargest {
public static void main(String args[]) {
int a=1,b=2,c=3,d=4,soln;
soln= Math.min(Math.max(a,b),Math.max(c,d));
System.out.println("Third largest=" +soln);
}
}
/*
Output:
Third largest=2
*/
But this only works for the used pattern of input if I change the pattern the output will be wrong. How can I fix this code with only using 3 comparators or comparisons strictly and we can use any programming language
IMO it is not possible to find third largest number out of 4 numbers using only three comparisons:
public static void main(String[] args) throws IOException {
int a=1,b=2,c=3,d=4,soln;
int maximum1 = Math.max(a,b);
int maximum2 = Math.max(c,d);
if(maximum1 < maximum2) {
// either c or d and we need more comparisons
}
else {
// either a or b and we need more comparisons
}
}
Edit: Actually we can find the largest number or smallest number using 3 comparisons but probably not the third largest etc.
Also check this answer for finding kth largest number in O(n) time.
This answer on the Math StackExchange site discusses the problem of finding the 2nd largest of N values. It states (with proof) that the lower (tight) bound is N + ceiling(log2N) - 2
For N == 4, that evaluates to 4.
(This applies here because the 3rd largest of 4 is also the 2nd smallest of 4.)
I don't think the proof excludes (hypothetical) solutions with less than 4 comparisons that rely on the N numbers being unique. But that was not part of the problem statement.
Thanks to #invisal for link to algorithm to find the maximum of two numbers without using comparison operator.
I flipped it to return minimum instead, then used as follows to find second lowest value, aka third highest:
private static int thirdHighest(int a, int b, int c, int d) {
int lowest = min(min(a,b),min(c,d));
if (a == lowest)
return min(min(b,c),d);
if (b == lowest)
return min(min(a,c),d);
if (c == lowest)
return min(min(a,b),d);
return min(min(a,b),c);
}
private static int min(int a, int b) {
return b - (((a - b) >> 31) & 0x1) * (b - a);
}
Exactly 3 == comparisons.
Works for input numbers in any order and also works if duplicate numbers are given.
Note: If inputs are constrained to be distinct, then the answer by #ajb can truly do it without any comparisons, by using the min/max bit manipulation of the link provided by #invisal.
I'm not sure what the exact definition of "comparator" is, the way they're using it. But assuming that Math.min and Math.max don't count as comparators, here's a way to compute it using no comparisons or comparators:
public static int thirdLargest(int a, int b, int c, int d) {
int min = Math.min(a, Math.min(b, Math.min(c,d)));
int offset = min + 1 - Integer.MIN_VALUE;
a -= offset;
b -= offset;
c -= offset;
d -= offset;
min = Math.min(a, Math.min(b, Math.min(c,d)));
return min + offset;
}
Computing the third largest number is the same as computing the second smallest number. The trick in this code is that it computes the smallest number, then subtracts from each number the exact offset needed to make the smallest number wrap around and become Integer.MAX_VALUE, while not wrapping around for the other values. The smallest of the remaining numbers is now the second smallest of the original numbers, minus the offset, which we'll add back.
However, I'll concede that this only works if all four numbers are distinct--or, at least, if the lowest two numbers are distinct. It fails if you give it a=1, b=1, c=2, d=3--it outputs 2 instead of 1. At least this should get you points for your problem-solving skill, which is what I assume the question is intended to find out. It had better not be to find out how you would actually solve this in a production situation, because putting restrictions like this on production code (no arrays) would be lunacy.
EDIT:
Here's another solution. There's one comparison in the code, but it's in a method that's executed three times, so that should count as three comparisons.
public static int thirdLargest(int a, int b, int c, int d) {
if (isThirdLargest(a, b, c, d)) {
return a;
}
if (isThirdLargest(b, a, c, d)) {
return b;
}
if (isThirdLargest(c, a, b, d)) {
return c;
}
return d;
}
public static boolean isThirdLargest(int a, int b, int c, int d) {
int z = 3 + ((b - a) >> 31) + ((c - a) >> 31) + ((d - a) >> 31);
// z = number of other parameters that are >= a. Note that all of the
// shift operations will return either 0 or -1.
int y = 3 + ((a - b) >> 31) + ((a - c) >> 31) + ((a - d) >> 31);
// y = number of other parameters that are <= a
int x = -y >>> 31;
// x = 1 if there are any other parameters <= a, 0 if not. Note that
// x can be 0 only if z == 3.
int w = z & (x << 1);
// This will be 2 if a is the third largest. If z == 2, then x == 1
// and w will be 2. If z == 3, and x == 1, that means that a is the
// smallest but is equal to at least one of the other parameters;
// therefore a is also the third largest. But if x == 0, a is
// strictly smaller than all other parameters and is therefore not the
// third largest.
return w == 2;
}
Note: This may suffer from overflow problems, if there are two numbers that differ by 231 or greater. Converting all the parameters to long should avoid the problem (also all the 31's would be changed to 63), but I haven't tested it.
The solution posted by #Andreas is very clean and readable. There is another solution that is less clean and less efficient. The solution relies on catching errors when dividing by zero. We keep on adding 1 to each number and then use the following expression to see if an error occurred:
1 / (currentNumber - Integer.MAX_VALUE)
The second number that threw an error will be the third largest number out of the four. Even though the code has 4 comparison operators =. It will only run two of these statements: One for the first error, and one for the second error. For a total of two comparison statements. This method works for any set of input integers, both positive and negative.
public class thirdlargest
{
public static void main(String args[])
{
System.out.println("Third highest number: " + thirdHighest(1, 2, 3, 4));
System.out.println("Third highest number: " + thirdHighest(4, 3, 2, 1));
System.out.println("Third highest number: " + thirdHighest(-5, -4, -3, -2));
System.out.println("Third highest number: " + thirdHighest(0, 0, 0, 0));
}
private static int thirdHighest(int a, int b, int c, int d)
{
int testa = a, testb = b, testc = c, testd = d;
int divisionResult;
int numberFound = 0;
while(true)
{
try
{
divisionResult = 1 / (testa++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{
return a;
}
}
try
{
divisionResult = 1 / (testb++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{ return b;
}
}
try
{
divisionResult = 1 / (testc++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{
return c;
}
}
try
{
divisionResult = 1 / (testd++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{
return d;
}
}
}
}
}
import java.util.Scanner;
public class TmaxFourNo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter no.'s:");
int w = sc.nextInt();
int x = sc.nextInt();
int y = sc.nextInt();
int z = sc.nextInt();
int m1 = Math.min(Math.max(w, x), Math.max(y, z));
int m2 = Math.max(Math.min(w, x), Math.min(y, z));
if (m1 < m2) {
System.out.println("Tmax=" + m1);
} else {
System.out.println("Tmax=" + m2);
}
sc.close();
}
}

Method to return a fractal sequence (1 12 123 1234 ...) as a string, but last sequence is printing twice. (Java)

The point of this program is to return a "fractal sequence" up until some number, n. That sounds fancy, but all it means is that if, say, n = 4, then it would return: 1 1 2 1 2 3 1 2 3 4. (It just counts up to 1, then 2, then 3, then 4, and returns each step as it gets there.) To make it easier to see: 1 12 123 1234.
The method is called "foo", and the main method must print it. So, the main method calls it by going System.out.print(foo(4)).
The foo method must return a string.
Loops may appear in the foo method, but the point of the exercise is to solve the problem recursively, and so the bulk of the work is supposed to feature a recursion. Or else, this would be a lot easier with some for loops!
public class test{
public static void main(String args[]){
System.out.print(foo(4));
}
public static String foo(int n){
String s = "";
if(n == 1){ //Base step of the recursion
s = 1 + " ";
}
else{
s = foo(n-1) + n + " "; //Recursive step of the recursion
}
System.out.print(s);
return s;
}
}
Right now, what the program will print is 1 1 2 1 2 3 1 2 3 4 1 2 3 4.
The problem is that it is printing out an extra set of 1 2 3 4 at the end. I realize the reason why it's doing that is because System.out.print(s) prints out everything I need, but then the extra System.out.print(foo(4)) in the main method is printing out the extra 1 2 3 4 at the end.
This could easily be solved if in the main method, I just took out System.out.print, and just wrote foo(4);. But, like rule (1) says, the main method must have the print. I'm not allowed to edit anything outside the foo method.
I have tried a bunch of different things (for about 7 hours or so now), but I don't seem to be "getting it". Can someone shed light on where I am going wrong?
Thank you sincerely!
I first thought about an iterative solution to this.
//Iterative Solution
public static String bar(final int n){
final StringBuilder builder = new StringBuilder();
for (int i = 1; i <= n ; i++) {
for (int j = 1; j <= i ; j++) {
builder.append(j);
}
builder.append(" ");
}
return builder.toString();
}
The fact that this relies on 2 nested loops suggests to me that it is not possible to produce a recursive solution using only a single method and no loops. So I've had to include a loop to build up the individual sections within the recursion.
//Recursive Solution (with some iteration too)
public static String foo(final int n) {
if( n == 1 ) {
return 1 + " ";
}
String s = "";
for (int i = 1; i <= n; i++) {
s += i;
}
return foo(n-1) + s + " ";
}
Both of these produce the same output when called with 4, so my main method:
public static void main(final String args[]){
System.out.println(bar(4));
System.out.println(foo(4));
}
Produces this output:
1 12 123 1234
1 12 123 1234
Change the method to:
public static String foo(int n){
String s = "";
if( n <= 0 ) { //Base step of the recursion
s = "";
}
else {
String foo = foo(n-1);
s = foo + foo.substring(foo(n-2).length(), foo.length() -1) + n + " "; //Recursive step of the recursion
}
return s;
}
[Edit]:
Explanation:
What we need here is an accumulator. However, just using foo(n-1) + n will just give us the sequence 12345. So we need to get the last part of the n-1 sequence to get the full 1 12 123 1234 ... I have not tested this code, maybe you need to use foo.substring(foo.length - n, foo.length), but i thought n-1 should be correct. This just retrieves the last sequence ( 123 from 112123 ).
I changed the boundaries because i forgot the space.
With space:
s = foo + foo.substring(foo.length()- n, foo.length() -1) + n + " ";
Without space:
s = foo + foo.substring(foo.length()- (n-1), foo.length()) + n;
[Edit 2]
Didn't work for values n > 10, the new version uses foo(n-2) to figure out the substring. Note that this changes the complexity class for the worse. A better version would either be iterative and use dynamic programming, or use Integer Lists instead of Strings.
This should work:
pulic class test {
public static void main(String args[]) {
System.out.print(foo(4));
}
public static String foo(int n) {
String s = "";
if(n == 0) { //do nothing
}
else {
s = foo(n-1);
System.out.print(s);
s=s+n;
}
return s;
}
}
Right now you are printing the result of the recursion as well as each step. As the result is "1 2 3 4" you get this doubled.
1 for `System.out.print(s);` on step 1
1 2 for `System.out.print(s);` on step 2
1 2 3 for `System.out.print(s);` on step 3
1 2 3 4 for `System.out.print(s);` on step 4
1 2 3 4 for `System.out.print(foo(4));`
so calling foo(4); will get the result you want

Memoization with recursive method in java

I am working on a homework assignment, and I have completely exhausted myself. I'm new to programming, and this is my first programming class.
this is the problem:
Consider the following recursive function in Collatz.java, which is related to a famous unsolved problem in number theory, known as the Collatz problem or the 3n + 1 problem.
public static void collatz(int n) {
StdOut.print(n + " ");
if (n == 1) return;
if (n % 2 == 0) collatz(n / 2);
else collatz(3*n + 1);}
For example, a call to collatz(7) prints the sequence
7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
as a consequence of 17 recursive calls. Write a program that takes a command-line argument N and returns the value of n < N for which the number of recursive calls for collatz(n) is maximized. Hint: use memoization. The unsolved problem is that no one knows whether the function terminates for all positive values of n (mathematical induction is no help because one of the recursive calls is for a larger value of the argument).
I have tried several things: using a for loop, trying to count the number of executions with a variable incremented each time the method executed, and hours of drudgery.
Apparently, I'm supposed to use an array somehow with the memoization. However, I don't understand how I could use an array when an array's length must be specified upon initiation.
Am I doing something completely wrong? Am I misreading the question?
Here is my code so far. It reflects an attempt at trying to create an integer array:
public class Collatz2 {
public static int collatz2(int n)
{
StdOut.print(n + " ");
if (n==1) {return 1;}
else if (n==2) {return 1;}
else if (n%2==0) {return collatz2(n/2);}
else {return collatz2(3*n+1);}
}
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
StdOut.println(collatz2(N));
}
}
EDIT:
I wrote a separate program
public class Count {
public static void main(String[] args) {
int count = 0;
while (!StdIn.isEmpty()) {
int value = StdIn.readInt();
count++;
}
StdOut.println("count is " + count);
}
}
I then used piping: %java Collatz2 6 | java Count
and it worked just fine.
Since you are interested in the maximum sequence size and not necessarily the sequence itself, it is better to have collatz return the size of the sequence.
private static final Map<Integer,Integer> previousResults = new HashMap<>();
private static int collatz(int n) {
int result = 1;
if(previousResults.containsKey(n)) {
return previousResults.get(n);
} else {
if(n==1) result = 1;
else if(n%2==0) result += collatz(n/2);
else result += collatz(3*n + 1);
previousResults.put(n, result);
return result;
}
}
The memoization is implemented by storing sequence sizes for previous values of n in Map previousResults.
You can look for the maximum in the main function:
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
int maxn=0, maxSize=0;
for(int n=N; n>0; n--) {
int size = collatz(n);
if(size>maxSize) {
maxn = n;
maxSize = size;
}
}
System.out.println(maxn + " - " + maxSize);
}
The trick here is to write a recursive method where an argument is the value you want to "memoize". For instance, here is a version of a method which will return the number of steps needed to reach 1 (it supposes that n is greater than or equal to 1, of course):
public int countSteps(final int n)
{
return doCollatz(0, n);
}
public static int doCollatz(final int nrSteps, final int n)
{
if (n == 1)
return nrSteps;
final int next = n % 2 == 0 ? n / 2 : 3 * n + 1;
return doCollatz(nrSteps + 1, next);
}
If you were to record the different steps instead, you'd pass a List<Integer> as an argument and .add() to it as you went through, etc etc.

check if two integers sum to a third

Ok I'm doing this programming assignment and need a little help.
Here is the problem:
Given three ints, a b c, return true if it is possible to add two of the ints to get the third.
twoAsOne(1, 2, 3) → true
twoAsOne(3, 1, 2) → true
twoAsOne(3, 2, 2) → false
Here's the what I have gotten so far:
public boolean twoAsOne(int a, int b, int c) {
return a + b != c;
}
It keeps saying it is not fully correct and I do not know where I am going wrong.
The question asks if it is possible to add any two to get the remaining one. Your code tests only if the first two add to the third.
Thus, twoAsOne(3,1,2) should return true because 3 = 1 + 2; but you are only checking whether 3 + 1 = 2, which is false.
You're only checking one of the possibilities and, on top of that, you're checking it wrongly since you'll return false if a + b == c (because you're using the != operator).
I'm not going to do you homework for you, but the full list of possibilities is:
n1 = n2 + n3
n2 = n1 + n3
n3 = n1 + n2
It should be a simple matter: the result should be true if any of those is true. Otherwise the result should be false.
Or, to provide even a more obvious clue: it should be true if one or more of those conditions are met. Else it should be false.
I don't know how much more obvious I can make it without writing the code for you :-)
Update: And now that more than enough time has probably elapsed to make the homework point moot, here's my solution:
public boolean twoAsOne (int n1, int n2, int n3) {
if (n1 == n2 + n3) return true;
if (n2 == n1 + n3) return true;
if (n3 == n1 + n2) return true;
return false;
}
Although those last two lines could be replaced with:
return (n3 == n1 + n2);
I prefer the (to me, anyway) more readable version.
Besides the answers provided by itowlson and Pax, since you are dealing with ints, there is a possibility that they will overflow, e.g.
Integer.MAX_VALUE + 1 == Integer.MIN_VALUE
Which is not mathematically true
You may want to check this kind of scenarios to make your program complete.
Your code only takes into consideration the sum of int a and int b. The solution requires all possibilities to be covered i.e. "sum of int a and int c" and "sum of int b and int c". Refer to the code mentioned below, hope it helps!
public boolean twoAsOne(int a, int b, int c) {
return ((a + b == c) || (b + c == a) || (c + a == b));
}
Dude I hope you got the answer by now... if you haven't
public boolean twoAsOne(int a, int b, int c) {
return ((a+b==c) || (a+c==b) || (b+c==a));
}
I might be very late yet I have minimized it. twoAsOne
public boolean twoAsOne(integer a, integer b, integer c){
return ((a+b) == c ? true : (a+c) == b ? true : (b+c == a)? true : false);
}
package get_third;
public class Get_third {
int a , b ,c ;
boolean third_value(int a , int b , int c){
if(a+b==c||b+c==a||c+a==b)
{
return true;
}
else
return false ;
}
public static void main(String[] args) {
Get_third obj =new Get_third();
System.out.println(obj.third_value(1, 2, 3));
System.out.println(obj.third_value(3, 1, 2));
System.out.println(obj.third_value(3, 2, 2));
}
}
// start
public boolean twoAsOne(int a, int b, int c) {
if (a + b == c) {
return true;
}
else if (a + c == b) {
return true;
}
else if (b + c == a) {
return true;
}
else {
return false;
}
}
// end

Categories

Resources