我该如何在C#中编写可逆的随机播放算法,该算法使用密钥进行随机播放并可以恢复为原始状态?
例如,我有一个字符串:“ Hello world”,如何对其进行混洗,以便以后可以将经过混洗的字符串反向转换为“ Hello world”。
查看费舍尔-耶茨(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是可逆的。
顺便说一句,你为什么要这样做?