Ben123
Ben123

Reputation: 355

C++ Problem: 'break' within nested for loops not working as expected?

I'm trying to write a program to find a specific 4 digit number with the following conditions:

I'm struggling to write this program. I tried nested for loops iterating each digit until the conditions are met (when a break terminates the loops), as below:

int a = 1;
int b = 1;
int c = 1;
int d = 1;

for (a = 1; a < 9; a++) {
    for (b = 1; b < 9; b++) {
        for (c = 1; c < 9; c++) {
            for (d = 1; d < 9; d++) {

                if (a + b + c + d == 27 && a == 3 * c && a != b && a != c
                && a != d && b!= c && b != d && c != d && d % 2 != 0) {
                    break;
                }
            }
        }
    }
}

I expected the digits a, b, c, d to provide me with the number to fulfil all conditions in the if statement above and thus to break. Instead, abcd is always 9999. Why is this happening? How am I misusing break?

Upvotes: 1

Views: 623

Answers (4)

ejderuby
ejderuby

Reputation: 735

The break in your code only breaks the for loop that it's in. One solution would be to place the calculation into a function, exit the function when the conditions are met with return, and return the value that you build from each digit. Also, you must test digits 0 through 9, but in your code, you only test values 1 through 8. So, the solution is as follows:

#include <iostream>

using namespace std;

int find_number(){
    int a, b, c, d, result;

    for (a = 0; a <= 9; a++) {
        for (b = 0; b <= 9; b++) {
            for (c = 0; c <= 9; c++) {
                for (d = 0; d <= 9; d++) {
                    if (a + b + c + d == 27 && a == 3 * c && a != b && a != c &&
                    a != d && b != c && b != d && c != d && d % 2 != 0) {
                        result = a*1000 + b*100 + c*10 + d;
                        return result;
                    } // end if
                } // end for
            } // end for
        } // end for
    } // end for
    
    return 0;
} // end find_number()

int main()
{
    cout << find_number() << endl;

    return 0;
} // end main()

My Suggested Improvements

Below is a solution assuming you know a few things about numbers and you want to optimize for efficiency (minimize the number of times the for loops are executed).

  • For a, only 3, 6, and 9 must be tested (1*3=3, 2*3=6, 3*3=9).
  • c can be derived from a, so you can eliminate the for loop testing c values.
  • Only loop for odd numbers in d loop.
  • Switch b and d loop so that code in outer loop runs less times.
  • a will never equal c, so no need to check.
  • Check a and c don't equal d right inside d loop.
  • Check b doesn't equal other digits before adding digits and checking they equal 27.
  • Separate the if statement conditions into different lines so that it's easier to read. This also enables a debugger to be able to step through the conditions line-by-line, and compilers will identify potential errors on which line/condition produced the error.
#include <iostream>

using namespace std;

int find_number(){
    int a, b, c, d, result;
    
    for(a = 3; a <= 9; a += 3){ // Only runs 3 times
        c = a/3;
        for(d = 1; d <= 9; d += 2){ // Skip even numbers
            if(d != a 
            && d != c){
                for(b = 0; b <= 9; b++){
                    if(b != a 
                    && b != c 
                    && b != d 
                    && a + b + c + d == 27){ 
                        result = a*1000 + b*100 + c*10 + d;
                        return result;
                    } // end if
                } // end for
            } // end if
        } // end for
    } // end for

} // end find_number()

int main()
{
    cout << find_number() << endl;

    return 0;
} // end main()

Upvotes: 0

Abhishek Dalakoti
Abhishek Dalakoti

Reputation: 31

break only breaks the inner loop. If you want to come out of all the loops, either use return, or a variable, like flag.

int a = 1;
int b = 1;
int c = 1;
int d = 1;
int flag = 0;

for (a = 1; a < 9; a++) {
    for (b = 1; b < 9; b++) {
        for (c = 1; c < 9; c++) {
            for (d = 1; d < 9; d++) {
                if (a + b + c + d == 27 && a == 3 * c && a != b && a != c
                && a != d && b!= c && b != d && c != d && d % 2 != 0) {
                    flag = 1;
                    break; // breaks d loop
                }
            }
            if(flag == 1)
                break; // breaks c loop
        }
        if(flag == 1)
            break; // breaks b loop
    }
    if(flag == 1)
        break; // breaks a loop
}

This is a bad practice, but will give correct output. I would prefer using a return statement, or you can use a goto statement to jump out of the loop.

Upvotes: 1

YourPalNurav
YourPalNurav

Reputation: 1320

#include<stdio.h>

int findNum();

int main()
{
    int num;
    num = findNum();
    printf("%d is the required number.\n\n",num);
    return 0;
}

int findNum()
{
    int a, b, c, d;
    for (a = 1; a <= 9; a++)
    {
        for (b = 0; b <= 9; b++)
        {
            for (c = 0; c <= 9; c++)
            {
                for (d = 0; d <= 9; d++)
                {
                    if (a+b+c+d==27 && a==(3*c) && a!=b && a!=c && a!=d && b!=c && b!=d && c!=d && (d%2)!=0)
                    {
                        return (1000*a)+(100*b)+(10*c)+d;
                    }
                }
            }
        }
    }
}

Upvotes: 2

Kon
Kon

Reputation: 4099

break will only break out of the inner most loop. So when you hit your condition, you just go into the next iteration of the c value.

Upvotes: 4

Related Questions