InsideDarkWeb.com

Finding all the 3-combinations of the output of for loops

I feel like this is supposed to be very straightforward but I am unable to work it out.

I have a very simple piece of c++ code.

for (int k = 0; k < 2; ++k)
    {
        for (int a = 0; a < 4; ++a)
        {
            for (int b = 0; b < 4; ++b)
            {
                if (a != b)
                {
                    std::cout << "k: " << k  << " a: " << a  << " b: " << b  << "n";
                }
            }
        }

The output will have 24 lines like this

k: 0 a: 0 b: 1
k: 0 a: 0 b: 2
k: 0 a: 0 b: 3
k: 0 a: 1 b: 0
k: 0 a: 1 b: 2
k: 0 a: 1 b: 3
k: 0 a: 2 b: 0
k: 0 a: 2 b: 1
k: 0 a: 2 b: 3
k: 0 a: 3 b: 0
k: 0 a: 3 b: 1
k: 0 a: 3 b: 2
k: 1 a: 0 b: 1
k: 1 a: 0 b: 2
k: 1 a: 0 b: 3
k: 1 a: 1 b: 0
k: 1 a: 1 b: 2
k: 1 a: 1 b: 3
k: 1 a: 2 b: 0
k: 1 a: 2 b: 1
k: 1 a: 2 b: 3
k: 1 a: 3 b: 0
k: 1 a: 3 b: 1
k: 1 a: 3 b: 2

What I want is essentially 3 choice of those 24 lines of output. 24 choose 3 = 2024 lines of output without any additional library usage. I want to do some calculations based on 3 of those 24 lines at a time.

The equivalent python code

import itertools    
iterable = ["k: 0 a: 0 b: 1", "k: 0 a: 0 b: 2", "k: 0 a: 0 b: 3", "k: 0 a: 1 b: 0", "k: 0 a: 1 b: 2", "k: 0 a: 1 b: 3", "k: 0 a: 2 b: 0", "k: 0 a: 2 b: 1", "k: 0 a: 2 b: 3", "k: 0 a: 3 b: 0", "k: 0 a: 3 b: 1", "k: 0 a: 3 b: 2", "k: 1 a: 0 b: 1", "k: 1 a: 0 b: 2", "k: 1 a: 0 b: 3", "k: 1 a: 1 b: 0", "k: 1 a: 1 b: 2", "k: 1 a: 1 b: 3", "k: 1 a: 2 b: 0", "k: 1 a: 2 b: 1", "k: 1 a: 2 b: 3", "k: 1 a: 3 b: 0", "k: 1 a: 3 b: 1", "k: 1 a: 3 b: 2"]
a = list(itertools.combinations(iterable, 3))
print(a)

demonstrates what I want. I was wondering how to do this in C++ using just the for loops.

Stack Overflow Asked on November 15, 2021

2 Answers

2 Answers

If value of k is varying and much larger than 3, we'll have to apply recursion. Till then 3 for loops works fine.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<vector<int>> M;
    for (int k = 0; k < 2; ++k)
        for (int a = 0; a < 4; ++a)
            for (int b = 0; b < 4; ++b)
                if (a != b)
                    M.push_back(vector<int>({ k, a, b }));

    vector<vector<int>> res;
    for (int i = 0; i < (int)M.size() - 2; ++i)
        for (int j = i + 1; j < (int)M.size() - 1; ++j)
            for (int k = j + 1; k < (int)M.size(); ++k)
            {
                vector<int> temp;

                for (int e : M[i])
                    temp.push_back(e);
                for (int e : M[j])
                    temp.push_back(e);
                for (int e : M[k])
                    temp.push_back(e);
                res.push_back(temp);
            }

    for (const vector<int>& V : res)
    {
        for (int e : V)
            cout << e << ' ';
        cout << endl;
    }
}

Answered by srt1104 on November 15, 2021

To make things easier, I'd group a k, a and b value together into a single object. Let's call it a K-A-B object, or a kab:

struct kab {
    int k, a, b;
};

Then, I'd make an increment function that'll take a kab and give us the next kab in the sequence. This'll allow us to condense all three of your loops down into one and make it easier to iterate from any point in the sequence. That could look like:

kab increment(kab obj) {
    obj.b = (obj.b + 1) % (MAX_B + 1);
    if(obj.b == 0) {
        obj.a = (obj.a + 1) % (MAX_A + 1);
        if(obj.a == 0) {
            obj.k++;
        }
    }
 
    // Ensure a != b by incrementing again if they are
    if(obj.a == obj.b) {
        return increment(obj);
    }
 
    return obj;
}

Lastly, it's just a matter of doing the actual increments. Here's an example:

while(vals.k <= MAX_K) {
    kab vals2 = increment(vals);
    while(vals2.k <= MAX_K) {
        kab vals3 = increment(vals2);
        while(vals3.k <= MAX_K) {
            std::cout << "k: " << vals.k  << " a: " << vals.a  << " b: " << vals.b  << std::endl;
            std::cout << "k: " << vals2.k  << " a: " << vals2.a  << " b: " << vals2.b  << std::endl;
            std::cout << "k: " << vals3.k  << " a: " << vals3.a  << " b: " << vals3.b  << std::endl;
            std::cout << std::endl;

            vals3 = increment(vals3);
        }
        vals2 = increment(vals2);
    }
    vals = increment(vals);
}

See it run here: https://ideone.com/9cVHuG (note that that much output causes ideone to timeout. This should work fine locally).

Answered by scohe001 on November 15, 2021

Add your own answers!

Related Questions

set year to the x labels in matplotlib

1  Asked on February 12, 2021 by nargento

     

Proper way to use Vuex with child components

1  Asked on February 12, 2021 by luma

     

is DRAM(main memory) a character device?

0  Asked on February 11, 2021 by jonggyu-park

   

How to declare a function that accepts a typed array parameter

1  Asked on February 11, 2021 by zentrunix

 

Loop nested array and return values by index

4  Asked on February 11, 2021 by jordan-starrk

   

Java writing unlimited text lines to a UI

0  Asked on February 11, 2021 by barry-griffey

     

R simple dplyr solution to filter

3  Asked on February 11, 2021 by triss

     

Go back browser button action

2  Asked on February 11, 2021 by ljopata

 

How to pass array to funtion to use as range based for loop

3  Asked on February 10, 2021 by aniket-ujgare

   

Ask a Question

Get help from others!

© 2021 InsideDarkWeb.com. All rights reserved.