一尘不染

使用密钥的可逆随机播放算法

algorithm

我该如何在C#中编写可逆的随机播放算法,该算法使用密钥进行随机播放并可以恢复为原始状态?

例如,我有一个字符串:“ Hello world”,如何对其进行混洗,以便以后可以将经过混洗的字符串反向转换为“ Hello world”。


阅读 227

收藏
2020-07-28

共1个答案

一尘不染

查看费舍尔-耶茨Fisher-
Yates)随机播放
,以了解一种根据密钥对字符串进行置换的方法。将密钥作为种子输入PRNG,使用该密钥生成随机播放的随机数。

现在,如何逆转该过程?Fisher-Yates通过交换某些元素对来工作。因此,要反转该过程,您可以将相同的键输入到相同的PRNG中,然后通过Fisher-
Yates算法运行,就 好像 您要对字符串大小的数组进行改组一样。但是实际上您什么也没动,只需记录将在每个阶段交换的元素的索引即可。

完成此操作后,请 按相反顺序浏览 交换列表,并将其应用于混洗后的字符串。结果是原始字符串。

因此,举例来说,假设我们使用以下交换对字符串“
hello”进行了混洗(我在这里没有使用PRNG,我掷骰子,但是关于PRNG的要点是,给定相同的数字序列种子):

(4,0): "hello" -> "oellh"
(3,3): "oellh" -> "oellh"
(2,1): "oellh" -> "olelh"
(1,0): "olelh" -> "loelh"

因此,改组后的字符串为“ loelh”。

为了进行混洗,我生成了相同系列的“随机”数字0、3、1、0。然后以相反的顺序应用交换:

(1,0): "loelh" -> "olelh"
(2,1): "olelh" -> "oellh"
(3,3): "oellh" -> "oellh"
(4,0): "oellh" -> "hello"

成功!

当然,这样做的缺点是,它为deshuffle使用了大量内存:与原始char数组一样长的索引数组。因此,对于真正的大型数组,您可能希望选择可以向前或向后步进而不需要存储所有输出的PRNG(或者无论如何是序列生成函数)。这排除了基于哈希的加密安全PRNG,但LFSR是可逆的。

顺便说一句,你为什么要这样做?

2020-07-28