Tavij
Tavij

Reputation: 98

Is it possible to execute n number of nested "loops(any)"(with distinct loop control variables) where n is given?

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

Answers (6)

sbabbi
sbabbi

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

Thinkal VB
Thinkal VB

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

Jarod42
Jarod42

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));
}

Demo

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);

Demo

Upvotes: 0

rcgldr
rcgldr

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

redpandamonium
redpandamonium

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

Rakete1111
Rakete1111

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

Related Questions