【问题标题】:Having trouble encoding text with a vigenere cipher in Haskell在 Haskell 中使用 vigenere 密码编码文本时遇到问题
【发布时间】:2013-02-13 19:01:24
【问题描述】:

我正在从事一个编码项目,我们需要在 Haskell 中编写一个 vigenere cypher。我花了几个小时并没有取得什么进展,但我被困在一个特定的部分。到目前为止,这是我的代码:

--Program: VigCipher.hs
--Author: Mouse

import Data.Char
import Text.Printf

--Changes letters to their numerical value
let2int   :: Char -> Int
let2int c = ord c - ord 'a'

--Changes numerical values to letters
int2let   :: Int -> Char
int2let n = chr (ord 'a' + n)

--Shift letter by n mod 26 places
shift :: Int -> Char -> Char
shift n c | isLower c = int2let ((let2int c + n) `mod` 26)
      | otherwise = c

--Encoding function
encode         :: String -> String -> [Char]
encode key msg = [shift (26 - let2int (key !! a) | a <- as) (msg !! a) | x <- zip (cycle key)msg]

我的问题出在 Encoding 函数中:我希望该函数在键和应该编码的消息的每个索引处检查和更改字符。我的印象是我所拥有的应该可以工作,但是当我运行它时,由于 |在:(键!!a)|一个

【问题讨论】:

  • 如果您包含错误可能会有所帮助

标签: haskell encryption vigenere


【解决方案1】:

语法是

[element | bindings, guards]

你的语法错误是这样的

  • 有两个| 标志
  • 第一个 | 出现在元素部分完成之前(计算括号)

所以试试

encode key msg = [shift (26 - let2int (key !! a)) (msg !! a)
                 | a <- as, x <- zip (cycle key) msg]

您的下一个错误是因为您没有在任何地方定义as。 (而且你似乎没有使用x。)


编辑:在 cmets 中,您说您已将代码更改为

encode key msg = [shift (26 - let2int (x)) (msg) | x <- zipWith (fst() key msg)]

你说你很困惑,你收到一条错误消息,表明你没有给zipWith它需要的三个参数。

你给zipWith一个参数,它是(fst() key msg)

我设想您将代码更改为类似于

encode key msg = zipWith f (cycle key) msg
  where f keyElem msgElem = shift (26 - let2int keyElem) msgElem

【讨论】:

  • 所以如果我想让它遍历消息的每个索引并更改它,我应该只更改长度(msg)吗?
  • 不,因为as 必须是一个列表。所以用[0 .. length msg - 1]替换它。但请注意,使用!! 通常是个坏主意(链表不是数组):您可以根据zipWith 重写shift 表达式并完全去掉a 变量。
  • 重写是指重写shift方法还是重写我在编码方法中使用shift的地方?
  • 我之前措辞不好,对不起。我的意思是重写encode,以便它使用zipWithshift 而不是使用列表理解和shift
  • 好吧,我已经编辑了代码以使用 zipWith,但它现在给了我错误,因为它认为我使用的参数太少。这就是我得到的:编码键 msg = [shift (26 - let2int (x)) (msg) | x
【解决方案2】:

启用parallel list comprehensions(通过在文件顶部粘贴{-# LANGUAGE ParallelListComp #-},或在GHCi 中输入:set -XParallelListComp),您可以编写:

encode key msg = [shift (26 - let2int k) m | k <- cycle key | m <- msg]

这将被脱糖为

encode key msg = [shift (26 - let2int k) m | (k,m) <- zip (cycle key) msg] 

相同
encode key msg = zipWith (\k m -> shift (26 - let2int k) m) (cycle key) msg

即dave4420 的解决方案。他的解决方案更加惯用,并且不依赖于 GHC 扩展 - 所以一定要使用那个!只是想我会展示一种简洁的书写方式。

【讨论】:

  • +1 用于平行列表理解的链接,谢谢我学到了一些新东西:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-15
  • 2023-01-23
相关资源
最近更新 更多