我正在寻找一个算法,用它可以从已经发生的洗牌过程中得到一个密钥。
假设我们有一个字符串“hello”,它被洗牌了:

"hello" -> "loelh"

现在我想从中得到一个键k,我可以用它来撤消洗牌。因此,如果我们使用k作为确定性洗牌算法(例如Fisher-Yates和shuffle"loelh"的输入参数,我们将恢复初始字符串"hello"
我的意思不是简单地使用同一个确定性洗牌算法来洗牌和去洗牌这是因为在我的例子中,第一个字符串不会真正被洗牌在古典意义上实际上会有两组数据(字节或位数组)刚刚给出,我们想从第一组到第二组,只得到一个之前导出的键。
我希望这是清楚的,我想实现什么,我会感谢所有的暗示或提出的解决方案。
当做,
梅里特
更新:
另一个尝试:
基本上,也可以称之为一组数据的确定性转换,例如字节数组,但我将坚持使用“hello”字符串示例。
假设我们有一个转换算法,其中transform(data, "unknown seed")是“hello”,而data是我们要找的unknown seed的结果是“loelh”我们正在寻找这个“未知的种子”,我们可以用来逆转这个过程在生成“未知种子”时,输入数据和结果都是已知的。
稍后,我想使用“未知种子”(应该已经知道了;-)再次获取原始字符串:因此这个transform应该再次导致transform("loelh", seed)
所以你也可以把它看作一种方程形式,比如"hello",我们试图找到未知的值(算符data*["unknown value"]=resultdata可以是任何类型的运算)。

最佳答案

洗牌只是创建一个给定序列的随机排列。典型的方法是像你指出的费舍尔·耶茨洗牌。问题是,shuffle程序基于一个种子生成多个随机数,除非实现随机数生成器,否则无法轻松反转随机数序列。
还有别的办法。如果你能直接生成一个序列的第n个置换呢也就是说,给定字符串“fast”,可以将前几个置换定义为:

0  Fast
1  Fats
2  Fsat
3  Fsta
... etc. for all 24 permutations

你需要这四个字符的随机排列。选择一个从0到23的随机数,然后调用函数来生成该置换。
如果你知道这个键,你可以调用另一个函数,再次传递那个键,让它把排列反转回原来的位置。
在他的fourth article中的series on permutations中,eric lippert演示了如何生成第n个置换,而不必生成它之前的所有置换。他没有展示如何逆转这个过程,但如果你了解发电机是如何工作的,那么这样做应该不难。值得花时间研究整个系列的文章。
如果您不知道密钥(即使用的随机数)是什么,那么导出获得原始订单所需的交换序列是昂贵的。
编辑
经过深思熟虑,如果给了原始序列和转换后的序列,就可能得到密钥。因为您知道每个符号移动了多远,所以应该能够导出密钥。考虑两个字母可能的排列:
0. ab  1. ba

现在,将字母b赋值为0,将字母a赋值为1什么排列数是ba?在字符串中找到a,向左交换,直到找到正确的位置,然后将交换次数乘以1。
那太容易了考虑下一个:
0. abc  1. acb  2. bac
3. cab  4. bca  5. cba

a现在是2,b是1,c是0。给定cab
swap a left one space. 1x2 = 2. Result is `acb`
swap b left one space. 1x1 = 1. Result is `abc`

所以cab是置换3。
这确实假设你的置换生成器以同样的方式对置换进行编号这也不是一种非常有效的做事方式。最坏的情况将需要n(n-1)/2交换。可以通过移动数组中的内容来优化交换,但这仍然是一个o(n^2)算法。其中n是序列的长度。100件甚至1000件都不可怕不过,那之后相当糟糕。

10-05 22:58