简化C ++ For Loop

时间:2015-12-02 09:50:21

标签: c++ arrays for-loop cartesian-product

目前我有以下代码:

for(int i = 0; i < 4; i++){
    cout << rowNo[i] << endl;
}

for(int i = 0; i < 4; i++){
    for(int j = 0; j < 4; j++){
        cout << rowNo[i] << '.';
        cout << rowNo[j] << endl;
    }
}

for(int i = 0; i < 4; i++){
    for(int j = 0; j < 4; j++){
        for(int k = 0; k < 4; k++){
            cout << rowNo[i] << '.';
            cout << rowNo[j] << '.';
            cout << rowNo[k] << endl;
        }
    }
}

for(int i = 0; i < 4; i++){
    for(int j = 0; j < 4; j++){
        for(int k = 0; k < 4; k++){
            for(int l = 0; l < 4; l++){
                cout << rowNo[i] << '.';
                cout << rowNo[j] << '.';
                cout << rowNo[k] << '.';
                cout << rowNo[l] << endl;
            }
        }
    }
}

其中rowNo []是数组{1,2,3,4}

我想知道两件事:

  1. 这可以简化,所以可能会进入某种递归循环吗?
  2. 然后,这可以用于大小为N?
  3. 的数组

4 个答案:

答案 0 :(得分:3)

您正在寻找Cartesian_product

使用

bool increment(std::vector<std::size_t>& v, std::size_t maxSize)
{
    for (auto it = v.rbegin(); it != v.rend(); ++it) {
        ++*it;
        if (*it != maxSize) {
            return true;
        }
        *it = 0;
    }
    return false;
}

然后你可以这样做:

void print_cartesian_product(const std::vector<int>&v, int n)
{
    std::vector<std::size_t> indexes(n);

    do {
        print(v, indexes);
    } while (increment(indexes, v.size()));

}

Demo

答案 1 :(得分:1)

我想到的第一个解决方案就是在每个循环中放入缓冲区并最终打印所有缓冲区。 我认为还有其他一些巧妙的方法

for(int i = 0; i < 4; i++){
        put in buffer1 rowNo[i]
        for(int j = 0; j < 4; j++){
            put in buffer2 rowNo[i],rowNo[j]
            for(int k = 0; k < 4; k++){
                 put in buffer3 rowNo[i],rowNo[j],rowNo[k]
                for(int l = 0; l < 4; l++){
                    put in buffer4 rowNo[i],rowNo[j],rowNo[k],rowNo[l],endl.
                }
            }
        }
    }
     print(buffer1);
     print(buffer2);
     print(buffer3);
     print(buffer4);

答案 2 :(得分:1)

您实际上是在尝试使用数字{1,2,3,4}打印在base4中编码的数字。要实现它,您只需要定义一个递增1的函数。我建议在打印和基数的数量方面的通用解决方案。 和其他人一样,我使用数字表示"empty digit",我使用零,这非常方便。

完整的源代码:

#include <iostream>
#include <vector>

bool increment_basep(std::vector<int>& number, int p)
{ 
    int i = 0; 
    while(i < number.size() && number[i] == p)
    { 
       number[i] = 1;
       ++i;
    }
    if(i >= number.size())
        return false;

    ++number[i];
    return true;
}

void print_vect(std::vector<int>& number)
{
   for(int i = number.size() -1 ; i >= 0; --i)
   {
       if(number[i] != 0)
          std::cout << number[i];
   }
   std::cout << std::endl;
}

int main() {
    int n = 4;
    int p = 4;
    std::vector<int> num4(n);
    std::fill(num4.begin(), num4.end(), 0);

    while(increment_basep(num4, p))
    {
        print_vect(num4);
    }
    return 0;
}

增量返回计算是否已溢出。当我们溢出时,我们知道我们需要停止。

答案 3 :(得分:0)

以下是我提出的最简单的代码。必须有更直接的方式来做到这一点......

它基本上引入了一个&#34;鬼&#34; index -1,对应于数字中的空位。循环条件中的三元运算符可以避免重复。

int main()
{
    int N = 4;
    int rowNo[4] = {1, 2, 3, 4};

    for (int i = -1; i < N; i++)
        for (int j = (i > -1 ? 0 : -1); j < N; j++)
            for (int k = (j > -1 ? 0 : -1); k < N; k++)
                for (int l = (k > -1 ? 0 : -1); l < N; l++)
                {
                    if (i > -1) std::cout << rowNo[i] << '.';
                    if (j > -1) std::cout << rowNo[j] << '.';
                    if (k > -1) std::cout << rowNo[k] << '.';
                    if (l > -1) std::cout << rowNo[l];
                    std::cout << std::endl;
                }
}

它当然可以推广到一个任意大小的数组,可能还有一些代码生成脚本。