考虑数组a[i]
,i=0,1,...,g
,g
可以是任何给定数字,a[0]=1
。
for a[1]=a[0]+1 to 1 do
for a[2]=a[1]+1 to 3 do
for a[3]=a[2]+1 to 5 do
...
for a[g]=a[g-1]+1 to 2g-1 do
#print a[1],a[2],...a[g]#
问题在于,每当我们更改g
的值时,我们都需要修改代码,即上面的循环。这不是一个好的代码。
答案 0 :(得分:1)
递归是解决这个问题的一种方法(虽然我很乐意看到迭代解决方案)。
!!! 警告,未经测试的代码 !!!
template<typename A, unsigned int Size>
void recurse(A (&arr)[Size],int level, int g)
{
if (level > g)
{
// I am at the bottom level, do stuff here
return;
}
for (arr[level] = arr[level-1]+1; arr[level] < 2 * level -1; arr[level]++)
{
recurse(copy,level+1,g);
}
}
然后拨打recurse(arr,1,g);
答案 1 :(得分:1)
想象一下,您使用数字数组表示数字。例如,682将是[6,8,2]。
如果你想从0到999计算,你可以写:
for (int n[0] = 0; n[0] <= 9; ++n[0])
for (int n[1] = 0; n[1] <= 9; ++n[1])
for (int n[2] = 0; n[2] <= 9; ++n[2])
// Do something with three digit number n here
但是当你想要数到9999时,你需要一个额外的for循环。
相反,您使用向数字添加1的过程:增加最后一位数字,如果溢出移动到前一位数字,依此类推。当第一个数字溢出时,循环完成。这可以处理任意位数的数字。
您需要一个类似的过程来为循环变量“添加1”。
增加最后的“数字”,即a[g]
。如果它溢出(即超过2g-1
),则转到下一个最重要的“数字”(a[g-1]
)并重复。与使用数字执行此操作相比,轻微的复杂性是,当值溢出时,通过数组返回,然后您需要继续将溢出的数字重置为其新的基值(取决于左侧的值)。
以下C#代码实现了这两种方法,并将数组打印到控制台。
static void Print(int[] a, int n, ref int count)
{
++count;
Console.Write("{0} ", count);
for (int i = 0; i <= n; ++i)
{
Console.Write("{0} ", a[i]);
}
Console.WriteLine();
}
private static void InitialiseRight(int[] a, int startIndex, int g)
{
for (int i = startIndex; i <= g; ++i)
a[i] = a[i - 1] + 1;
}
static void Main(string[] args)
{
const int g = 5;
// Old method
int count = 0;
int[] a = new int[g + 1];
a[0] = 1;
for (a[1] = a[0] + 1; a[1] <= 2; ++a[1])
for (a[2] = a[1] + 1; a[2] <= 3; ++a[2])
for (a[3] = a[2] + 1; a[3] <= 5; ++a[3])
for (a[4] = a[3] + 1; a[4] <= 7; ++a[4])
for (a[5] = a[4] + 1; a[5] <= 9; ++a[5])
Print(a, g, ref count);
Console.WriteLine();
count = 0;
// New method
// Initialise array
a[0] = 1;
InitialiseRight(a, 1, g);
int index = g;
// Loop until all "digits" have overflowed
while (index != 0)
{
// Do processing here
Print(a, g, ref count);
// "Add one" to array
index = g;
bool carry = true;
while ((index > 0) && carry)
{
carry = false;
++a[index];
if (a[index] > 2 * index - 1)
{
--index;
carry = true;
}
}
// Re-initialise digits that overflowed.
if (index != g)
InitialiseRight(a, index + 1, g);
}
}
答案 2 :(得分:0)
我会说你首先不想要嵌套循环。相反,你只想调用一个合适的函数,取当前的嵌套级别,最大嵌套级别(即g
),循环的开始,以及作为参数的计算上下文需要的任何东西:
void process(int level, int g, int start, T& context) {
if (level != g) {
for (int a(start + 1), end(2 * level - 1); a < end; ++a) {
process(level + 1, g, a, context);
}
}
else {
computation goes here
}
}