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

How do I return both a processed list and a modified object?

提问人:Pierre Abbat 提问时间:7/3/2023 更新时间:7/3/2023 访问量:80

问:

我正在设计一个名为 Daphne 的密码,它采用一个明文字节并返回一个加密字节和一个修改后的 Daphne。当应用于列表时,它应该在处理完所有字节后返回加密字节列表和 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赞 David Fletcher 7/3/2023 #1

我完全不明白你为什么要引入序列,所以我 可能误解了问题。但似乎递归 该列表可以正常工作。类似的东西(未经测试)

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

其中任何一个都应该只需要恒定的内存,但有一个警告。 如果在使用加密列表之前检查最终的达芙妮,则 通过做的例子,它会 必须浏览整个列表才能先获得最终的达芙妮,同时 将整个加密列表保存在内存中以便能够使用它 下一个。首先打印加密列表,然后打印最终的达芙妮和 应该没问题。如果你只检查它,它甚至可以在无限的列表中工作。print (listEncrypt something something)snd (listEncrypt something something)

评论

0赞 Pierre Abbat 7/4/2023
Daphne 已经使用序列作为移位寄存器,因此使用序列不会添加新库。我马上就要出去购物了,但今晚会尝试一下。