haskell 如何返回已处理的列表和已修改的对象?

q7solyqu  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(132)

我在设计一个密码叫达芙妮它接受一个字节的明文返回一个加密的字节和一个修改过的达芙妮当应用于列表时,它应该返回加密字节的列表和处理完所有字节后的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。它还没有准备好生产;我还没破译过更别说别人了我可以通过它运行千兆字节的数据并计算统计数据。

mqkwyuun

mqkwyuun1#

我真的不明白你为什么要引入序列,所以我可能误解了这个问题。但似乎在列表上递归会很好。未经测试(Untested)

listEncrypt daph [] = (daph, [])
listEncrypt daph (b:bs) = (finalDaph, e:es)
  where
    (nextDaph, e) = byteEncrypt daph b
    (finalDaph, es) = listEncrypt nextDaph bs

字符串
实际上这个模式是一个mapAccumL。我认为byteEncrypt已经有了正确顺序的参数,所以它只是

listEncrypt = mapAccumL byteEncrypt


这两种方法都应该只需要常量内存,但有一点需要注意。如果在使用加密列表之前检查最后一个daphne,例如通过执行print (listEncrypt something something),它将不得不首先遍历整个列表以获得最后一个daphne,同时将整个加密列表保存在内存中以便能够使用下一个。先打印加密的列表,然后再打印最后的达芙妮,应该没问题。如果你只检查snd (listEncrypt something something),它甚至可以在无限列表上工作。

相关问题