2012-07-31 68 views
6

我有這些for循環。C++冷凝嵌套for循環

// output all possible combinations 
for (int i1 = 0; i1 <= 2; i1++) 
    { 
     for (int i2 = 0; i2 <= 2; i2++) 
      { 
       for (int i3 = 0; i3 <= 2; i3++) 
        { 
         for (int i4 = 0; i4 <= 2; i4++) 
          { 
           for (int i5 = 0; i5 <= 2; i5++) 
            { 
             for (int i6 = 0; i6 <= 2; i6++) 
              { 
               for (int i7 = 0; i7 <= 2; i7++) 
                { 
                 //output created words to outFile 
                 outFile 
                 << phoneLetters[n[0]][i1]<< phoneLetters[n[1]][i2] 
                 << phoneLetters[n[2]][i3]<< phoneLetters[n[3]][i4] 
                 << phoneLetters[n[4]][i5]<< phoneLetters[n[5]][i6] 
                 << phoneLetters[n[6]][i7] 
                 << " "; 

                 if (++count % 9 == 0) // form rows 
                  outFile << std::endl; 
                 } 
               } 
             } 
           } 
         } 
       } 
     } 

它看起來很糟糕,但我太過分了,知道從哪裏開始凝視它們。

有人可以給我一個或兩個指針,所以我可以使這個代碼有點整潔?

+13

哇...這是一件藝術品... – Mysticial 2012-07-31 19:55:38

+0

我想重寫這個,所以它使用盡可能少的循環 – frankV 2012-07-31 19:59:34

+3

這將是相當微不足道的轉換成遞歸函數,其中每個遞歸調用積累下一個值,並且當您有足夠的值時,打印該數字。或者,保留一個運行計數器,並將其轉換爲基數3(或計算其基數3分量)。 – 2012-07-31 20:01:08

回答

6

您正在索引0,1和2七個級別。這可能不是非常有效的,但這個怎麼樣:

int i1, i2, i3, i4, i5, i6, i7; 
int j; 

for (int i = 0; i < 2187; i++) 
{ 
    // 0 through 2186 represent all of the ternary numbers from 
    // 0000000 (base 3) to 2222222 (base 3). The following 
    // pulls out the ternary digits and places them into i1 
    // through i7. 

    j = i; 

    i1 = j/729; 
    j = j - (i1 * 729); 

    i2 = j/243; 
    j = j - (i2 * 243); 

    i3 = j/81; 
    j = j - (i3 * 81); 

    i4 = j/27; 
    j = j - (i4 * 27); 

    i5 = j/9; 
    j = j - (i5 * 9); 

    i6 = j/3; 
    j = j - (i6 * 3); 

    i7 = j; 

    // print your stuff 
} 

或者,基於評論user315052的建議:

int d[7]; 

for (int i = 0; i < 2187; i++) 
{ 
    int num = i; 
    for (int j = 6; j >= 0; j--) 
    { 
     d[j] = num % 3; 
     num = num/3; 
    } 

    // print your stuff using d[0] ... d[6]] 
} 
+0

相當整潔。 – Puppy 2012-07-31 20:21:35

+3

我會用'j%= X'來代替減法/乘法。如果你首先開始填充第七項,你可以通過使用3來使常量無效。如果將'i'切換到一個數組中,它將變成一個非常簡單的循環來計算mod作爲一個mod 3,div 3迭代。 – jxh 2012-07-31 20:23:56

+0

編輯我的答案,以反映user315052的建議。非常好的主意! – John 2012-07-31 20:37:12

2

在一般情況下,可以使用遞歸:

template <typename Stream, typename Iterator> 
void generateNumbers(Stream& stream, Iterator begin, Iterator end) { 
    if (end - begin == 7) { 
    for (Iterator p = begin; p < end; p++) { 
     stream << phoneLetters[n[*p]][*p]; 
    } 
    stream << " "; 
    } else { 
    for (*end = 0; *end <= 2; ++*end) 
     generateNumbers(stream,begin,end+1); 
    if (end - begin == 6) 
     stream << std::endl; 
    } 
} 

它可以通過使用一個緩衝器矢量或一個普通的舊的C陣列(既具有足夠的大小)調用。

例如:

std::vector<int> buf(7,0); 
generateNumbers(std::cout,buf.begin(),buf.begin()); 
// or 
int buf2[7]; 
generateNumbers(std::cout,buf2,buf2); 

但是,如果你的價值觀是二進制的,PBrando的回答是好。

2

我看到詹姆斯McNellis已經評論這個解決方案,但在這裏它是:

void phone_combo(int n[], int i[], int d, ostream &ofile, int &count) { 
    if (d == 7) { 
     //output created words to outFile 
     ofile 
     << phoneLetters[n[0]][i[0]]<< phoneLetters[n[1]][i[1]] 
     << phoneLetters[n[2]][i[2]]<< phoneLetters[n[3]][i[3]] 
     << phoneLetters[n[4]][i[4]]<< phoneLetters[n[5]][i[5]] 
     << phoneLetters[n[6]][i[6]] 
     << " "; 
     if (++count % 9 == 0) // form rows 
      ofile << std::endl; 
     } 
     return; 
    } 
    for (i[d] = 0; i[d] <= 2; i[d]++) { 
     phone_combo(n, i, d+1, ofile, count); 
    } 
} 

int i[7]; 
phone_combo(n, i, 0, outFile, count); 
0

之前發佈的一個響應將此減少爲單個for循環,但由於某種原因它被刪除。

for(int i(0); i!= 2187; ++i) 
{ 
    outFile 
    << phoneLetters[n[0]][(i >> 6) & 0x01]<< phoneLetters[n[1]][(i >> 5) & 0x01] 
    << phoneLetters[n[2]][(i >> 4) & 0x01]<< phoneLetters[n[3]][(i >> 3) & 0x01] 
    << phoneLetters[n[4]][(i >> 2) & 0x01]<< phoneLetters[n[5]][(i >> 1) & 0x01] 
    << phoneLetters[n[6]][i & 0x01] 
    << ' '; 

    if (++count % 9 == 0) // form rows 
     outFile << '\n'; 
} 

如果您知道計算每個可能的置換所需的迭代次數的確切次數,這隻會起作用。