如何以n位数组的方式生成所有n位数?

时间:2015-09-25 00:36:35

标签: c++ algorithm

我知道如何以传统的数字方式生成所有的n位数字,

    mainAdapter = new ParseQueryAdapter<Meal>(this, Meal.class);
    mainAdapter.setTextKey("title");
    mainAdapter.setImageKey("photo");

    // Subclass of ParseQueryAdapter
    favoritesAdapter = new FavoriteMealAdapter(this);

    // Default view is all meals
    setListAdapter(mainAdapter);

例如,

for(long long number = pow(10, n-1); number < pow(10, n); number++) {
    cout << number << endl; 
}

但是,由于我必须评估每个数字的数字,因此首先以数字数组格式构造数字会非常方便。

例如,以下代码以数组方式生成所有5位数字:

for n = 5, it will generate 10000 to 99999;

现在的问题是:n未知。 (例如,它可能是2,3,4,5,6 ......,10) 那么如何根据数字n?

生成n位数组

例如,我想要一段代码,如下所示(任何比这更好的方法都受到高度赞赏):

for(int i = 1; i < 9; i++)
    for(int j = 0; j < 9; j++)
        for(int k = 0; k < 9; k++)
            for(int l = 0; l < 9; l++)
                for(int m = 0; m < 9; m++) {
                    //executed 9 * 10^4 = 90000 times
                    //construct my array instance with i, j, k, l, m
                    cout << i << j << k << l << m << endl;      
                }

4 个答案:

答案 0 :(得分:3)

没有理由将自己限制在该数字的每个数字的0 - 9范围内 对于每个数字位置,我们将代表一个范围:

std::pair<int,int> range;

示例中的每个循环都是从范围的开头到范围的结尾迭代 所有的循环都只是一系列的范围;每个嵌套循环负责生成数字的下一个数字。

我们可以通过以下方式表示:

std::vector<std::pair<int, int>> ranges;

如果您考虑嵌套for loops的工作方式,可以使用两个指针在向量上模拟相同的功能。我已经完成了这项工作并将功能包装在一个类中:

//header
class Range_Combinator {

public:

  Range_Combinator(std::vector<std::pair<int, int>> const &ranges_in);
  std::vector<int> Next();
  std::vector<int> Current();
  bool Done();

private:

  bool Adjust();
  void Reset_From_Current_Back(int from);

  std::vector<std::pair<int, int>> ranges;
  int current;
  int last;
  bool all_exausted;
  std::vector<int> current_vals;
};
//source
Range_Combinator::Range_Combinator(
    std::vector<std::pair<int, int>> const &ranges_in) {

  ranges = ranges_in;
  last = ranges.size() - 1;
  current = last;
  all_exausted = false;

  for (auto it : ranges) {
    current_vals.push_back(it.first);
  }
}

std::vector<int> Range_Combinator::Next() {
  all_exausted = Adjust();
  return current_vals;
}
std::vector<int> Range_Combinator::Current() { return current_vals; }

bool Range_Combinator::Done() { return all_exausted; }

bool Range_Combinator::Adjust() {
  if (current_vals[current] < ranges[current].second) {
    current_vals[current]++;
  } else {

    while (current_vals[current] == ranges[current].second) {
      current--;
    }

    if (current < 0) {
      return true;
    }

    Reset_From_Current_Back(current + 1);
    current_vals[current]++;
    current = last;
  }
  return false;
}

void Range_Combinator::Reset_From_Current_Back(int from) {

  for (int i = from; i <= last; ++i) {
    current_vals[i] = ranges[i].first;
  }
}

这就是你如何使用它:

//create range combinator
std::vector<std::pair<int,int>> ranges{{1,2},{3,4}};
Range_Combinator r(ranges);

//print each number
auto number = r.Current();
while (!r.Done()){
    for (auto it: number) std::cout << it; std::cout << '\n';
    number = r.Next();
}

//prints: 13
//        14
//        23
//        24

答案 1 :(得分:2)

我不知道你为什么需要这个,但你可以试试这个:

size_t n = ; //whatever value

unsigned char* x = new unsigned char[n]();
x[0] = 1;   //make it n-digit 10000...000
do
{
    //process digits here

    ++x[n - 1];
    for (size_t i = n; i > 1; --i)
    {
        if (x[i - 1] == 10)
        {
            x[i - 1] = 0;
            ++x[i - 2];
        }
    }
} while (x[0] < 10);

delete [] x;

您甚至可以处理不是十进制数字,只需将硬编码的10替换为适当的数字。

答案 2 :(得分:0)

一种不考虑效率的简单方法:

#include <cstdio>

int main(void) {
    int n = 3; // the number of digits
    long long start = 1;
    int *array = new int[n];
    for (int i = 1; i < n; i++) start *= 10;
    for(long long x = start; x < start * 10; x++) { // not all 10-digit number will fit in 32-bit integer
        // get each digits in decimal, lowest digit in array[0]
        for (int i = 0, shift = 1; i < n; i++, shift *= 10) array[i] = (int)((x / shift) % 10);
        // do some work with it (print it here)
        for (int i = n - 1; i >= 0; i--) printf("%d", array[i]);
        putchar('\n');
    }
    delete[] array;
    return 0;
}

答案 3 :(得分:0)

我想我可以为你写出整件事,但这并不好玩。相反,我将概述基本方法,你可以填写空白来自己完成答案。

考虑以这种方式表示的n位长号:

 struct digit {
    struct digit *next;
    int n;    /* Digit 0-9 */
 };

以这种方式表示的单个数字可以这样打印出来:

void print_digit(struct digit *p)
{
    while (p)
    {
        std::cout << p->n;
        p=p->next;
    }
    std::cout << std::endl;
}

现在,让我们创建一个递归循环,迭代所有可能的n位数字:

void iterate(int ndigits)
{
    for (int i=0; i<10; ++i)
    {
        if (ndigits > 1)
        {
            iterate(ndigits-1);
        }
        else
        {   // This is the last digit

            // Here be dragons
        }
    }
}

经过一番思考后,您可以看到,例如,如果您调用iterate(4),那么当“听到龙”部分被执行时,这将在一个四深嵌套迭代堆栈中。将有四个深度for循环,彼此嵌套。并且,使用iterate(6),将会有六个,依此类推。

现在,考虑一下这样一个事实:基于struct digit的n位数字表示也是一种堆栈。

因此,这里的作业分配是使用这种递归迭代来动态构建这个链表,在堆栈上,“here be dragons”部分简单地调用print_digit() in打印每个号码。

提示:iterate()需要更多参数,在初始调用iterate()时,它将适当地使用,并具有一定的预设值。