All variations of if statements

Not sure if there's a name or process for this. Looked around and I'd couldn't really find what I was looking for. I'd like to test multiple if statements and all variations of them, but I was wondering if there's a way to do it without specifying every detail in individual if statements. Here's an example of the current process I'm taking, but just looking for simpler ways. Thanks in advance for help.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void foo(int value)
{
    int a, b, c, d, e;
    
    if (a - value <= 5)
    {
        cout << "A is close" << endl;
    }
    
    if (a - value <= 5 &&
            b - value <= 5)
    {
        cout << "A & B are close" << endl;
    }
    
    if (a - value <=5 &&
            b - value <= 5 &&
            c - value <= 5)
    {
        cout << "A & B & C are close" << endl;
    }
    
    if (b - value <= 5 &&
            c - value <=5 &&
            e - value <= 5)
    {
        cout << "B & C & E are close" << endl;
    }
} //Etc, etc, etc 
Last edited on
Do you mean something like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// Example program
#include <iostream>
#include <string>

void foo(int value)
{
    const int arr_size = 5;

    // instead of int a, b, c, d, e...
    int arr[arr_size]  = { 3, -1, 2, 4, 7 };
    char letters[] = "ABCDE";
    
    std::string output;
    const int special_value = 5;    
    
    int num_matches = 0;

    for (int i = 0; i < arr_size; i++)
    {
        if (arr[i] - value <= special_value)
        {
            if (num_matches > 0)
            {
                output += " & ";
            }
            
            output += letters[i];
            num_matches++;
        }
    }
    
    if (num_matches > 1)
    {
        std::cout << output << " are close\n";
    }
    else if (num_matches == 1)
    {
        std::cout << output << " is close\n";
    }
    else
    {
        std::cout << "No matches\n";
    } 
}

int main()
{
    foo(0);
}


A & B & C & D are close


PS: I just copied your logic, but if you're talking about "being close", you probably want to consider the absolute value of the difference.

There's probably even more condensed ways to write this (lambdas, <algorithm>), depending on how fancy you wanna get.
Last edited on
you want to exercise every possible combination of paths through your code?
for this, the only way I know to do it is to loop a,b,c,d,e etc all from X to Y where x and y are bigger than what you think you need to try all your rules.


or you want to make this logic more compact and sensible and cover all possibilities?
(many ways to do this, see above) .. I would have made a boolean for each variable (an array of them seems right here), set each one to true if close, and then cookup a single print statement from that at the end. Similar to above, but a little different.
Last edited on
I don't know why I did this. I was trying make a "for_each_if" <algorithm>-type function but it didn't work out.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Example program
#include <iostream>

template <class Input, class Printout, class FuncCondition, class FuncAction>
void recrudescence(Input in[], Printout printout[], int size, FuncCondition fc, int value, FuncAction fa)
{
    int count = 0;
    for (int i = 0; i < size; i++) {
        fa(i, fc(in[i], value), printout[i], size, count);
    }
}

bool close_enough(int a, int value)
{
    return a - value <= 5;
}

void action(int i, bool passed, char letter, int size, int& count)
{
    if (passed)
    {
        if (count++ > 0)
        {
            std::cout << " & ";
        }
        std::cout << letter;
    }
    if (i == size - 1)
    {
        if (count > 1)
        {
            std::cout << " are close\n";
        }
        else if (count == 1)
        {
            std::cout << " is close\n";
        }
        else
        {
            std::cout << "No matches\n";   
        }
    }
}

int main()
{
    const int size = 5;
    int value = -5;
    int values[size]  = {  3,  -1,   2,   4,   7  };
    int letters[size] = { 'A', 'B', 'C', 'D', 'E' };
    recrudescence(values, letters, size, close_enough, value, action);
}
Last edited on
Meta-program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <string>
#include <cmath>
#include <cctype>

std::string bitstring(int value, int num_bits)
{
    std::string ret;
    for (int b = num_bits-1; b >= 0; b--)
    {
        if (value & (1 << b))
        {
            ret += '1';
        }
        else
        {
            ret += '0';
        }
    }
    return ret;
}

int main(int argc, char** argv)
{
    using std::cout;
    
    int n = 5;
    if (argc > 1)
    {
        n = std::stoi(argv[1]);
    }
    
    bool full_example_program = true;
    
    if (full_example_program)
    {
        cout << "#include <iostream>\n\n";
    }

    cout <<  "void foo(int value)\n"
        << "{\n";
    cout << "    using std::cout;\n\n";

    // attempt at producing a variety of initial values for the variables using modulus
    cout << "    int ";
    for (int i = 0; i < n-1; i++)
    {
        cout << static_cast<char>(i + 'a') << "=" << (i * i * i + 1) % n << ", ";
    }
    cout << static_cast<char>(n-1 + 'a') << "=" << (n * n * n + 1) % n << ";\n\n";
    
    int p = std::pow(2, n);
    
    // skipping i == 0 (will always be at least 1 bit set)
    for (int i = p-1; i > 0; i--)
    {
        std::string bits = bitstring(i, n);
        cout << "    if (";

        for (int i = 0, count = 0; i < n; i++)
        {
            if (bits[i] == '1')
            {
                if (count > 0)
                {
                    cout << " && \n        ";
                }
                cout << static_cast<char>(i + 'a') << " - value <= 5";
                count++;
            }
        }
        
        cout << ")\n";
      
        cout << "    {\n";
        cout << "        cout << \"";
        int plural_count = 0;
        for (int i = 0; i < n; i++)
        {
            if (bits[i] == '1')
            {
                if (plural_count > 0)
                {
                    cout << " & ";
                }
                cout << static_cast<char>(std::toupper(i + 'a'));
                plural_count++;
            }
        }
        if (plural_count > 1)
        {
            cout << " are close\\n\";\n";
        }
        else if (plural_count == 1)
        {
            cout << " is close\\n\";\n";
        }
        
        std::cout << "    }\n";
    }
    
    cout << "}\n";
    
    
    if (full_example_program)
    {
        cout << "\nint main() {\n";
        cout << "    foo(2);\n";
        cout << "}\n";
    }
}


Output of meta-program:
#include <iostream>

void foo(int value)
{
    using std::cout;

    int a=1, b=2, c=4, d=3, e=1;

    if (a - value <= 5 &&
        b - value <= 5 &&
        c - value <= 5 &&
        d - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & B & C & D & E are close\n";
    }
    if (a - value <= 5 &&
        b - value <= 5 &&
        c - value <= 5 &&
        d - value <= 5)
    {
        cout << "A & B & C & D are close\n";
    }
    if (a - value <= 5 &&
        b - value <= 5 &&
        c - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & B & C & E are close\n";
    }
    if (a - value <= 5 &&
        b - value <= 5 &&
        c - value <= 5)
    {
        cout << "A & B & C are close\n";
    }
    if (a - value <= 5 &&
        b - value <= 5 &&
        d - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & B & D & E are close\n";
    }
    if (a - value <= 5 &&
        b - value <= 5 &&
        d - value <= 5)
    {
        cout << "A & B & D are close\n";
    }
    if (a - value <= 5 &&
        b - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & B & E are close\n";
    }
    if (a - value <= 5 &&
        b - value <= 5)
    {
        cout << "A & B are close\n";
    }
    if (a - value <= 5 &&
        c - value <= 5 &&
        d - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & C & D & E are close\n";
    }
    if (a - value <= 5 &&
        c - value <= 5 &&
        d - value <= 5)
    {
        cout << "A & C & D are close\n";
    }
    if (a - value <= 5 &&
        c - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & C & E are close\n";
    }
    if (a - value <= 5 &&
        c - value <= 5)
    {
        cout << "A & C are close\n";
    }
    if (a - value <= 5 &&
        d - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & D & E are close\n";
    }
    if (a - value <= 5 &&
        d - value <= 5)
    {
        cout << "A & D are close\n";
    }
    if (a - value <= 5 &&
        e - value <= 5)
    {
        cout << "A & E are close\n";
    }
    if (a - value <= 5)
    {
        cout << "A is close\n";
    }
    if (b - value <= 5 &&
        c - value <= 5 &&
        d - value <= 5 &&
        e - value <= 5)
    {
        cout << "B & C & D & E are close\n";
    }
    if (b - value <= 5 &&
        c - value <= 5 &&
        d - value <= 5)
    {
        cout << "B & C & D are close\n";
    }
    if (b - value <= 5 &&
        c - value <= 5 &&
        e - value <= 5)
    {
        cout << "B & C & E are close\n";
    }
    if (b - value <= 5 &&
        c - value <= 5)
    {
        cout << "B & C are close\n";
    }
    if (b - value <= 5 &&
        d - value <= 5 &&
        e - value <= 5)
    {
        cout << "B & D & E are close\n";
    }
    if (b - value <= 5 &&
        d - value <= 5)
    {
        cout << "B & D are close\n";
    }
    if (b - value <= 5 &&
        e - value <= 5)
    {
        cout << "B & E are close\n";
    }
    if (b - value <= 5)
    {
        cout << "B is close\n";
    }
    if (c - value <= 5 &&
        d - value <= 5 &&
        e - value <= 5)
    {
        cout << "C & D & E are close\n";
    }
    if (c - value <= 5 &&
        d - value <= 5)
    {
        cout << "C & D are close\n";
    }
    if (c - value <= 5 &&
        e - value <= 5)
    {
        cout << "C & E are close\n";
    }
    if (c - value <= 5)
    {
        cout << "C is close\n";
    }
    if (d - value <= 5 &&
        e - value <= 5)
    {
        cout << "D & E are close\n";
    }
    if (d - value <= 5)
    {
        cout << "D is close\n";
    }
    if (e - value <= 5)
    {
        cout << "E is close\n";
    }
}

int main() {
    foo(2);
}



Example output of program made from meta-program:

A & B & C & D & E are close
A & B & C & D are close
A & B & C & E are close
A & B & C are close
A & B & D & E are close
A & B & D are close
A & B & E are close
A & B are close
A & C & D & E are close
A & C & D are close
A & C & E are close
A & C are close
A & D & E are close
A & D are close
A & E are close
A is close
B & C & D & E are close
B & C & D are close
B & C & E are close
B & C are close
B & D & E are close
B & D are close
B & E are close
B is close
C & D & E are close
C & D are close
C & E are close
C is close
D & E are close
D is close
E is close


Let me know if there are bugs.
Last edited on
This is exactly what I was looking for @Ganado, thanks. So, if I'm not mistaken, this tests the values and then writes the if statements itself, correct? I was trying to figure out how exactly it would work, but I don't think I could've come up with this.
My last post was kinda a joke, but yes for my original post, it uses an array instead of using 5 hardcoded variables with frankly meaningless names (a - e), and then generates an output strings based on which of those numbers in the array meet the criteria.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
using namespace std;

bool criterion( double x, double value ){ return abs( x - value ) <= 5; }

string satisfied( const vector< pair<string,double> > &V, double value )
{
   string answer;
   int n = 0;
   for ( auto pr : V )
   {
       if ( criterion( pr.second, value ) )
       {
          answer += ( n ? " & " : "" ) + pr.first;
          n++;
       }
   }
   return ( n ? answer + ( n > 1 ? " are " : " is " ) : "None are " ) + "close";
}

int main()
{
   double value = 8.0;
   vector< pair<string,double> > V = { { "A", 3.0 }, { "B", -1.0 }, { "C", 2.0 }, { "D", 4.0 }, { "E", 7.0 } };
   cout << satisfied( V, value ) << '\n';
}
Last edited on
Much more concise :)
Kind, @Ganado, but I was practising obfuscation!
Well in that case: Awful code, I was able to understand it way too quickly, 1/10.
Topic archived. No new replies allowed.