凯撒的密码,包含整数列表

时间:2017-01-28 19:35:09

标签: haskell recursion

我仍然是Haskell的新手,我正在尝试编写一个函数,使得密码的输入参数是一个整数列表,而不是一个整数。第一个字符使用第一个整数作为参数进行加密,第二个字符使用第二个整数等进行加密。如果用完整数,则从头开始使用它们。

这是我到目前为止所得到的:

import Data.Char

--encode is for encoding one character with one interger
encode :: Int -> String -> String  
encode shift msg = 
    let ords = map ord msg  
        shifted = map (+ shift) ords  
    in  map chr shifted

-- this is the troubling part, I try to use head to send the first element of string and the first element of intgers' list
cipher :: [Int] -> String -> String
cipher x str =
    let splitedstr= (head str)
        splitedint= (head x) -- parse error on input splitedint
    in encode splitedint splitedstr ++ cipher x str

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

根据您的问题陈述,我认为encode函数本身应该在Char而非String上运行。因此,您可以将其改编为:

encode :: Int -> Char -> Char
encode shift = chr . (+ shift) . ord

接下来,您只需使用zipWithcycle来构建字符串:

cipher :: [Int] -> String -> String
cipher shifts = zipWith encode $ cycle shifts

实施这些时,我得到:

*Main> cipher [1,2,4] "HelloWorld"
"Igpmq[ptpe"
ghci中的

如果您想自己编写递归,可以按如下方式执行此操作:

cipher :: [Int] -> String -> String
cipher shifts = cipher2 shifts shifts

cipher2 :: [Int] -> [Int] -> String -> String
cipher2 _ _      []     = []
cipher2 s []     ts     = cipher2 s s ts
cipher2 s (x:xs) (t:ts) = (encode x t):cipher2 s xs ts

你因此将cipher传递给cipher2cipher2有一个第一个参数,它是整个班次序列(这样它可以在失去班次时重新启动)。此外,如果字符串已到达其末尾,我们返回一个空列表(字符串)。否则,我们只需在字符串和移位列表的头部调用encode,并在尾部递归调用cipther2

最后还有一个语义问题:例如,您可能会向z函数提供encode。如果你移动它,它将超出字母数字范围,这可能不是你想要的。在这种情况下,你应该使用modulo。