Stack Overflow Asked on November 15, 2021
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.
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
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP