Reputation: 98
For example, you are given an integer n(at compile time). Your task is to creat n nested loops with distinct loop control variables(array[0],array[1]. i,j,k...) and under the scope of all loops, execute statements like :cout<<"Hello, World"<<endl
and make the possibility to use all loop control variables(So that logic using loop control variables can be designed).Along with n, other informations like initial value and condition for i'th(0 to n) loop control variable could be provided.Our objective should be to make the process flexible and generic. Is it possible in C or C++ or Java or ....(Popular Programming Languages) ?
A C++ code for n = 3 could be :
for(int i = 0; i<n; i++)
{
for(int j = 0; j<n; j++)
{
for(int k = 0; k<i+j; k++)
{
cout<<i*j+k<<endl;
}
}
}
For n=4, it could be
for(int i = 0; i<n; i++)
{
for(int j = 0; j<n; j++)
{
for(int k = 0; k<i+j; k++)
{
for(int l = 0; l<k+3; l++)
{
cout<<i*j+k-l<<endl;
}
}
}
}
Upvotes: 1
Views: 972
Reputation: 11181
One way to do it would be to have a function template that takes a function (innermost loop body) and some bounds:
// Single loop, end of recursion
template<class Function>
void nested_loop( Function && f, std::size_t k)
{
for ( std::size_t i = 0; i < k; ++i )
f(i);
}
// General case, Bounds is expected to be convertible to std::size_t.
template<class Function, class ... Bounds>
void nested_loop( Function && f, std::size_t k, Bounds && ... bounds)
{
for ( std::size_t i = 0;i < k; ++i )
{
// The lambda expression here binds 'i' to the first argument
// of f.
nested_loop(
[f = std::forward<Function>(f), i](auto && ... args)
{
return f(i, args ...);
},
bounds ... );
}
}
Which can be used like this:
nested_loop(
[](int i, int j) { cout << i << ", " << j << endl; },
2,4 );
This can be trivially extended to support loop bounds that depend on the iteration variable of the outer loops. To do so, you need to require Bounds
to be a callable, and bind the iteration variable to its first argument at every step.
Upvotes: 0
Reputation: 303
c++ +11 Have bounded for each loop ( If you intent to use the mentioned looping with arrays )
#include <iostream>
int main()
{
int fibonacci[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
for (int number : fibonacci) // iterate over array fibonacci
std::cout << number << ' '; // we access the array element for this iteration through variable number
return 0;
}
Upvotes: 0
Reputation: 217245
For fixed bound, you may do
bool increase(const std::vector<std::size_t>& v, std::vector<std::size_t>& it)
{
for (std::size_t i = 0, size = it.size(); i != size; ++i) {
const std::size_t index = size - 1 - i;
++it[index];
if (it[index] > v[index]) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
void iterate(const std::vector<std::size_t>& v)
{
std::vector<std::size_t> it(v.size(), 0);
do {
do_job(it);
} while (increase(v, it));
}
For dependent bound, you may adapt it to:
bool increase(const std::vector<std::function<std::size_t()>>& v,
std::vector<std::size_t>& it)
{
for (std::size_t i = 0, size = it.size(); i != size; ++i) {
const std::size_t index = size - 1 - i;
++it[index];
if (it[index] > v[index]()) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
void iterate(std::vector<std::size_t>& it,
const std::vector<std::function<std::size_t()>>& v)
{
do {
do_job(it);
} while (increase(v, it));
}
with usage similar to:
std::vector<std::size_t> its(3, 0);
std::vector<std::function<std::size_t()>> bounds = {
[]{ return 2; },
[]{ return 3; },
[&its]{ return its[0] + its[1]; },
};
iterate(its, bounds);
Upvotes: 0
Reputation: 28828
Variable nested loops can be implemented similar to an odometer. You have an array of counters and an array of end values if the end values are not the same for all counters. For each loop, the least significant counter is incremented, and when it reaches its end value, it is reset to a starting count, and the next least significant counter is incremented, checked to see if it's reached it's end value and so on.
Upvotes: 2
Reputation: 159
How about something like this? Not the prettiest, but should do the job of creating n layers of loops where n can be defined at run time. (c++, but works with all your languages if you replace the std::vector)
void func(const std::vector<int*>& controlVars, int remainingLayers) {
int i = 0;
controlVars.push_back(&i);
for (; i < n; ++i) {
if (remainingLayers == 0) {
// Read control var vector and do something
}
else {
func(controlVars, remainingLayers - 1);
}
}
controlVars.pop_back();
}
Upvotes: 0
Reputation: 48948
This is a use-case for recursion:
void loop(int n, int count = -1) {
if (count == -1) //Could be helper function too
count = n;
else if (count == 1) { //Last loop contains logic
for (int i = 0; i < n; ++i)
std::cout << "Hello World!\n"; //To have access to the loop variables,
//make a std::vector
return; //Stop
}
for (int i = 0; i < n; ++i)
loops(n, count - 1);
}
You can then call it using:
loop(3); //3 Nested for loops
loop(4); //4 Nested for loops
You could also make loop
more generic by passing a function pointer to the function that has to get executed.
Upvotes: 0