Help me please.
I have a 3d vector. I need to make a new vector from this using existing internal indices. I hope the input and output information will be clear.
Input:
a = {
{ {1,1,1,1}, {2,2,2,2}, {3,3,3,3}, {4,4,4,4}, {5,5,5,5}, {6,6,6,6} },
{ {10,10,10,10}, {20,20,20,20}, {30,30,30,30}, {40,40,40,40}, {50,50,50,50}, {60,60,60,60} },
{ {100,100,100,100}, {200,200,200,200}, {300,300,300,300}, {400,400,400,400}, {500,500,500,500}, {600,600,600,600} },
};
Output:
b = {
{{ 1,1,1,1}, {10,10,10,10}, {100,100,100,100}},
{{ 2,2,2,2}, {20,20,20,20}, {200,200,200,200}},
{{ 3,3,3,3}, {30,30,30,30}, {300,300,300,300}},
{{ 4,4,4,4}, {40,40,40,40}, {400,400,400,400}},
{{ 5,5,5,5}, {50,50,50,50}, {500,500,500,500}},
{{ 6,6,6,6}, {60,60,60,60}, {600,600,600,600}},
}
I don't know how to iterate over indices in a 3D array to create a new 3D array (Output). I want to create a 3D vector from the columns (n-indices) of an existing 3D vector. I have a 3D vector ('Input'). I need to make a 3D vector out of this ('Output').
#include <iostream>
#include <vector>
using namespace std;
void show3D_vector(std::vector<std::vector<std::vector<double>>>& a);
void show2D_vector(std::vector<std::vector<double>>& a);
template<typename T> std::vector<std::vector<T>> SplitVector(const std::vector<T>& vec, size_t n);
int main()
{
a = {
{ {1,1,1,1}, {2,2,2,2}, {3,3,3,3}, {4,4,4,4}, {5,5,5,5}, {6,6,6,6} },
{ {10,10,10,10}, {20,20,20,20}, {30,30,30,30}, {40,40,40,40}, {50,50,50,50}, {60,60,60,60} },
{ {100,100,100,100}, {200,200,200,200}, {300,300,300,300}, {400,400,400,400}, {500,500,500,500}, {600,600,600,600} },
};
}
void show3D_vector(std::vector<std::vector<std::vector<double>>>& a)
{
for (double i = 0; i < a.size(); ++i)
{
for (double j = 0; j < a[i].size(); ++j)
{
for (double k = 0; k < a[i][j].size(); ++k)
std::cout << a[i][j][k] << " ";
std::cout << endl;
}
std::cout << endl;
}
}
void show2D_vector(std::vector<std::vector<double>>& a)
{
for (int i = 0; i < a.size(); i++) {
for (auto it = a[i].begin(); it != a[i].end(); it++)
{
std::cout << *it << " ";
}
std::cout << endl << endl;
}
}
template<typename T>
std::vector<std::vector<T>> SplitVector(const std::vector<T>& vec, size_t n)
{
std::vector<std::vector<T>> outVec;
size_t length = vec.size() / n;
size_t remain = vec.size() % n;
size_t begin = 0;
size_t end = 0;
for (size_t i = 0; i < std::min(n, vec.size()); ++i)
{
end += (remain > 0) ? (length + !!(remain--)) : length;
outVec.push_back(std::vector<T>(vec.begin() + begin, vec.begin() + end));
begin = end;
}
return outVec;
}
Thank you.
You can solve this matrix transpose more succinctly.
for(const auto& a1 : a){
b.resize(a1.size());
auto b1 = b.begin();
for(const auto& a2 : a1){
b1->push_back(a2);
b1++;
}
}
output is
{{1,1,1,1,},{10,10,10,10,},{100,100,100,100,},},
{{2,2,2,2,},{20,20,20,20,},{200,200,200,200,},},
{{3,3,3,3,},{30,30,30,30,},{300,300,300,300,},},
{{4,4,4,4,},{40,40,40,40,},{400,400,400,400,},},
{{5,5,5,5,},{50,50,50,50,},{500,500,500,500,},},
{{6,6,6,6,},{60,60,60,60,},{600,600,600,600,},},
Given your input and output in the example you posted, it seems to be just a transpose of the data, where n would be irrelevant.
If this is the case, the following code does this:
#include <vector>
#include <iostream>
void show3D_vector(std::vector<std::vector<std::vector<double>>>& a)
{
for (size_t i = 0; i < a.size(); ++i)
{
for (size_t j = 0; j < a[i].size(); ++j)
{
std::cout << "{";
for (size_t k = 0; k < a[i][j].size(); ++k)
{
if (k > 0)
std::cout << ",";
std::cout << a[i][j][k];
}
std::cout << "} ";
}
std::cout << std::endl;
}
}
template<typename T>
std::vector<std::vector<std::vector<T>>> Transpose(const std::vector<std::vector<std::vector<T>>>& vec)
{
if (vec.empty())
return {};
// Construct the output vector
std::vector<std::vector<std::vector<T>>>
outVect(vec[0].size(),
std::vector<std::vector<T>>(vec.size()));
// transpose loop
for (size_t row = 0; row < vec.size(); ++row)
{
for (size_t col = 0; col < vec[0].size(); ++col)
outVect[col][row] = vec[row][col];
}
return outVect;
}
int main()
{
std::vector<std::vector<std::vector<double>>> a =
{
{ {1,1,1,1}, {2,2,2,2}, {3,3,3,3}, {4,4,4,4}, {5,5,5,5}, {6,6,6,6} },
{ {10,10,10,10}, {20,20,20,20}, {30,30,30,30}, {40,40,40,40}, {50,50,50,50}, {60,60,60,60} },
{ {100,100,100,100}, {200,200,200,200}, {300,300,300,300}, {400,400,400,400}, {500,500,500,500}, {600,600,600,600} },
};
auto b = Transpose(a);
show3D_vector(b);
}
Output:
{1,1,1,1} {10,10,10,10} {100,100,100,100}
{2,2,2,2} {20,20,20,20} {200,200,200,200}
{3,3,3,3} {30,30,30,30} {300,300,300,300}
{4,4,4,4} {40,40,40,40} {400,400,400,400}
{5,5,5,5} {50,50,50,50} {500,500,500,500}
{6,6,6,6} {60,60,60,60} {600,600,600,600}
The other issue is that your show3d_vector function uses an incorrect type for the for loop counter. It should be size_t, not double.
Hello I am looking for a way to write this C++ Code in a general way, so that if a want 20 columns I will not have to write 20 for loops:
for(int i=1; i<6; i++) {
for(int j=i; j<6; j++) {
for(int k=j; k<6; k++) {
for(int m=k; m<6; m++) {
std::cout << i << j << k << m << std::endl;
}
}
}
}
It is important that my numbers follow a >= Order.
I am very grateful for any help.
This recursive function should work:
#include <iostream>
bool inc( int *indexes, int limit, int n )
{
if( ++indexes[n] < limit )
return true;
if( n == 0 ) return false;
if( inc( indexes, limit, n-1 ) ) {
indexes[n] = indexes[n-1];
return true;
}
return false;
}
int main()
{
const size_t N=3;
int indexes[N];
for( size_t i = 0; i < N; ++i ) indexes[i] = 1;
do {
for( size_t i = 0; i < N; ++i ) std::cout << indexes[i] << ' ';
std::cout << std::endl;
} while( inc( indexes, 6, N-1 ) );
return 0;
}
live example
The design here is simple. We take a std::vector each containing a dimension count and a std::vector containing a current index at each dimension.
advance advances the current bundle of dimension indexes by amt (default 1).
void advance( std::vector<size_t>& indexes, std::vector<size_t> const& counts, size_t amt=1 ) {
if (indexes.size() < counts.size())
indexes.resize(counts.size());
for (size_t i = 0; i < counts.size(); ++i ) {
indexes[i]+=amt;
if (indexes[i] < counts[i])
return;
assert(counts[i]!=0);
amt = indexes[i]/counts[i];
indexes[i] = indexes[i]%counts[i];
}
// past the end, don't advance:
indexes = counts;
}
which gives us an advance function for generic n dimensional coordinates.
Next, a filter that tests the restriction you want:
bool vector_ascending( std::vector<size_t> const& v ) {
for (size_t i = 1; (i < v.size()); ++i) {
if (v[i-1] < v[i]) {
return false;
}
}
return true;
}
then a for loop that uses the above:
void print_a_lot( std::vector<size_t> counts ) {
for( std::vector<size_t> v(counts.size()); v < counts; advance(v,counts)) {
// check validity
if (!vector_ascending(v))
continue;
for (size_t x : v)
std::cout << (x+1);
std::cout << std::endl;
}
}
live example.
No recursion needed.
The downside to the above is that it generates 6^20 elements, and then filters. We don't want to make that many elements.
void advance( std::vector<size_t>& indexes, std::vector<size_t> const& counts, size_t amt=1 ) {
if (indexes.size() < counts.size())
indexes.resize(counts.size());
for (size_t i = 0; i < counts.size(); ++i ) {
indexes[i]+=amt;
if (indexes[i] < counts[i])
{
size_t min = indexes[i];
// enforce <= ordering:
for (size_t j = i+i; j < counts.size(); ++j) {
if (indexes[j]<min)
indexes[j]=min;
else
break; // other elements already follow <= transitively
}
assert(vector_ascending(indexes));
return;
}
assert(counts[i]!=0);
amt = indexes[i]/counts[i];
indexes[i] = indexes[i]%counts[i];
}
// past the end, don't advance:
indexes = counts;
}
which should do it without the vector_ascending check in the previous version. (I left the assert in to do testing).
This function works for me, but do not call it with 20 if you want it to finish.
#include <list>
#include <iostream>
std::list<std::list<int>> fun (std::list<std::list<int>> inputlist, int counter)
{
if(counter == 0)
{
return inputlist;
}
else
{
std::list<std::list<int>> outputlist;
for(std::list<int> oldlist : inputlist)
{
for(int i = 1; i<6; i++)
{
std::list<int> newlist = oldlist;
newlist.push_back(i);
outputlist.push_back(newlist);
}
}
return fun(outputlist, counter - 1);
}
}
int main()
{
std::list<int> somelist;
std::list<std::list<int>> listlist;
listlist.push_back(somelist);
std::list<std::list<int>> manynumbers = fun (listlist,5);
for (std::list<int> somenumbers : manynumbers)
{
for(int k : somenumbers)
{
std::cout<<k;
}
std::cout<<std::endl;
}
return 0;
}
Same with Processing (java) here :
void loopFunction(int targetLevel, int actualLevel, int min, int max, String prefix){
/*
targetLevel is the wanted level (20 in your case)
actualLevel starts from 1
min starts from 1
max is the max number displayed (6 in your case)
prefix starts from blank
see usage bellow (in setup function)
*/
for(int m=min; m<max; m++) {
if(targetLevel==actualLevel)
{
println(prefix+ " " + m);
}
else
{
loopFunction(targetLevel, actualLevel+1,m,max,prefix+ " " + m);
}
}
}
void setup(){
loopFunction(10,1,1,6,"");
}
Well, I am not the fastest in writing answer... when I started there was no other answer. Anyhow, here is my version:
#include <iostream>
#include <vector>
using namespace std;
class Multiindex {
public:
typedef std::vector<int> Index;
Multiindex(int dims,int size) :
dims(dims),size(size),index(Index(dims,0)){}
void next(){
int j=dims-1;
while (nextAt(j) && j >= 0){j--;}
}
Index index;
bool hasNext(){return !(index[0]==size-1);}
private:
bool nextAt(int j){
index[j] = index[j]+1;
bool overflow = (index[j]==size);
if (!overflow && j < dims-1){std::fill(index.begin() + j + 1,index.end(),index[j]);}
return overflow;
}
int dims;
int size;
};
int main() {
Multiindex m(4,6);
while (m.hasNext()){
cout << m.index[0] << m.index[1] << m.index[2] << m.index[3] << endl;
m.next();
}
cout << m.index[0] << m.index[1] << m.index[2] << m.index[3] << endl;
return 0;
}
I am working on a N dimensional grid.
I would like to generate nested loops depending on any dimension (2D, 3D, 4D, etc...).
How can I do that in an elegant and fast way ? Below a simple illustration of my problem.
I am writing in C++ but I think this kind of question can be useful for other languages.
I need to know the indices (i,j,k...) in my do stuff part.
Edit : lower_bound and upper_bound represents the indexes in the grid so they are always positive.
#include <vector>
int main()
{
// Dimension here is 3D
std::vector<size_t> lower_bound({4,2,1});
std::vector<size_t> upper_bound({16,47,9});
for (size_t i = lower_bound[0]; i < upper_bound[0]; i ++)
for (size_t j = lower_bound[1]; j < upper_bound[1]; j ++)
for (size_t k = lower_bound[2]; k < upper_bound[2]; k ++)
// for (size_t l = lower_bound[3]; l < upper_bound[3]; l ++)
// ...
{
// Do stuff such as
grid({i,j,k}) = 2 * i + 3 *j - 4 * k;
// where grid size is the total number of vertices
}
}
Following may help:
bool increment(
std::vector<int>& v,
const std::vector<int>& lower,
const std::vector<int>& upper)
{
assert(v.size() == lower.size());
assert(v.size() == upper.size());
for (auto i = v.size(); i-- != 0; ) {
++v[i];
if (v[i] != upper[i]) {
return true;
}
v[i] = lower[i];
}
return false;
}
And use it that way:
int main() {
const std::vector<int> lower_bound({4,2,1});
const std::vector<int> upper_bound({6,7,4});
std::vector<int> current = lower_bound;
do {
std::copy(current.begin(), current.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while (increment(current, lower_bound, upper_bound));
}
Live demo
An iterative approach could look like this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> lower_bound({-4, -5, -6});
std::vector<int> upper_bound({ 6, 7, 4});
auto increase_counters = [&](std::vector<int> &c) {
for(std::size_t i = 0; i < c.size(); ++i) {
// This bit could be made to look prettier if the indices are counted the
// other way around. Not that it really matters.
int &ctr = c .rbegin()[i];
int top = upper_bound.rbegin()[i];
int bottom = lower_bound.rbegin()[i];
// count up the innermost counter
if(ctr + 1 < top) {
++ctr;
return;
}
// if it flows over the upper bound, wrap around and continue with
// the next.
ctr = bottom;
}
// end condition. If we end up here, loop's over.
c = upper_bound;
};
for(std::vector<int> counters = lower_bound; counters != upper_bound; increase_counters(counters)) {
for(int i : counters) {
std::cout << i << ", ";
}
std::cout << "\n";
}
}
...although whether this or a recursive approach is more elegant rather depends on the use case.
#include <iostream>
#include <vector>
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f)
{
std::vector<int> temp;
process(lower, upper, f, 0, temp);
}
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f,
int index, std::vector<int>& current)
{
if (index == lower.size())
{
f(current);
return;
}
for (int i = lower[index]; i < upper[index]; ++i)
{
current.push_back(i);
process(lower, upper, f, index + 1, current);
current.pop_back();
}
}
int main()
{
// Dimension here is 3D
std::vector<int> lower_bound({-4, -5, 6});
std::vector<int> upper_bound({6, 7, 4});
// Replace the lambda below with whatever code you want to process
// the resulting permutations.
process(lower_bound, upper_bound, [](const std::vector<int>& values)
{
for (std::vector<int>::const_iterator it = values.begin(); it != values.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
});
}
Probably some typos an whatnot, but I'd flatten the whole range.
This is based on the idea that the range can be described as
x_0 + d_0*(x_1+d_1*(x_2+d_2....)
So we can roll our own that way
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
//ranges
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
}
Edit: to be more generic:
template <typename D>
void multi_for(const std::vector<int>& lower_bound, const std::vector<int> upper_bound, D d) {
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
size_t numel = std::accumulate(ranges.begin(), ranges.end(), std::multiplies<int,int>{});
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
d(idx,indexes);
}
}
//main
size_t* grid;//initialize to whateer
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
auto do_stuff = [grid](size_t idx, const std::vector<int> indexes) {
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
};
multi_for(lower_bound,upper_bound,do_stuff);
A recursive function may help you achieve what you want.
void Recursive( int comp )
{
if(comp == dimension)
{
// Do stuff
}
else
{
for (int e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
Some additions may be necessary in the function signature if you need to know the current indices (i,j,k,...) in your "Do Stuff" section.
This is a clean way to have access to these indices
void Recursive( int comp, int dimension )
{
static std::vector<int> indices;
if( comp == 0 ) // initialize indices
{
indices.clear();
indices.resize(dimension, 0);
}
if(comp == dimension -1)
{
// Do stuff
}
else
{
int& e = indices[comp];
for (e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
This is however not usable along multiple threads, due to the shared static vector.