2015-05-17 14 views
9

Czy istnieje sposób, aby stworzyć dla pętle formularzaTworzenie N-zagnieżdżone dla pętle

for(int i = 0; i < 9; ++i) { 
    for(int j = 0; j < 9; ++i) { 
    //... 
     for(int k = 0; k < 9; ++k) { //N-th loop 

bez wiedząc N w czasie kompilacji. Idealnie próbuję wymyślić sposób na przechodzenie przez oddzielne elementy wektora cyfr, aby utworzyć każdą możliwą liczbę, jeśli pewna ilość cyfr zostanie zastąpiona różnymi cyframi.

+3

Możesz użyć N wywołań rekursywnych do funkcji zawierającej pętlę for. –

Odpowiedz

8

Można użyć rekurencji zamiast warunku podstawowego -

void doRecursion(int baseCondition){ 

    if(baseCondition==0) return; 

    //place your code here 

    doRecursion(baseCondition-1); 
} 

Teraz nie trzeba podać wartość baseCondition w czasie kompilacji. Możesz go podać, wywołując metodę doRecursion().

+0

Dlaczego istnieje różnica między innymi? Nie jestem pewien, jak to się uda. – Andrew

+0

@Andrew, Dzięki. Naprawiłem to. Właściwie na początku nie było tam komentarza (// umieść tutaj swój kod). Po dodaniu komentarza zapomniałem usunąć "else". – Razib

2

Można użyć rekurencyjne wywołanie jak:

void runNextNestedFor(std::vector<int> counters, int index) 
{ 
    for(counters[index] = 0; counters[index] < 9; ++counters[index]) { 
     // DO 
     if(index!=N) 
      runNextNestedFor(counters, index+1); 
    } 
} 

Nazwijmy to po raz pierwszy jako:

std::vectors<int> counters(N); 
runNextNestedFor(counters, 0); 
3

Można użyć funkcji rekurencyjnej:

void loop_function(/*params*/,int N){ 
for(int i=0;i<9;++i){ 
    if(N>0) loop_function(/*new params*/,N-1); 
} 

Wywoła to rekurencyjnie loop_function N razy, podczas gdy każda funkcja będzie iterować wywołanie loop_function

może być nieco trudniejsze, aby zaprogramować w ten sposób, ale należy robić to, co chcesz

+0

Kiedy próbuję uruchomić licznik int = 0; void loop_function (wektor i cyfry, int n) { \t int index = n-1; \t dla (cyfry [indeks] = 0, cyfry [indeks] <9; ++ cyfry [indeks]) \t { \t jeśli (n> 1) funkcja pętli (cyfry, n-1); \t wyświetlacz (cyfry); \t ++ licznik; \t} \t } Int główny() { \t wektor vec (3, 0); \t funkcja pętli (vec, vec.size()); \t cout << counter << endl; \t return 0; } Otrzymuję licznik = 819, ale z pewnością ma to być 999? – Andrew

+0

Ponieważ rozumiem twój kod, twoje cyfry wektorowe zmieniają się aż do wektora {9,9,9}, aby to zrobić, wykonujesz 9 * 9 * 9 iteracji na ostatnim elemencie (przechodzisz od 0 do 9 wewnątrz 2 pętli), dla drugiego robisz 9 * 9 iteracji, i dla ostatnich 9 kolejnych iteracji. Ostatecznie masz wektor cyfr do {9,9,9}, a żeby to osiągnąć, wykonujesz w sumie 9 * 9 * 9 + 9 * 9 + 9 = 819 iteracji, który jest licznikiem, który powiedziałeś – angrykoala

+0

Próbuję utworzyć każdy element od 1 do 999. Co muszę zmienić w kodzie? – Andrew

4

lubię coś takiego (tylko szkic):

struct multi_index 
{ 
    std::vector<int> min_ind; 
    std::vector<int> max_ind; 
    std::vector<int> ind; 
    bool _end = false; 

    multi_index(int N, int _max, int _min = 0) 
     : min_ind(N,_min) 
     , max_ind(N,_max) 
     , ind(N, _min) 
    {} 

    //possibly other constructors taking vectors for min_ind and max_ind 

    auto& operator++() 
    { 
     // increase first index i for which ind[i] < max_ind[i] 
     // set all indices j < i equal to min_ind[j] 
     // if no index found to increase, set end = true 
     return *this; 
    } 
    auto operator[](int i) const { return ind[i]; } 
    auto end() const { return _end; } 
    operator bool() const { return !_end; } 
}; 

Chodzi o to, aby wyraźnie skonstruować wektor trzyma N wskaźników i iterować nad nim.

Użyj go jako

int N=5; 
for(auto m=multi_index(N,9); !m.end(); ++m) 
{ 
    // now m[i] holds index of i-th loop 
} 

... i przedłużyć go w razie potrzeby.

+0

Jaki jest powód do trzymania w wektorach min_ind i max_ind? Czy nie byłoby łatwiej po prostu użyć int min_ind i int max_ind? – Andrew

+0

jeśli to ci wystarczy, rób to w ten sposób. Może się jednak zdarzyć, że pierwsza pętla przejdzie od 3 do 6, druga od 1 do 8 i tak dalej. – davidhigh

0

Zamierzam wziąć OP w wartości nominalnej na przykład podany kod i przyjąć, że to, o co się pytamy, jest rozwiązaniem, które liczy się poprzez arbitralny numer bazowy 10. (Opieram to na komentarzu "Idealnie próbuję znaleźć sposób na przechodzenie przez oddzielne elementy wektora cyfr, aby utworzyć każdą możliwą liczbę."

To rozwiązanie ma pętlę, która liczy się przez wektor cyfr podstawy 10 i przekazuje każde kolejne wartości do funkcji pomocnika (doThingWithNumber). do testów miało to pomocniczy prostu drukowanie numeru.

#include <iostream> 

using namespace std; 

void doThingWithNumber(const int* digits, int numDigits) 
{ 
    int i; 
    for (i = numDigits-1; i>=0; i--) 
     cout << digits[i]; 
    cout << endl; 
} 

void loopOverAllNumbers(int numDigits) 
{ 
    int* digits = new int [numDigits]; 
    int i; 
    for (i = 0; i< numDigits; i++) 
     digits[i] = 0; 

    int maxDigit = 0; 
    while (maxDigit < numDigits) { 
     doThingWithNumber(digits, numDigits); 
     for (i = 0; i < numDigits; i++) { 
      digits[i]++; 
      if (digits[i] < 10) 
       break; 
      digits[i] = 0; 
     } 
     if (i > maxDigit) 
      maxDigit = i; 
    } 
} 

int main() 
{ 
    loopOverAllNumbers(3); 
    return 0; 
} 
1

że trochę kodu C++ 11 realizuje N- zagnieżdżone dla mnie pętli.Tutaj jest główna część kodu, który może być używany jako pojedynczy import .hpp (nazwałem go nestedLoop.HPP):

#ifndef NESTEDLOOP_HPP 
#define NESTEDLOOP_HPP 
#include <vector> 

namespace nestedLoop{ 

    class nestedLoop { 
     public: 
      //Variables 
      std::vector<int> maxes; 
      std::vector<int> idxes; //The last element is used for boundary control 
      int N=0; 
      int nestLevel=0; 

      nestedLoop(); 
      nestedLoop(int,int); 
      nestedLoop(int,std::vector<int>); 

      void reset(int numberOfNests, int Max); 
      void reset(int numberOfNests, std::vector<int> theMaxes); 

      bool next(); 
      void jumpNest(int theNest); 

     private: 
      void clear(); 
    }; 

    //Initialisations 
    nestedLoop::nestedLoop(){} 

    nestedLoop::nestedLoop(int numberOfNests, int Max) { 
     reset(numberOfNests, Max); 
    } 

    nestedLoop::nestedLoop(int numberOfNests, std::vector<int> theMaxes) { 
     reset(numberOfNests, theMaxes); 
    } 

    void nestedLoop::clear(){ 
     maxes.clear(); 
     idxes.clear(); 
     N = 0; 
     nestLevel = 0; 
    } 

    //Reset the scene 
    void nestedLoop::reset(int numberOfNests, int Max){ 
     std::vector<int> theMaxes; 
     for(int i =0; i < numberOfNests; i++) theMaxes.push_back(Max); 
     reset(numberOfNests, theMaxes); 
    } 

    void nestedLoop::reset(int numberOfNests, std::vector<int> theMaxes){ 
     clear(); 
     N = numberOfNests; 

     maxes=theMaxes; 

     idxes.push_back(-1); 
     for(int i=1; i<N; i++) idxes.push_back(theMaxes[i]-1); 
    } 

    bool nestedLoop::next(){ 
     idxes[N-1]+=1; 

     for(int i=N-1; i>=0; i--){ 
      if(idxes[i]>=maxes[i]) { 
       idxes[i] = 0; 

       if(i){ //actually, if i > 0 is needed 
        idxes[i-1] += 1; 
       }else{ 
        return false; 
       } 
      }else{ 
       nestLevel = i; 
       break; 
      } 
     } 
     return true; 
    } 

    void nestedLoop::jumpNest(int theNest){ 
     for(int i = N-1; i>theNest; i--) { 
      idxes[i] = maxes[i]-1; 
     } 
    } 
} 
#endif // NESTEDLOOP_HPP 

Oto przykład z oczekiwanego wyjścia:

#include <iostream> 
#include "stlvecs.hpp" 
#include "nestedLoop.hpp" 

int main(){ 
    nestedLoop::nestedLoop looper; 
    std::vector<int> maxes = {2, 3, 2, 2}; 
    looper.reset(4,maxes); 
    int i = 0; 
    while(looper.next()){ 
     std::cout << "Indices: " << looper.idxes << ", Last nest incremented: " << looper.nestLevel << std::endl; 
     if(i == 5){ 
      std::cout << "...Jump Second Nest (index 1)..." << std::endl; 
      looper.jumpNest(1); 
     } 
     i++; 
    } 
} 

/* Expected output 
Indices: 4 0 0 0 0 , Last nest incremented: 0 
Indices: 4 0 0 0 1 , Last nest incremented: 3 
Indices: 4 0 0 1 0 , Last nest incremented: 2 
Indices: 4 0 0 1 1 , Last nest incremented: 3 
Indices: 4 0 1 0 0 , Last nest incremented: 1 
Indices: 4 0 1 0 1 , Last nest incremented: 3 
...Jump Second Nest (index 1)... 
Indices: 4 0 2 0 0 , Last nest incremented: 1 
Indices: 4 0 2 0 1 , Last nest incremented: 3 
Indices: 4 0 2 1 0 , Last nest incremented: 2 
Indices: 4 0 2 1 1 , Last nest incremented: 3 
Indices: 4 1 0 0 0 , Last nest incremented: 0 
Indices: 4 1 0 0 1 , Last nest incremented: 3 
Indices: 4 1 0 1 0 , Last nest incremented: 2 
Indices: 4 1 0 1 1 , Last nest incremented: 3 
Indices: 4 1 1 0 0 , Last nest incremented: 1 
Indices: 4 1 1 0 1 , Last nest incremented: 3 
Indices: 4 1 1 1 0 , Last nest incremented: 2 
Indices: 4 1 1 1 1 , Last nest incremented: 3 
Indices: 4 1 2 0 0 , Last nest incremented: 1 
Indices: 4 1 2 0 1 , Last nest incremented: 3 
Indices: 4 1 2 1 0 , Last nest incremented: 2 
Indices: 4 1 2 1 1 , Last nest incremented: 3 
*/ 
+0

Dobra odpowiedź! Plug-n-play dla mnie. –

0

używam tego rozwiązania:

unsigned int dim = 3; 
unsigned int top = 5; 
std::vector<unsigned int> m(dim, 0); 
for (unsigned int i = 0; i < pow(top,dim); i++) 
{ 
    // What you want to do comes here 
    //  | 
    //  | 
    //  v 
    // ----------------------------------- 
    for (unsigned int j = 0; j < dim; j++) 
    { 
     std::cout << m[j] << ","; 
    } 
    std::cout << std::endl; 
    // ----------------------------------- 

    // Increment m 
    if (i == pow(top, dim) - 1) break; 
    unsigned int index_to_increment = dim - 1; 
    while(m[index_to_increment] == (top-1)) { 
     m[index_to_increment] = 0; 
     index_to_increment -= 1; 
    } 
    m[index_to_increment] += 1; 
} 

Można z pewnością zoptymalizowana i dostosowana, ale działa całkiem dobrze i nie trzeba przekazywać parametrów do funkcji rekursywnej. Z oddzielną funkcją do zwiększania indeksu wielo-indeksowego:

typedef std::vector<unsigned int> ivec; 
void increment_multi_index(ivec &m, ivec const & upper_bounds) 
{ 
    unsigned int dim = m.size(); 
    unsigned int i = dim - 1; 
    while(m[i] == upper_bounds[i] - 1 && i>0) { 
     m[i] = 0; 
     i -= 1; 
    } 
    m[i] += 1; 
} 

int main() { 

    unsigned int dim = 3; 
    unsigned int top = 5; 
    ivec m(dim, 0); 
    ivec t(dim, top); 
    for (unsigned int i = 0; i < pow(top,dim); i++) 
    { 
     // What you want to do comes here 
     //  | 
     //  | 
     //  v 
     // ----------------------------------- 
     for (unsigned int j = 0; j < dim; j++) 
     { 
      std::cout << m[j] << ","; 
     } 
     std::cout << std::endl; 
     // ----------------------------------- 

     // Increment m 
     increment_multi_index(m, t); 
    } 

}