Recursion with if statements Java - java

Got two int a and b, need to find the sum of all the numbers between including them too.
Got Recursion Method:
with two if statements, if use only one if statement code work fine,
otherwise fall with StackOverflowError.
public static int getSum(int a, int b) {
int result = 0;
if (a <= 0 && b <= 0) result = getSum(a + 1, b + 1) + a + b;
if (a >= 0 && b >= 0) result = getSum(a - 1, b - 1) + a + b;
return result;
}
How can I fix it?

Lets assume a is 1, and b is 2.
if (a <= 0 && b <= 0) result = getSum(a + 1, b + 1) + a + b;
if (a >= 0 && b >= 0) result = getSum(a - 1, b - 1) + a + b;
The 2nd kicks in:
result = getSum(1 - 1, 2 - 1) + a + b;
So you call: with a = 0, b = 2. That one picks:
result = getSum(0 + 1, 1 + 1) + a + b;
So you are back to call with 1, 2.
And it starts from scratch. Leading into an endless recursion.
So, there are multiple problems with your current approach:
both if conditions might apply. As you use "<=" and ">=", when a or b are 0, both if conditions kick in
worse: as shown, your setup allows to easily go down-up-down-up-... forever
beyond that: a correct "stop recursion" is missing. For certain input, your code will simply always go and call itself, again.
guessing here: you are also missing corner cases, such as a < 0, but b > 0
So, long story short: your whole algorithm is bogus, and you need to step back and rethink what you are doing here!

This doesn't need recursion, but I assume you are trying to learn recursion.
Please see comments for explanation.
public static int getSum( int a, int b ) {
if ( a == b ) { // if both are equal there are no numbers in between - so sum is number itself.
return a;
}
// if a < b then increment a to reach b otherwise increment b to reach a.
// this works even if a or b or both are negative.
// So when you increment a, add 'a' only to current sum and then move forward
// When you increment b, add 'b' only to current sum and then move forward.
return a < b ? a + getSum( a + 1, b ) : b + getSum( a, b + 1 );
}

You don't need those if statements. Just do it as follows:
public static int getSum(int a, int b){
if (b < a) return 0;
if (b == a) return b;
return a + getSum(a + 1, b);
}

Related

How to make a recursive method?

I am trying to make this recursive method.
public int addWithFactors(int[] a, int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum = sum + (i + 1) * a[i];
}
return sum;
}
I have tried to make an if statement instead of a for loop:
if (n == 0) {...}
but I don't know what is the recursive equivalent
You can consider this code as its recursive equivalent. In your original code, you set a as a given array, and n as the maximum term, which is at most a.length - 1, and i as the current term. Your program is effectively a summation program.
The recursive helper version is shown below, and it also handles exceptional situations such as i being out of bounds:
public int addWithFactorsRecursive(int[] a, int i, int n) {
if (i < 0) // Exceptional case where
return -1;
else if (i == n - 1) // End recursion here
return (i + 1) * a[i];
else if (i < n - 1) // Return the term, and consider further terms
return (i + 1) * a[i] + addWithFactorsRecursive(a, i + 1, n);
return 0;
}
The outputs I will show to you will take an array input a, and loop addWithFactors(a, 0) to addWithFactors(a,a.length).
Here is one input I used, {1,4,9,16} and the output I got, the one on the left being your current iterative version, and the one on the right being the recursive version:
0 1 // n == 0
1 1 // n == 1
9 9 // n == 2
36 36 // n == 3
Similarly for {2,4,8,16,32,64}, I got
0 2
2 2
10 10
34 34
98 98
258 258
you can define your function like this:
public int addWithFactors(int[] a, int n) {
if (n == 1)
return a[n - 1];
return (n) * a[n - 1] + addWithFactors(a, n - 1);
}
You shuld call it like below:
addWithFactors(new int[] {1, 1, 2} ,3)
And it return 9.
private int addWithFactorsInternal(int[] a, int n, int i) {
if (i == n) {
return 0; //base case
}
return addWithFactors(a, n, i + 1) + (i + 1) * a[i];
}
addWithFactors(a, n, i + 1) makes recursive calls incrementing i. The base case is when i reaches n where you return 0.
For others, you add (i + 1) * a[i] to the recursive call and return.
If your top-level method is of the signature you've mentioned, you can call the above as
public int addWithFactors(int[] a, int n) {
return addWithFactorsInternal(a, n, 0);
}
NOTE: I didn't assume n is equal to a.length
Example:
a = {1,4 5} n = 3 (Read the LHS from top to bottom and RHS from bottom to top)
[Returns 24]
addWithFactorsInternal(a, 3, 0) - 23 + (0 + 1) * 1 = 24
addWithFactorsInternal(a, 3, 1) - 15 + (1 + 1) * 4 = 23
addWithFactorsInternal(a, 3, 2) - 0 + (2 + 1) * 5 = 15
addWithFactorsInternal(a, 3, 3) - returns 0 (base case)

What is really happening here? This is a code for swapping two variables

a = b-(a-(b = a)); //swapping a and b
also, if a=20,b=10 why does
System.out.println(b = a);
give 20 as result?
a = b-(a-(b = a)); //swapping a and b
It's a way of swapping numeric types without the need of a support variable.
They usually ask you this in interviews.
It is particularly unreadable as it's written in one line, but consider this step by step:
int a = 5;
int b = 2;
a = b - a; // <- -3
b = b - a; // <- 2 - ( - 3) <- 5
a = a + b; // <- (- 3) + 5 = 2
You still can't swap non-numeric types without a temporary variable.
With
System.out.println(b = a);
I guess you wanted to check if b equals a, in which case you should have written System.out.println(b == a), which evaluates to a boolean result.
With b = a, you are assigning a's value to b and then print its result.

Counting values above the average for returning to another method

public class main {
public static void main(String[] args) {
aboveAverageTester();
}
public static int aboveAverage(int a, int b, int c, int d, int e, int f) {
//This method computes the average of the parameters
//and then returns how many of the parameters are above the average.
int avg = (a + b + c + d + e + f) / 6;
int above = 0;
if (a > avg) {
return a;
}else if (b > avg) {
return b;
}else if (c > avg) {
return c;
}else if (d > avg) {
return d;
}else if (e > avg) {
return e;
}else if (f > avg) {
return f;
}else{
return a + b + c + e + f;
}
}
public static int aboveAverageTester() {
int aboveAverage = aboveAverage(10, 10, 10, 10, 45, 50);
System.out.println(aboveAverage);
return aboveAverage;
}
}
I know the aboveAverage method logic may be completely off, but I'm getting a problem when I'm trying to return how many of the parameters are above the average.
From my code, I believe that when you keep returning like a, b ,c.. etc after each if-- it's just 1 instance and not adding to the list of others that my be larger than the average.
I'm trying to preform this without printing anything in this method, only logic.
I know I kind of messed up, also, at the bottom of the aboveAvg method by adding all the a,b,c,d,e,f and not just creating a list from them.
Can anyone give me an idea of how to approach this?
Your method is returning one of the values, not the count. It also truncates the average when the sum a + b + c + d + e + f is not divisible by six.
You can fix this by using double for the average, dividing by 6.0 to force double result type, and then counting the number of above average numbers with conditional operator:
double avg = (a + b + c + d + e + f) / 6.0;
return (a > avg ? 1 : 0)
+ (b > avg ? 1 : 0)
+ (c > avg ? 1 : 0)
+ (d > avg ? 1 : 0)
+ (e > avg ? 1 : 0)
+ (f > avg ? 1 : 0);
To count the number of elements above the average, you can loop on each one and increment a counter as the condition is true :
int aboveAverage = 0;
List<Integer> numbers = Arrays.asList(a,b,c,d,e,f);
for (int number : numbers){
if (number > avg){
aboveAverage++;
}
}
return aboveAverage;
With Java 8, you could write it in a less verbose way :
long aboveAverage = Arrays.asList(a,b,c,d,e,f).stream()
.filter(n-> n > avg)
.count();
Not sure if I got your question completely, but I guess you want to count how many values are above the average.
So instead of returning the value when the if statement holds true, you should increment the counter like this:
if (a > avg) {
above++;
}

Why is my program giving an incorrect output in certain cases?

I have made an implementation of the Euclidean Algorithm in Java to find the Greatest Common Divisor (GCD) of two given numbers.
For the most part, my program works fine, I have tested it with a few random sets of numbers, although, I have found in one case (that I know of) that it's giving an incorrect output, which is for the following combination of numbers:
Enter integer a: 8965
Enter integer b: 55
The output of the program should be 55, although this is not the case. The out given is as follows:
gcd = 1
Execution time: 0.005747ms.
I'm not sure why this particular combination of numbers is causing a problem, as it works fine for other numbers, for example, here is the results for a different set of numbers:
Enter integer a: 15000
Enter integer b: 5325
gcd = 75
Execution time: 0.007389ms.
import java.util.Scanner;
public class EuclideanAlgorithm {
public static void main (String [] args) {
int a, b;
try(Scanner sc = new Scanner(System.in);) {
System.out.print("Enter integer a: ");
a = sc.nextInt();
System.out.print("Enter integer b: ");
b = sc.nextInt();
}
long start = System.nanoTime();
int answer = EuclideanAlgorithm(a, b);
long stop = System.nanoTime();
System.out.println("gcd = " + answer);
System.out.println("Execution time: " + ((stop - start) / 1e+6) + "ms.");
}
public EuclideanAlgorithm() {}; //Suppress default constructor
private static int EuclideanAlgorithm(int a, int b) {
if ( (a == 0) || (b == 0)) {
return 0;
}
if (b > a) {
int temp = a;
a = b;
b = temp;
}
int gcd = 1;
while(gcd != 0) {
if( (a % b) == 0) {
break;
}
gcd = a % b;
a = b;
b = gcd;
}
return gcd;
}
}
Whenever one of your numbers a, b is a multiple of the other, then your if condition will cause a break and 1 will be returned, which is incorrect. But the rest of the algorithm is incorrect also.
According to the pseudocode for the Euclidean Algorithm:
function gcd(a, b)
while b ≠ 0
t := b
b := a mod b
a := t
return a
You need to check if b is not 0, not the gcd. You'll need to modify your code to match this algorithm; your code is not currently matching this algorithm.
Because of the if condition inside this while loop
int gcd = 1;
while(gcd != 0) {
if( (a % b) == 0) {
break;
}
gcd = a % b;
a = b;
b = gcd;
}
So, in case a % b = 0 at the beginning -> result is always equaled to 1.
You need to handle that case separately.
int gcd = b;
while(a % b != 0){
gcd = a % b;
a = b;
b = gcd;
}
It's easy 55 divides 8965 that means you programm breaks in the first line and returns your initial value which is 1.
Instead something like this could help.
int gcd = 1;
if( (a % b) == 0) {
return b;
}
while(gcd != 0) {
if( (a % b) == 0) {
break;
}
gcd = a % b;
a = b;
b = gcd;
}

fault or error in this method

I am revising for a software testing exam. One of the questions gives this method and asks to identify the fault as well as produce a test case (if one exists) which does not execute the fault.
Here is the code:
public static int oddOrPos(int[] x) {
//Effects: if x==null throw NullPointerException
// else return the number of elements in x that
// are either odd or positive (or both)
int count = 0;
for (int i = 1; i < x.length; i++)
{
if (x[i]%2 == 0 || x[i] > 0)
{
count++;
}
}
return count;
}
I have identified two problems. One being that i is initialised to 1 in the for loop so x[0] doesn't get tested. Also x[i] % 2 == 0 should be x[i] != 0
Are these problems faults or errors? I ask this because the question makes it appear that there is only one fault.
Also, I assume that because the for loop will always be executed, there is no test case which will not execute the fault.
Actually x[i] % 2 == 0 should be x[i] % 2 != 0 (if we want to detect odd values along with the positive ones. The existing code will detect even values instead).
The test case is just { -2 } - this element is even and negative, so should not get counted, and the method will return 0 even though it is faulty. { 1 } will also give 0, which is wrong.
If you want to detect odd negative values you'll have to look for -1 and not for 0 as it's done right now.
For odd positive values it will be 1. So basically you want anything but 0.
The % operator is a remainder operator, not really a modulo operator, it returns a negative number if the first given number is negative:
class Test1 {
public static void main(String[] args) {
int a = 5 % 3; // 2
int b = 5 / 3; // 1
System.out.println("5%3 produces " + a +
" (note that 5/3 produces " + b + ")");
int c = 5 % (-3); // 2
int d = 5 / (-3); // -1
System.out.println("5%(-3) produces " + c +
" (note that 5/(-3) produces " + d + ")");
int e = (-5) % 3; // -2
int f = (-5) / 3; // -1
System.out.println("(-5)%3 produces " + e +
" (note that (-5)/3 produces " + f + ")");
int g = (-5) % (-3); // -2
int h = (-5) / (-3); // 1
System.out.println("(-5)%(-3) produces " + g +
" (note that (-5)/(-3) produces " + h + ")");
}
}
Another "small" fault is the way the condition is done. Instead of checking for odd or positive, looking for positive or odd will be slightly faster. It's only because it's easier to check if a number is positive or not than getting its remainder.
Resources:
15.17.3. Remainder Operator %
The major thing here is that your for loop is starting at 1, and it should start at 0. You will always miss the first element of the array. Also x[i]%2 == 0 returns true for even numbers, not odd. So change that to x[i]%2 != 0.
public class test{
public static void main(String[] args){
int[] x = {3, 5, -1, -14}
if( 3 == oddOrPos(x)){
System.out.println("Working");
else
System.out.println("Test Fail");
}
public static int oddOrPos(int[] x) {
//Effects: if x==null throw NullPointerException
// else return the number of elements in x that
// are either odd or positive (or both)
int count = 0;
for (int i = 0; i < x.length; i++)
{
if (x[i]%2 != 0 || x[i] > 0)
{
count++;
}
}
return count;
}
}
As I understand it, you are right in your assumption. The first position of the array should be tested, hence the i[0] you pointed out.
However, x[i]%2 == 0 should instead be x[i]%2 == 1 for an odd number.

Categories

Resources