我在设计一个密码叫达芙妮它接受一个字节的明文返回一个加密的字节和一个修改过的达芙妮当应用于列表时,它应该返回加密字节的列表和处理完所有字节后的Daphne。我不知道如何在不占用O(n)内存的情况下做到这一点。代码如下:
byteEncrypt :: Daphne -> Word8 -> (Daphne,Word8)
byteEncrypt (Daphne key sreg acc) plain = ((Daphne key newsreg newacc),crypt) where
left = computeLeft key sreg acc
right = computeRight key sreg acc
crypt = step plain left right
newacc = acc+plain
newsreg = Seq.drop 1 (sreg |> crypt)
byteDecrypt :: Daphne -> Word8 -> (Daphne,Word8)
byteDecrypt (Daphne key sreg acc) crypt = ((Daphne key newsreg newacc),plain) where
left = computeLeft key sreg acc
right = computeRight key sreg acc
plain = invStep crypt left right
newacc = acc+plain
newsreg = Seq.drop 1 (sreg |> crypt)
seqEncrypt :: Seq.Seq Word8 -> (Daphne,Seq.Seq Word8) -> (Daphne,Seq.Seq Word8)
seqEncrypt Seq.Empty a = a
seqEncrypt (bs:|>b) (daph,acc) = (daph2,acc2) where
(daph1,acc1) = seqEncrypt bs (daph,acc)
(daph2,c) = byteEncrypt daph1 b
acc2 = acc1 |> c
listEncrypt :: Daphne -> [Word8] -> (Daphne,[Word8])
listEncrypt daph bs = (daph1,toList seq1) where
(daph1,seq1) = seqEncrypt (Seq.fromList bs) (daph,Seq.Empty)
seqDecrypt :: Seq.Seq Word8 -> (Daphne,Seq.Seq Word8) -> (Daphne,Seq.Seq Word8)
seqDecrypt Seq.Empty a = a
seqDecrypt (bs:|>b) (daph,acc) = (daph2,acc2) where
(daph1,acc1) = seqDecrypt bs (daph,acc)
(daph2,c) = byteDecrypt daph1 b
acc2 = acc1 |> c
listDecrypt :: Daphne -> [Word8] -> (Daphne,[Word8])
listDecrypt daph bs = (daph1,toList seq1) where
(daph1,seq1) = seqDecrypt (Seq.fromList bs) (daph,Seq.Empty)
字符串listEncrypt
在RAM中有一个列表的副本作为序列,这占用了O(n)RAM,这应该是不必要的。
完整代码在https://github.com/phma/daphne。它还没有准备好生产;我还没破译过更别说别人了我可以通过它运行千兆字节的数据并计算统计数据。
1条答案
按热度按时间mqkwyuun1#
我真的不明白你为什么要引入序列,所以我可能误解了这个问题。但似乎在列表上递归会很好。未经测试(Untested)
字符串
实际上这个模式是一个mapAccumL。我认为byteEncrypt已经有了正确顺序的参数,所以它只是
型
这两种方法都应该只需要常量内存,但有一点需要注意。如果在使用加密列表之前检查最后一个daphne,例如通过执行
print (listEncrypt something something)
,它将不得不首先遍历整个列表以获得最后一个daphne,同时将整个加密列表保存在内存中以便能够使用下一个。先打印加密的列表,然后再打印最后的达芙妮,应该没问题。如果你只检查snd (listEncrypt something something)
,它甚至可以在无限列表上工作。