2015-05-17 19 views
9

C'è un modo per creare in-loop di una formaCreazione N annidati per-loop

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

senza conoscere N al momento della compilazione. Idealmente sto cercando di capire un modo per passare da elementi separati di un vettore di cifre per creare ogni numero possibile se una certa quantità di cifre viene sostituita con cifre diverse.

+3

È possibile utilizzare N chiamate ricorsive a una funzione che contiene un ciclo for. –

risposta

8

È possibile utilizzare la ricorsione invece con una condizione di base -

void doRecursion(int baseCondition){ 

    if(baseCondition==0) return; 

    //place your code here 

    doRecursion(baseCondition-1); 
} 

Ora non c'è bisogno di fornire il valore baseCondition in fase di compilazione. È possibile fornirlo chiamando il metodo doRecursion().

+0

Perché c'è un divario tra se altro? Non sono sicuro di come possa funzionare – Andrew

+0

@Andrew, grazie. L'ho risolto In realtà all'inizio non c'era il commento (// posiziona il tuo codice qui) lì. Dopo aver aggiunto il commento, ho dimenticato di rimuovere 'else'. – Razib

2

È possibile utilizzare chiamata ricorsiva come:

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

chiamarlo prima volta come:

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

Si potrebbe utilizzare una funzione ricorsiva:

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

Ciò richiederà in modo ricorsivo a loop_function N volte, mentre ogni funzione itererà chiamando loop_function

Può essere un po 'più difficile da programmare in questo modo, ma dovrebbe fare quello che vuoi

+0

Quando provo eseguire int counter = 0; void loop_function (vector & digits, int n) { \t int index = n-1; \t per (cifre [indice] = 0; cifre [indice] <9; ++ cifre [index]) \t { \t se (n> 1) loop_function (cifre, n-1); \t display (cifre); \t ++ contatore; \t} \t } int main() { \t vettoriale vec (3, 0); \t loop_function (vec, vec.size()); \t cout << contatore << endl; \t ritorno 0; } Ottengo contatore = 819, ma sicuramente è pensato per essere 999? – Andrew

+0

Come ho capito il tuo codice, le cifre dei tuoi vettori cambiano finché il vettore è {9,9,9}, per fare ciò, esegui iterazioni 9 * 9 * 9 sull'ultimo elemento (vai da 0 a 9 all'interno di 2 loop), per il secondo fai 9 iterazioni 9 * e per le ultime 9 altre iterazioni. Quindi, finalmente, il vettore delle cifre è {9,9,9}, e per ottenere ciò, esegui un totale di 9 * 9 * 9 + 9 * 9 + 9 = 819 iterazioni, che è il contatore che hai detto – angrykoala

+0

Sto cercando di creare ogni elemento da 1 a 999. Cosa devo cambiare nel codice? – Andrew

4

mi piace qualcosa di simile (solo uno schizzo):

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

L'idea è quella di costruire in modo esplicito un vector holding N indici e iterare su di esso.

usarlo come

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

... e si estendono in base alle esigenze.

+0

Qual è il motivo per contenere min_ind e max_ind nei vettori? Non sarebbe più semplice usare int min_ind e int max_ind? – Andrew

+0

se questo è sufficiente per te, fallo così. Potrebbe tuttavia essere che il primo ciclo passerà da 3 a 6, il secondo da 1 a 8 e così via. – davidhigh

0

Ho intenzione di prendere l'OP al valore nominale sul codice di esempio che è stato dato, e suppongo che ciò che viene chiesto è una soluzione che conta attraverso un numero arbitrario di base-10. (Baso questo sul commento "Idealmente sto cercando di capire un modo per passare da elementi separati di un vettore di cifre per creare ogni numero possibile."

Questa soluzione ha un ciclo che conta attraverso un vettore di cifre in base 10, e passa ciascun valore successivo in una funzione di supporto (doThingWithNumber). Per gli scopi di prova avevo questo helper semplicemente stampare il numero.

#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

ho scritto qualche codice C++ 11 attuazione di un N- nested for-loop per me stesso. Ecco la parte principale del codice che può essere utilizzata come singola importazione .hpp (l'ho chiamata 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 

Ecco un esempio con risultati attesi:

#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

Buona risposta! Plug-n-play per me. –

0

utilizzo questa soluzione:

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

Si può certamente ottimizzato e adattato, ma funziona abbastanza bene e non è necessario passare i parametri a una funzione ricorsiva. Con una funzione separata per incrementare il multiindice:

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

}