嵌套循环:置换由向量表示的n维数组

时间:2017-01-20 22:19:02

标签: c++ arrays algorithm loops

我有一个n维数组T,其中每个维度的长度都相同L。此数组由1D向量v表示(可以看作T的“重新整形”版本,因此v的长度为L^n)。

以下示例显示了v如何根据T(其中n = 3L = 4)的索引编制索引:

enter image description here

(例如T(0,3,2) = v[14]

我想要做的是创建一个代表u维数组n的向量S,其中S是通过置换/旋转{{1}获得的1,即

任何T

T(i1,i2,...,in) = S(i2,i3,...,in,i1)

(当(i1,i2,...,in)是矩阵时,T对应于S)的转置。

更新:

以下代码可以更好地解释我的问题:

T

然而,在实践中,我认为直接使用矢量更好。因此,我会做这样的事情:

void permute(vector<double> &output, const vector<double> &v, int L)
{
    int n = log(v.size())/log(L);

    // Suppose that we have a function doing this
    narray T = get_narray_from_vector(v, L);

    // Get the permutation of T
    narray S(T.size());
    for(int i1 = 0; i1 < L; i1++){
        for(int i2 = 0; i2 < L; i2++){
            ...
            for(int in = 0; in < L; in++){
                S(i2,i3,...,in,i1) = T(i1,i2,...,in);
            }
        }
    }

    // get vector from narray
    output.resize(v.size());
    int idx = 0;   
    for(int i1 = 0; i1 < L; i1++){
        for(int i2 = 0; i2 < L; i2++){
            ...
            for(int in = 0; in < L; in++){
                output[idx] = S(i1,i2,...,in);
                idx++;
            }
        }
    }   
}

这里的难点是嵌套循环,因为void permute(vector<double> &output, const vector<double> &v, int L) { int n = log(v.size())/log(L); output.resize(v.size()); // Get the permutation for(int i1 = 0; i1 < L; i1++){ for(int i2 = 0; i2 < L; i2++){ ... for(int in = 0; in < L; in++){ output[i2*pow(L, n-1) + i3*pow(L, n-2) + ... + in*L + i1] = v[i1*pow(L, n-1) + i2*pow(L, n-2) + ... + i_{n-1}*L + in]; } } } } 是一个参数。

任何想法如何做到这一点? 预先感谢您的帮助!!

1 个答案:

答案 0 :(得分:1)

这是一个不需要n嵌套for循环的解决方案。

首先,我有一些旧代码可以将数字分解为基于L的数字系统。

std::vector<int>
num2base(const int value,
         const unsigned int base){

  // Represents an input int VALUE in a new BASE-based number system                                                                                                    
  // n = a0*b^0 + a1*b^1 + ...                                                                                                                                          

  std::vector<int> base_representation;
  unsigned int num_digs = (unsigned int) (floor(log(value)/log(base))+1);
  base_representation.resize(num_digs);

  for (unsigned int i_dig = 0; i_dig < num_digs; i_dig++){
    base_representation[i_dig] =
      ((value % (int) pow(base,i_dig+1)) - (value % (int) pow(base, i_dig))) /
      (int) pow(base, i_dig);
  }

  return base_representation;
}

换句话说,这是将单值索引idx转换为i1in n - 元组索引的方法。

idx = i1*L^0 + i2*L^1 + ... in*L^(n-1)

这是代码的另一种方式

int
base2num(const std::vector<int> base_representation,
         const unsigned int base){

  unsigned int digit_val = 1;

  int value = 0;

  for (unsigned int digit = 0; digit < base_representation.size(); digit++){
    value += base_representation[digit]*digit_val;
    digit_val *= base;
  }

  return value;
}

一旦你有std::vector<int>表示你的n - 元组索引,就很容易置换它。

void
permute_once(std::vector<int> &base_representation){

  std::vector<int>::iterator pbr = base_representation.begin();
  int tmp = *pbr;
  base_representation.erase(pbr);
  base_representation.push_back(tmp);

  return;
}

因此,要生成新的n - 维数组S

  1. 浏览idxS的每个索引S

  2. idxS转换为n - 元组(iS1iS2,...,iSn

  3. T及其n - 元组(iT1iT2,...,iTn)中找到相关条目

  4. 将其转换为单个索引idxT

  5. u[idxS] = v[idxT];