java - Transposition Cipher Enumeration

时间:2017-12-14 17:12:22

标签: java encryption cryptography

注意:我之前删除了此帖子,因为我找到了以下post,但我不确定如何将其应用于我的问题。

我正在使用转置密码解码器。我已经解决了静态列的问题(1,2,3,4按顺序保存),但是我不知道如何创建一个长度的每个可能排列的数组(作为参数给出),I了解最简单的方法是某种递归方法,但在尝试这种方法时,我一直迷失在这种努力中。 (我整天都在编码而且很累)

示例数组将包含:

1,2,3,4,5,6
2,1,3,4,5,6
2,3,1,4,5,6
...

2 个答案:

答案 0 :(得分:0)

经过一段时间的困惑,并尝试了一些不同的事情,我的一个朋友(这里不是用户)给了我以下的java解决方案:

if

答案 1 :(得分:0)

回想一下n!项的n个排列。 n!可以通过以下方式轻松理解:

1.   There are `n` options for choosing the first item.
2.   There are `n-1` items remaining from which to choose the second item
...
n-1. There are `2` options left for the `n-1`-th item.
n.   There is only 1 item left for the `n`-th position.

因此,如何订购商品总共有(n) * (n-1) * (n-2) * ... (2) * (1) = n!个选项。

这直接揭示了使用混合基数编号方案枚举排列的方法。在此方案中,最重要的数字将为基数n,下一个最重要的数字将为基数n-1等。

使用这样的混合基数以下列方式选择排列:

  1. 使用最高有效数字从数组中选择一个元素(请注意,第一个数字的范围为[0, n-1],并且有n个元素可供选择,因此您可以将其用作索引要选择的项目。)
  2. 从数组中删除所选元素,记录它是置换数组的第一个元素,并将其余元素压缩到数组的前面。
  3. 使用第二位有效数字从剩余项目中选择一个元素(请注意,此数字的值范围为[0, n-2],并且还有n-1个数字)
  4. 删除所选元素,将其记录为置换数组中的第二个元素
  5. 重复,直到选中所有项目。
  6. 如果我们使用数组来表示little-endian数字顺序的混合基数,那么我们将得到以下结果:

    int mixed_radix[n] = {0};
    

    您可以通过以下方式递增此混合基数:

    //Increment the least-significant digit
    mixed_radix[0]++;
    
    //Ripple overflow toward the most-significant digit
    for(i=0; i<n; i++) {
      if(mixed_radix[i] > i) {
        mixed_radix[i] = 0;
        if(i < n-1)mixed_radix[i+1]++;
      }
      else {
        break;
      }
    }
    

    因此我们有办法将混合基数编号初始化为零,然后将其递增到每个可能的值,一旦它回绕到零就停止。 (或n!-1递增后......)

    所有这一切,有一个可爱的数字技巧可以使这更简单:你可以通过以下方式从整数解压缩那个丑陋的混合基数:

    我们知道n!个项目有n个排列;对于val范围内的任何整数[0, n!-1],下面提供了整数值和混合基数之间的双射映射:

    int working = val;  //val in the range [0, n!-1]
    for(j=0 j<n; j++) {
      mixed_radix[j] = working % (j+1);
      working /= (j+1);
    }
    

    所以嵌入这个&#34;拆包&#34;在val0范围内运行n!-1的外循环内循环是一个更密集的方法来枚举混合基数(枚举可能的排列)。它还为每个排列分配一个整数,有效地命名它们。 :)