我仍然是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
感谢您的帮助。
答案 0 :(得分:1)
根据您的问题陈述,我认为encode
函数本身应该在Char
而非String
上运行。因此,您可以将其改编为:
encode :: Int -> Char -> Char
encode shift = chr . (+ shift) . ord
接下来,您只需使用zipWith
和cycle
来构建字符串:
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
传递给cipher2
而cipher2
有一个第一个参数,它是整个班次序列(这样它可以在失去班次时重新启动)。此外,如果字符串已到达其末尾,我们返回一个空列表(字符串)。否则,我们只需在字符串和移位列表的头部调用encode
,并在尾部递归调用cipther2
。
最后还有一个语义问题:例如,您可能会向z
函数提供encode
。如果你移动它,它将超出字母数字范围,这可能不是你想要的。在这种情况下,你应该使用modulo。