2012-07-31 72 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'; 
} 

如果您知道计算每个可能的置换所需的迭代次数的确切次数,这只会起作用。