Having trouble with recursive method in java - java

The compiler says I'm not returning an integer. The getC method returns an integer. How can I fix this?
public static int calcCost(Guard[] g, int spot){
if(spot >= 31078657) return 0;
else {
for(int i = 51499; i >= 0; i--){
if(g[i].getS() == spot && g[i].getF() <= 31078657) {
return (g[i].getC() + calcCost(g, g[i].getF() + 1));
}
}
}
}

This problem arises when your method doesn't return a result by following all the paths. In this case, if the if inside the for loop never gets executed, you aren't returning anything.
Just add a default return statement at the bottom of your method:
public static int calcCost(Guard[] g, int spot){
if(spot >= 31078657) return 0;
else {
for(int i = 51499; i >= 0; i--){
if(g[i].getS() == spot && g[i].getF() <= 31078657) {
return (g[i].getC() + calcCost(g, g[i].getF() + 1));
}
}
}
//here
return 0; //or another desired default value
}

You're not returning an integer in every case. If the inner condition is never met, control will flow to the end of the method without anything being returned.

You need to add a 'return' for the case when your 'for' loop terminates - i.e. with i==0. Not knowing what this code is doing, it's entirely possible that you are certain the the inner return must occur for some value of i, but neither I nor your compiler can determine that this is the case, merely by looking at this code fragment. Modern compilers are pretty smart, but not that smart ;-)

Simply add default value in the end
public static int calcCost(Guard[] g, int spot){
if(spot >= 31078657) return 0;
else {
for(int i = 51499; i >= 0; i--){
if(g[i].getS() == spot && g[i].getF() <= 31078657) {
return (g[i].getC() + calcCost(g, g[i].getF() + 1));
}
}
}
return -1;// add default value here
}
OR you can throw an Exception such as IllegalArgumentException in case of invalid value.
public static int calcCost(Guard[] g, int spot){
if(spot >= 31078657) return 0;
else {
for(int i = 51499; i >= 0; i--){
if(g[i].getS() == spot && g[i].getF() <= 31078657) {
return (g[i].getC() + calcCost(g, g[i].getF() + 1));
}
}
}
throw new IllegalArgumentException();
}

Related

Why does the code not work in this instance?

I am struggling to understand why code wouldn't work. According to the truth table/logic gates for AND and OR https://en.wikipedia.org/wiki/Truth_table I would assume that I would be able to have an if statement inside the for-loop such that (p < 2 || p % i == 0) would work for finding prime numbers but it fails when considering negative numbers.
I know that if you if take out the p < 2 and write it as an if statement outside this for-loop it works, but if the p < 2 is inside the for-loop it does not work. Why is this so?
public class test {
public static void main(String [] args) {
System.out.println("Hello World!");
int a = 7;
System.out.println("A is Prime: " + isPrime(a));
System.out.println();
int b = 4;
System.out.println("B is Prime: " + isPrime(b));
System.out.println();
int c = -7;
System.out.println("C is Prime: " + isPrime(c));
System.out.println();
int d = 53;
System.out.println("D is Prime: " + isPrime(d));
}
public static boolean isPrime(int p) {
for (int i = 2; i < p; i++) {
if (p < 2 || p % i == 0) {
return false;
}
}
return true;
}
}
Because for p < 2, the body of the for loop is never performed. Indeed:
for (int i = 2; i < p; i++) {
// ...
}
If p = 2, then it initializes i = 2, and then checks i < p which fails, and hence the body is never executed. It skips the for loop, and thus returns true.
We can fix it by performing a check before (or after) the for loop, and even boost the performance of the loop slighly:
public static boolean isPrime(int p) {
if(p <= 2) {
return p == 2;
}
if(p % 2 == 0) {
return false;
}
for (int i = 3; i*i <= p; i += 2) {
if (p % i == 0) {
return false;
}
}
return true;
}
We can simply return false first for all values less than 2, and true for 2. Furthermore we only need to iterate up to √p, since if there is a value j larger than √p that divides p, then there is a smaller value i = p/j that is smaller than √p that will already be checked. We furthermore only need to check odd numbers, since even numbers are already implied by the division by 2.
You may want to invest in Math.abs(int):
public static boolean isPrime(int p) {
p = Math.abs(p);
for (int i = 2; i < p; i++) {
...
This will ensure that p is always non-negative, and your initial assumptions about how the loop should behave are justified.

How to return value when there's no input in array method?

So, I have to write a program that counts the most repeated number in an array (e.g. 1, 2, 2, 3, 3, 3) and then tells the user what number is it (3). Finally, an online compiler tests my code and sees if my output is correct.
Here are the inputs from the program.
My issue is the last input, which is nothing. I tried to return a value but I couldn't.
Here's my code excluding the main method (Java):
Edit: Thank you everyone. I'm an idiot.
public int lengthOfLongestRun(int[] values) {
if (values == null){
return 0;
}
int lastVal = values[0];
int currentLength = 1;
int longestLength = 1;
for (int i = 1; i < values.length; i++) {
if (values[i] == lastVal)
currentLength++;
else
currentLength = 1;
lastVal = values[i];
if (currentLength > longestLength)
longestLength = currentLength;
}
return longestLength;
}
Since the array is empty you need to check the length and return zero if the length of the array is zero.
Right now you have added a condition already for null check. Just extend that and add another condition for empty array aswell.
public int lengthOfLongestRun(int[] values)
{
if(values == null || values.length == 0){ // code added here
return 0;
}
int...
...
That should solve your problem.
I can see another potential bug here. Your loop starting at position 1
for (int i = 1; i < values.length; i++)
{
What if the biggest number lies at position 1 ? You are not seeing the bug because all your input arrays starting with value 1.
You should check array size
if(values == null || array.length == 0){
return 0;
}
if(values == null || values.length == 0){
return 0;
}
If the input array is [], its length is zero. So just check for that:
if (values.length == 0) {
return 0;
}
Note that it's maybe better not to return 0 in the null case: it's an invalid input, so don't give a valid output. Throw a NullPointerException or IllegalArgumentException, for instance.
You can also write the loop so as not to need to handle the zero case separately:
int longestLength = 0;
int i = 0;
while (i < values.length) {
int start = i++;
while (i < values.length && values[i] == values[start]) {
++i;
}
longestLength = Math.max(longestLength, i - start);
}
return longestLength;

Getting every combination of Queens?

public class SomeQueens {
static Stack<Integer> s= new Stack<Integer>();
static int Solved = 0;
static int current = 0;
public static int solve(int n) { // n is 8
while(current < n) { // should I use current < n instead
for (int i = current; i < n; i++) {
if(validPosition(i)) {
s.push(i);
current = 0;
}
}
if(!validPosition(current)) {
if(s.empty()) {
break;
}
if(!s.empty()) {
s.pop();
current++;
}
}
if(s.size() == n) {
s.pop();
current++;
printSolution(s);// this is a method, but it shouldn't matter for this
Solved++;
}
}
return Solved;
}
public static boolean validPosition(int column) {
for( int row = 0; row < s.size(); row++)
if(s.get(row) == column || ((column - s.get(row)) == (s.size() - row)) ||
((s.get(row) - column) == (s.size() - row)) )
return false; // there's a conflict
return true; // no conflict;
}
//it's called by int num = solve(n);
//sop("There're" + num + "sols to the" + n "queens prob");
This is a subsection of my program for NQueens, but I seem to always get: There are 0 solutions to the 8-queens problem. I tried debugging with system.out.prints in the main method, which led me to guess that there would be something wrong in my boolean method, but I don't think it's doing anything wrong.
I'm unsure if my while statement is incorrect or if the break inside the while loop is initialized before anything is even done. Thanks for the help and guidance and I'm sorry if my program and explanation makes no sense
Here is why you instantly get a zero:
s.push(0);
while(s.size() > n) // n is 8
{
//...
}
return Solved;
When the program arrives at the while-condition s has a size of one and n is 8. This will instantly fail and cause the method to return a zero.
But that's not the only problem with the algorithm. You should seriously rethink it.

Java logic issues

I'm working on a method that finds the first instance of a given value and returns its position. It works for some cases, but if I give it an array of [1,2,3], and set the value to 2, it returns 0, instead of 1. I'm not sure why, either. Here is the code:
int b = 0;
for(int a = 0; a < values.length; a++) {
if (values[a] == find){
b++;
}
}
return b-1;
Thanks in advance!
Its because you are returning b-1. In fact, if you need to find the same instance and return the index, you wont even need the variable b. You could achieve this with something like this:
for( int a = 0; a < values.length; a++) {
if (values[a] == find){
return a;
}
}
return -1 // Notfound
}
Add the return -1 line for when a value is not found, to use as a sentinel value.
Try
for( int a = 0; a<values.length; a++) {
if (values[a] == find){
return a;
}
}
Why not return a itself instead of doing b-1;
Maybe you can add a break statement too to stop iterating as you just need the position of first instance
int b=0,result;
for( int a = 0; a<values.length; a++)
{
if (values[a] == find)
{
result=a;
break;
}
}
return result;

Sort ArrayList Objects properties with custom start point

My question is about how to sort an ArrayList with custom Object by one of them properties but starting from a custom condition.
Let me explain better, here is my code:
public static void sortArrayListByProperty(ArrayList colorList){
Collections.sort(colorList, new Comparator(){
public int compare(Object emp1, Object emp2){
int intValue1 = ((ColorCounter)emp1).getIntColorValue();
int intValue2 = ((ColorCounter)emp2).getIntColorValue();
if(intValue1 < intValue2)
return 1;
else if(intValue1 > intValue2)
return -1;
else
return 0;
}
});
}
This will sort my ArrayList from bigger to smaller.
But what I want is to sort my ArrayList from a starting number that I will specify.
For example if ArrayList contains
5 3 9 1 14
lets say that I want numbers start from 3 then I need to have
3 5 9 14 1
I hope is clear enought...
Is it possible?
#Joachim Sauer
Thank you, I edited your code a little and changed return values and it worked!
Edited code:
if (cv1 >= threshold && cv2 < threshold) {
return -1;
} else if (cv2 >= threshold && cv2 < threshold) {
return -1;
} else if (cv1 < cv2) {
return 1;
} else if (cv1 > cv2) {
return 1;
} else {
return 0;
}
Test example:
16777215
16448250
15790320
4013373
Sorting by 15790320:
15790320
16448250
16777215
4013373
You could try this:
public class ColorCounterComparator implements Comparator<ColorCounter> {
private final threshold;
public ColorCounterComparator(final int threshold) {
this.threshold = threshold;
}
#Override
public int compare (ColorCounter c1, ColorCounter c2) {
int cv1 = c1.getIntColorValue();
int cv2 = c1.getIntColorValue();
if (cv1 >= threshold && cv2 < threshold) {
return -1;
} else if (cv2 >= threshold && cv2 < threshold) {
return 1;
} else if (cv1 < cv2) {
return -1;
} else if (cv1 > cv2) {
return 1;
} else {
return 0;
}
}
}
This is obviously very untested, might have some off-by-one-errors and might have flipped the -1/1 values. But it should show you the basic idea ;-)
using ArrayList sublist method to create a sub-list, and then sort this sub-list.
Not tested, but you get the idea: you have 2 situations
both numbers are below the start number (3 in your example) or both are above ==> compare them
one number is below the start number, the other above ==> the first one is after the second one in your custom sort order:
if (intValue1 < start && intValue2 < start || intValue1 >= start && intValue2 >= start) {
if(intValue1 < intValue2)
return 1;
else if(intValue1 > intValue2)
return -1;
else
return 0;
} else {
if (intValue1 < start)
return -1;
else
return 1;
}

Categories

Resources