My loop doesn't end when the condition is true - java

My program prompts the user to input an item's code. Duplicate codes are not allowed so when he enters the code, the for loop will checks if it exists. The for loop should break for my condition because I do get the output "Item's code exists" but it still does not add the item to the array. What am I missing?
tems[] items = new Items[200];
AddItem add = new AddItem();
Scanner s = new Scanner(System.in);
int z,x;
double c,v;
String n,m,b;
public void addItem(){
int r;
z = add.getCode();
x = add.getQuantity();
c = add.getCostPrice();
n = add.getDescription();
m = add.getDiscount();
v = add.getSellingPrice();
b = add.getStatus();
for(r = 0; r < items.length; r++){
for(int q=0; q<r; q++){
if(z==items[q].getCode()){
System.out.println("Item's code exists");
break;
}
}
if(items[r]==null){
items[r] = new Items(z, n, x, c, v, b, m);
break;
}else if (items[r]!=null){
continue;
}
}
}

If you want to break the outer loop, use a labeled break. Something like,
out: for(r = 0; r < items.length; r++){
for(int q=0; q<r; q++){
if(z==items[q].getCode()){
System.out.println("Item's code exists");
break out;
}
}

Your code is a little difficult to understand. Try improving variable names and creating comments so others can understand code better. I Believe the problem lies in your loops. The break statement breaks out of the first for loop, but it will not break out of both. If i am understanding your code, then it would be better to place a flag to properly break out of both loops.

An alternative to using break is using a boolean variable :
boolean codeExists = false;
for(r = 0; r < items.length && !codeExists; r++){
for(int q=0; q<r && !codeExists; q++){
if(z==items[q].getCode()) {
System.out.println("Item's code exists");
codeExists = true;
}
}
}
Both loops would be exited once codeExists becomes true.

Related

Using return vs While(condition) methods To Break Loops

I'm doing a little google interview question. Find the pair of numbers in a loop that add up to the number given. I found the numbers 2 and 6 that make up 8 so I say match = true so that the while loop stops, however it still proceeds until it finds the second which is 6 and 2 however, those numbers I have already found just the other way around and I had expected my loop to break as my if statement states if there is any 2 numbers that give the sum, match = true therefore terminating the loop, I guess I am wrong though.
However, if I get rid of the while statement and just return; once a match is found it breaks without looking for the second match (which I want it to).
Why is this happening, the logic of both seems the exact same to me.
Using the while(condition) Method
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
boolean match = false;
int sumNeeded = 8;
while(!match){
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j >= 0; j --){
if(list[i] != list[j]){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
match = true;
}
}
}
}
}
}
}
Using return
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
int sumNeeded = 8;
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j >= 0; j --){
if(list[i] != list[j]){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
return;
}
}
}
}
}
}
In your while-loop implementation, if the array doesn't have the desired pair at all it would result in an infinite loop. There is no need for the while statement in your solution.
After you enter into the while loop, you look for all the possible pairs in the array and then check for their sum. If it equals the desired sum, you make the boolean variable match as true.
But, until the nested for loop is completely executed (i.e., all the possible pairs are checked) we do not check for the while condition. The entire nested for loop is executed in one iteration of the while loop. Then, the while loop condition is checked again.
As by the end of the first iteration of the while loop all the possible pairs are accounted for, there is no need for a while loop.
Moreover, there are other logical errors in your implementation. The correct brute-force implementation is as follows:
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
boolean match = false;
int sumNeeded = 8;
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j > i; j --){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
return;
}
}
}
}
}
The inner-for loop is modified to reduce the double-counting of the unordered pairs. Whenever a match is found and printed, we exit the function.
You may also add a break statement inside the while loop in your initial implementation.
if(match == true) {
break;
}
The while condition continues to execute the first and second for-loop until it's finished where as with return it stops execution entirely from the first and second loop.
To fix the while loop you could use a label and then break from that.
firstLoop:
for(int i = 0; i < list.length; i ++) {
match = true;
break firstLoop;

comparing elements in an array and fetching new ones

I realize this has been asked before and I had a look at it but, for me, it only works to a point. After some struggle, I thought I'd ask.
I have an array of floats in an object's constructor.
That goes like this:
count = 3;
angles = new float[count];
The array length is really small though I'd like implement a modular and reusable approach.
I loop through the array assigning floats:
for (int i = 0; i < angles.length; i++) {
angles[i] = radians(random(360));
}
Then, with a new loop, I check if the singular elements have less than 30 degrees in between them, and if so, assign a new random value:
for (int i = 0; i < angles.length; i++) {
for (int k = i+1; k < angles.length; k++){
if(angles[i] != angles[k]){
if(abs(angles[i] - angles[k]) <= radians(30)){
angles[i] = radians(random(360));
}
}
}
}
This works nice and well but it doesn't guarantee that the new random number will keep the 30 degrees limit with the remaining elements. This, I assume, has to do with the length of the 'for' loop.
What would be the best way to overcome this and guarantee that newly fetched number will always conform to the 30 degree rule?
Instead of just checking once with an if statement, you could change it to a while statement, so that it attempts to find a new random number until the new one works.
while (abs(angles[i] - angles[k]) <= radians(30)){
angles[i] = radians(random(360));
}
However, if there are no numbers that follow your 30 degree rule, your program will get stuck in this loop, so you might want to check that there is a possible solution before entering the loop.
Edit: the above solution will ensure that the number follows the 30 degree rule with only one number in your array. Add a boolean to determine if the condition has been met, and loop until the boolean is true.
for (int i = 0; i < angles.length; i++) {
boolean meetsCondition = false;
while (!meetsCondition) {
for (int k = 0; k < angles.length; k++){
if(i != k){
if(abs(angles[i] - angles[k]) <= radians(30)){
angles[i] = radians(random(360));
meetsCondition = false;
break;
}
}
}
meetsCondition = true; //if the for loop completes, it has met the condition.
}
}
Why not use recursion earlier on:
for (int i = 0; i < angles.length; i++) {
angles[i] = findSuitable( i==0 ? 0 : angles[i-1] )
}
...
float findSuitable(float limit){
float sample = radians(random(360));
if(Math.abs(sample-limit) > 30)
return sample;
else
return findSuitable(limit);
}
In my opinion, you can try to change the the codes of random to this:
Random d = new Random();
int a = d.nextInt(360);

How to break out of nested loops

I'm currently making a program where nested loops are needed to search through an array to find a spot for good input within the array. Here is an example:
public void placePiece(int column) {
boolean goodInput = false;
while(!goodInput) {
for(int x = 5; x >= 0; x--) {
if(boardStatus[x][column] == 0) {
setRow(x);
boardStatus[x][column] = 1;
goodInput = true;
break;
}else if(boardStatus[0][column] == 1) {
goodInput = false;
break;
}else{
}
}
}
}
The method takes a parameter which is the column in which the piece should be located (received by a mouse listener). If the column in the 2D array is already filled to the top, the program gets stuck in an endless loop within the "else if", and I'm unsure how I would break out of this loop. How could I break out of this loop if there is bad input so that the user can try to give another column as input.
An easy way is to use a labeled break statement.
myLabelName:
for(outer loop)
for(inner loop)
if(condition)
break myLabelName;
This is useful when you'd rather not waste time iterating over other objects/items when you've found what you needed.
To expand, when you use just break; (without a label) it will exit the parent loop.
Ex:
myLabelName:
for(outer loop){
for(inner loop){
if(condition){
break myLabelName; //breaks outer loop
}
else if(other condition){
break; //breaks parent (inner/nested) loop
}
}
}
When you are in elseif loop your are again assigning the goodInput = false; so the while conditions again becomes true and loops continuous forever.
if you want to take input till correct input is received can use do(){}while() loop
Based on the description you provided, I am not sure of the purpose of the else if statement. As I understand you intention, you are checking all of the rows within a certain column to see if that cell has been set or not?
The combination of the while loop and the for loop seems suspect as well. There doesn't seem to be any need for the while loop in this case.
What is supposed to happen if the entire column is filled? Should this method return a status flag?
Can't this be implemented with a single for loop?
for (int x = 5; x >= 0; --x)
{
if(boardStatus[x][column] == 0) {
setRow(x);
boardStatus[x][column] = 1;
break;
}
}
If you want, you can track a flag variable to indicate if you ever found a cell which was empty.
you can use flag or you can use goto statement
flag description
code
bool flag = true;
for (int i = 0; (i < 10) && (flag==true); i++)
{
for(int j = 0; (j < 10) && (flag==true); j++)
{
if (condition)
flag = false;
}
}
Change the parameter AFTER the loop:
public void placePiece(int column) {
boolean goodInput = false;
while(!goodInput) {
for(int x = 5; x >= 0; x--) {
if(boardStatus[x][column] == 0) {
setRow(x);
boardStatus[x][column] = 1;
goodInput = true;
break;
}else if(boardStatus[0][column] == 1) {
goodInput = false;
break;
}else{
}
}
goodInput = true; // <-----
}
}

So I was wondering why it truns out to be a false about my junit test

here is my solution
public int count_chars_in_String(String s, String s1){
int count = 0;
for(int j = 0; j<s1.length(); j++){
for(int i = 0; i<s.length();i++){
if(s.charAt(i) == s1.charAt(j)){
count += 1;
}
}
}
and here is my rest code
#Test public void tests4(){
code.Solution s = new code.Solution();
String input = "hhhhhey ";
String input1 = "hhh";
int expected = 3;
int actual = s.count_chars_in_String(input, input1);
assertTrue("Expected was" +expected+"but the actual was" +actual , expected == actual);
}
every time i run the junit test it shows up that Expected was3 but actual was 15? How???I am so confusing.
Code which would give you result 3 would look probably like (note the break statement):
// the outer loop
for(int j = 0; j<s1.length(); j++){
// the inner loop
for(int i = 0; i<s.length();i++){
if(s.charAt(i) == s1.charAt(j)){
count += 1;
// Break the inner loop after finding
// the match.
break;
}
}
}
Without the break, for each h in hhh (the outer loop), you increase the counter 5 times (the inner loop; because h occurs 5 times in hhhhhey).
do not know if this answer is what you are looking for and excuse my poor English.
The for j will run 3 times and for each of the times the for i will run 5 times, that are equal to the time that the condition is met. Now 5x3=15, the result that you get.
if what you expect is to get the number characters that match each string (3), then just do the following:
for(int i = 0; i<s1.length();i++){
if(s.charAt(i) == s1.charAt(i)){
count += 1;
}
}
Regards.

Dead code in double for loop

I recently started coding in Java, and I have met this dead code problem. I have been looking at other questions (and answers) at Stack Overflow but I haven't found a solution yet. Hopefully you can help. The problem occurs at t++
public static boolean constraint2(int [][] xmatrix, int [][] ymatrix){
for(int l = 0; l < xmatrix.length; l++){
for(int t = 0; t < xmatrix[0].length; t++){ // DEAD CODE at "t++"
if(b[t]*xmatrix[l][t] > ymatrix[l][t]){
return false;
}
else{
return true;
}
}
}
return false;
}
It means that this statement will never execute. First iteration of this loop will exit method and break the loop. So this code is equivalent to:
for(int l = 0; l < xmatrix.length; l++){
if(xmatrix[0].length>0) {
if(b[0]*xmatrix[l][0] > ymatrix[l][0]){
return false;
}
else{
return true;
}
}
}
and t++ doesn't really make sense.
"Dead code" is usually just a warning and wouldn't stop you from compiling your app.
Also, probably you meant t < xmatrix[l].length in loop condition.
UPDATE: You didn't mention it in your question body, but as far as I understand from your comment to another answer what you need is to check that constraint holds for each element in the matrix. To implement it all you need is to check if constraint fails:
public static boolean constraint2(int [][] xmatrix, int [][] ymatrix){
for(int l = 0; l < xmatrix.length; l++){
for(int t = 0; t < xmatrix[l].length; t++){
if(b[t]*xmatrix[l][t] > ymatrix[l][t]) {
//constraint failed
return false;
}
}
}
//constraint holds for all elements
return true;
}
The code returns boolean value in your for loop and returns to the calling function. So it is obvious that code will not execute further after first iteration.
for(int t = 0; t < xmatrix[0].length; t++){ //This is your for loop
if(b[t]*xmatrix[l][t] > ymatrix[l][t]){
return false; // In first iteration, this loop either return false
} // or
else{ //true as per the condition
return true; // And return to the calling function by breaking the loop.
}
}
Inside the most inner for loop---- for both if and else condition checking you are returning from the function after the first iteration. So the t++ is not executing. It's nothing with Java. I think there is some problem in problem solving logic. You have to stop from returning either the if condition is true or the false condition.

Categories