Recursive Statement not Instantly Returning - java

I am creating a method that takes a list of numbers and an index.
If there is a number after the index that is six times the first number, it returns true. Otherwise, it returns false.
public static boolean firstElementMultiple(int []Numbers, int index) {
System.out.println(Numbers[index]);
if ((Numbers[0]*6)==Numbers[index]){
System.out.println("Yep");
return true;
}
if (index+1 >= Numbers.length){
return false;
}
firstElementMultiple(Numbers, index+1);
return false;
With a list of {5,6,7,30} and an index of 1, false is returned, even though 30 is in the list.
6
7
30
Yep
Is printed, which shows me that it did recognise that 30 was in the list. However, it is still returning false even though the next statement is true and should stop the method?
This has to be done by recursion.
edit: I have to put the 'return false;' at the end as, without it, it doesn't let me. However, I don't see how it can ever get there because there is always a recursive call in the way.

firstElementMultiple(Numbers, index+1);
return false;
Here's the end of your method. This is what it does. It says "Call firstElementMultiple to keep looking for the value we're looking for. Once you've finished looking, completely ignore whether or not you found it and return false anyway."
Given that, how can you fix it to do what you want it to do, namely return whether or not we found the element?

Because in the end, you are returning false in your recursive function no matter what you get in further calculations. You should change your code to this:
public static boolean firstElementMultiple(int []Numbers, int index) {
System.out.println(Numbers[index]);
if ((Numbers[0]*6)==Numbers[index]){
System.out.println("Yep");
return true;
}
if (index+1 >= Numbers.length){
return false;
}
return firstElementMultiple(Numbers, index+1);
}
Basically you need to change
firstElementMultiple(Numbers, index+1);
return false;
to
return firstElementMultiple(Numbers, index+1);

Related

Do i also need to return string outside if-else condition ,when the return type is String

The compiler keeps telling to return string.I used if-else condition and from within if-else i have returned string.The compiler problem will be solved if i put return statement at the end of the code but my problem will start .I dont understand how to solve this problem.I want to return right when its right.
Code:
public String isValidID(String id) {
if(getId().length()!=6) {//checks for 6 digit id
return "wrong";
}
else{//checks if digit contains invalid entry
for(int i=0;i<getId().length();i++){
if(Id.charAt(i)>'9'||Id.charAt(i)<'0')
return "wrong";
}
}
}
In reply to my comment to add return "right" at the end, you said:
but that will make the program return "right " always.Becoz after if-else condition check ,the compiler will execute rest statement and will return "right" always
Now the source of your confusion is clear: return doesn't just set the value the method will return, it also exits the method, immediately. So for instance, the return "wrong"; inside your loop will exit from the loop, and the method, immediately. This is true of all the languages I've seen that use the return keyword (whereas there are some languages, like VB/VB.Net, where you assign a value to the function's name to set the return value, but execution continues normally until you use "exit").
That's why adding return "right"; at the end is how you resolve this, because the code won't reach that point if it ever reached return "wrong"; during the program flow above it:
public String isValidID(String id) {
if(getId().length()!=6) {//checks for 6 digit id
return "wrong"; // <== Exits immediately if reached
}
else{//checks if digit contains invalid entry
for(int i=0;i<getId().length();i++){
if(Id.charAt(i)>'9'||Id.charAt(i)<'0')
return "wrong"; // <== Exits immediately if reached
}
}
return "right"; // <== Exits immediately if reached
// (granted, we would have exited
// below anyway :-) )
}
In any condition, you need to return "something". In your code it possible that return never executed in a certain condition. Suppose your program execution comes to if(Id.charAt(i)>'9'||Id.charAt(i)<'0') and it never gets true then what the method will return? So, You need to write the code in a manner that in condition method execution will execute a return statement which returns a String object.
Just imagine a conditon Suppose
1. getId().length()!=6 -> false
2. getId().length() is 0
3. for(int i=0;i<getId().length();i++) will never enter the loop.
Then what should the method returns when you call it.
If I can understand your logic you can just use :
public String isValidID(String id) {
return id.matches("\\d{6}") ? "correct" : "wrong";
}
You check the length if it is 6 or not then you check if all characters are digits, you can combine both of them in one instruction, just check if the input is a number with length 6 with regex.
If you want a clean solution use boolean instead of a String in this case you can use :
public boolean isValidID(String id) {
return id.matches("\\d{6}");
}
Inside your else you have another if statement, so your return its not always reached. You need another return after the for cycle.
And you are checking if something is wright or wrong you should return Boolean true or false.
public boolean isValidID(String id) { if(getId().length()!=6) {//checks for 6 digit id return false; }
else{//checks if digit contains invalid entry for(int i=0;i'9'||Id.charAt(i)<'0') return false; }
return true;// when nothing false was found.
}
}
So in your case, I would have done public boolean isValidID instead.
Here, the compiler tells you to return something in case the length of the ID is not correct and the components of the ID (so the caracters) are between 0 and 9 (for example if your ID is something like 00ggg89, then I suppose it is wrong, but if your ID is 000000, then it could be right. Here is what I would have done
public boolean isValidID(String id) {
return id.matches("[0-9]{6}");
}
Hope this helps ! :D
public String isValidID(String id) {
String result = "right";
if(getId().length()!=6) {//checks for 6 digit id
result = "wrong";
}
else{//checks if digit contains invalid entry
for(int i=0;i<getId().length();i++){
if(Id.charAt(i)>'9'||Id.charAt(i)<'0')
result = "wrong";
}
}
return result;
}
Edit: In case the first statement is not valid it will never get to a return statement. Thats why you have to return a String in every possible case.

Implementing an equals method recursively

Basically, I need to compare two arrays and check if they have the same values in the same positions (recursively of course). I get an error with my current code: Array out of index exception:20
The code I have right now looks as follows:
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd){
if (first[iStart] == second[iStart]){
if (equalsHelper(first,second,(iStart+1),iEnd))
{
return true;
}
}
if (iStart == iEnd){
return first[iEnd] == second[iEnd];
}
return false;
}
You simply need to put you stop condition at the begin of you code. This will work if iStart is 0 at the beginning and iEnd is array length - 1.
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) { // you need to check this first
return first[iEnd] == second[iEnd];
}
if (first[iStart] == second[iStart]) {
if (equalsHelper(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
If you want to use the array length as input for iEnd you just need to change the code a little
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) {
return true;
}
if (first[iStart] == second[iStart]) {
if (equalsHelper2(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
Since performance was mentioned a few times I will say a few things about it.
The stack contains information about local variables and function calls. So each recursiv call will save these informations on the stack which will lead to a stackoverflow on huge inputs since the stack only has limited space. It is also slower in terms of execution due to more assembler commands in comparison to loops.
This can be avoided by using tail recursive functions.
A tail recursive call means simply that your recursive call must be the last statement that is executed in your method. The compiler will translate this into a loop. This is faster and uses less space on the stack.
A tail recursive version of your equals method would look like this:
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd)
{
if (iStart == iEnd)
{
return true;
}else{
if(first[iStart] != second[iStart])
{
return false;
} else
{
return equalsHelper2(first, second, iStart + 1, iEnd);
}
}
}
Leaving aside the question of whether recursion is the right solution (it really isn't, iteration here is trivial and will perform better), the problem is that the termination condition (iStart == iEnd) is not checked until after the recursive call.
Any recursive algorithm must a) check whether it is appropriate to continue recursing, and b) do the recursive call after that check. Failing to include the first step, or doing the steps out of order, will result in infinite recursion until an error is reached (StackOverflowError if nothing else happens first).
You do have a condition check before your recursive call, but it's for the method's overall purpose rather than for ending recursion. You also have a condition check for ending recursion, but it's done after the recursive call. The solution is to swap their order - take the if (iStart == iEnd) block and move it to before the if (first[iStart] == second[iStart]) block.
Recursion is a powerful programming technique, but has some draw backs in the Java language. If a method in java calls itself recursively an excessive number of times before returning it will lead to a StackOverflowError. It this instance, comparing equality of two Array's is almost guaranteed to do so.
Other languages like Scala allow you to write recursive functions which are optimised for recursion (tail recursive) and execute in constant stack space.
That been said, you should think whether recursion is really the correct solution here. It neither optimises the solution, nor adds code clarity.
Note: If you just want to compare two Array's in Java, then java.util.Arrays already has you covered.

why does my java program not iterate?

This is supposed to check if an int occurs at a specific index in an array or at any other index over that. However, my for loop doesn't loop
public static boolean searchIterative(int[] list, int f, int x){
for (; f<list.length;f++){
return list[f]==x;
}
return false;
}
You return immediately after entering your loop. return exits the loop (and the function.
Regardless of whether or not the value is true, the first time you enter the loop you return a true or false - you return the conditional statement list[f]==x;
You want to iterate through until you find it, and then return true, or return false if you never find it. If you need to find if it's in multiple places you need to count each time you find it within the method, and then return that.

Comparing one ArrayList to another ArrayList using boolean method in java

I am trying to get a boolean method to return true or false on wether two arrayLists are equal to each other. The arraysLists are array and array1. The user inputs them. Right now here is the code that I thought would work:
public boolean equals(){
//if both are equal return true, else false
boolean test = false;
for(int i = 0; i < array1.size() && !test; i++){
if(array1.get(i) == (array.get(i))){
test = true;
}
}
return test;
}
except even when all the arrayLists numbers match the other arrayLists numbers, it returns false.
You don't need to overwrite the equals method, as there is one already provided for lists that does exactly what you need.
If you insist of writing it yourself there is a simple error in your code.
Because you initialize test to be false, "&& !test" lets your loop exist right at the start.
The correct version would be:
public boolean equals(){
if(array.size()!=array1.size) return false; // test for different length
for(int i = 0; i < array1.size(); i++){
if(!array1.get(i).equals(array.get(i))){
return false;
}
}
return true;
}
double equals (==) is dangerous. You are actually returning objects in your code up there, so you should definitely use equals() instead
Think that you are only iterating one array. Think what can go wrong there. Also take a look at your control statement.
If you carefully follow the flux of your code you quickly will realize why is false.
You should just 'reverse' your method. Assume the arrays are equal first. It should then check on each iteration if the element differs. If the element differs, then set a "not equal" flag. In pseudo-codee
boolean different = false;
for (each element of array 1) {
if (element != element of array 2) different = true
break;
}
You'll need to change your code to this:
public boolean equals(){
if (array1.size() != array.size()) return false;
for(int i = 0; i < array1.size(); i++){
if(!array1.get(i).equals(array.get(i))){
return false;
}
}
return true;
}
First off, you have to start with test being true and return false if you find something that isn't equal, because this clearly shows that the ArrayLists are not equal. You actually don't need the test variable at all, so I took it out. Just return false if you find something that isn't equal. If you don't find something that isn't equal, it will never return false and will just return true at the end. Second, you have to use the equals() method, because ArrayLists use the Integer class, not the int primitive so == will check if they are the same object, not if they are the same number. Lastly, to deal with comparing arrays of different sizes, you should compare their size and return false if they are not the same size, since there is no way they can be equal.

Error with return in Java?

I get an error in the code from this part of my code:
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
}
return true;
}
When I remove the first return true and instead to the last return true, it don't get the error in my eclipse code, but why can't I have the first place and would this be the same? Thanks!
EDIT: The error message from eclipse say: This method must return a result of type boolean. I'm confused because isn't that what I have done?!
Yes, a break must be in the code
Can I write the method in some other way?
EDIT NUMBER 2
Why isn't this code working?
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
}
This method returns a boolean value so I don't understand why I get an error!? The code looks right to me?
Your edit #2 doesn't compile because there is a possibility that your code won't enter the for-loop. This will be the case if customerList.size() is 0. To fix this, you'll simply need to add a return statement after the for-loop as well:
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
return false;
Another point here is that this code doesn't logically make much sense: it will only return true or false based on the first item in your list. And this is probably not what you want. So take a closer look at several of the other answer here, many of which are good examples for how you can do this.
public boolean findCustomer(String inPersonalNumber){
boolean result = false;
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
result = true;
break;
}
}
return result ;
}
When I remove the first return true and instead to the last return
true, it don't get the error in my eclipse code, but why can't I have
the first place and would this be the same?
If you remove the second return statement the code would be able to run and not return a value - this is not possible as you defined the method to have a return type of Boolean. So it must always return a value no matter what.
Just change the second return statement to false, should do what you want.
Looks like you have turned off the Build Automatically feature of eclipse. It maybe complaining about an error that used to be present when you still hadn't typed in your code fully! This can also happen if you have back-dated your system for some reason.
Also, shouldn't you be returning false if the condition doesn't satisfy?
public boolean findCustomer(String inPersonalNumber) {
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)) {
return true;
}
}
return false;
}
First return will return only in case of all conditions satisfied, but this method should be returning boolean as per code. It would be expecting a return in failure case also.
Removing first return won't affect compilation as it has a return in second place which will work without any condtions.
Edit : Answer for your second question
This code has two return's, but what if your customerList is size 0, in that case also, method must return boolean. right? for that only, compiler is asking.
BTW, code doesn't have null checks.
Your final code could be this. Keeping multiple return statements in code in not a good practice.
public boolean findCustomer(String inPersonalNumber) {
boolean retVal = false;
if (!(inPersonalNumber == null || inPersonalNumber.trim().equals("")
|| customerList == null || customerList.size() == 0)) { // inputs are valid to run this check
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (inPersonalNumber.equals(customerList.get(i).getCustomerPersonalNumber()) { // to avoid NPE, kept inPersonalNumber in check
retVal = true;
break;
}
}
}
return retVal;
}
Because your for loop looses meaning if you're returning true anyway.
If you want to stop loop use break; instead of first return.

Categories