所以我正在尝试使用频率分析来破译代码。
import Data.Char
import Data.List
import Data.Function
import qualified Data.Map as DMap
codedMsg = "V'Z GELVAT GB GRNPU GUR PNIRZRA GB CYNL FPENOOYR. VG'F HCUVYY JBEX. GUR BAYL JBEQ GURL XABJ VF 'HAU', NAQ GURL QBA'G XABJ UBJ GB FCRYY VG."
mostFreqLtr = ["E", "T", "A", "O", "I", "N", "S", "H", "R", "D", "L", "C", "U", "M", "W", "F", "G", "Y", "P", "B", "V", "K", "X", "J", "Q", "Z"]
--weed out non alphabetical characters from the list
alphaSort lst
| null lst = []
| isAlpha (head lst) = (head lst) : alphaSort (tail lst)
| otherwise = alphaSort (tail lst)
--sort the list by characters
msgSort [] = []
msgSort lst = sortBy (compare `on` ord) lst
--group each character into it's own list
grp [] = []
grp lst = group lst
--sort the list into most frequent character first
lSort [] = []
lSort lst = reverse (sortBy (compare `on` length) lst)
--change the list into one instance of each character
oneChar [] = []
oneChar lst = take 1 (head lst) : oneChar (tail lst)
--Pairing letters and creating a map of tuples containing frequency related characters
msg = zip (oneChar $ lSort $ grp $ msgSort $ alphaSort $ map toUpper $ codedMsg) mostFreqLtr
msg2 = DMap.fromList msg
--replace coded list with analyzed list
replaceChars lst
| null lst = []
| isAlpha (head lst) = DMap.lookup (head lst) msg2 : replaceChars (tail lst)
| otherwise = (head lst) : replaceChars (tail lst)
result = replaceChars codedMsg
我一直收到这个错误:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: DMap.Map Char a0
Actual type: DMap.Map [Char] [Char]
In the second argument of `DMap.lookup', namely `msg2'
In the first argument of `(:)', namely
`DMap.lookup (head lst) msg2'
答案 0 :(得分:3)
在所有顶级函数上写入类型签名。然后你会发现
oneChar :: [[a]] -> [[a]]
虽然,从使用中,我推测你的意图
oneChar :: [[Char]] -> [Char]
而不是take 1
,您应该使用head
,或者您应concat
编辑结果以获取Char
的列表。
按原样,您构建的地图msg2
以[Char]
作为键,但您尝试使用它,就像它有Char
个键一样。
答案 1 :(得分:3)
请使用类型签名,它有助于大量思考您的代码 - 编译器也可以进行优化
给出更有意义的名字
mostFreqLtr
- > freqTable_EN
(表明你正在解读英文文本)alphaSort
- > filterAlpha
(因为你过滤了非字母元素而没有排序任何东西,这是误导性的msgSort
- > sort
(因为我认为是相同的)head
和tail
lst@(c:cs)
c
是它的头部和cs
它的尾部(单个元素通常被称为单个字母,列表作为其附加 s 的quasiplurals import Prelude hiding (lookup)
import Data.Char ( isAlpha
, toUpper)
import Data.List ( group
, sort
, sortBy)
import Data.Function (on)
import Data.Map ( fromList
, lookup
, Map)
import Data.Maybe (mapMaybe)
仅导入必要的代码位
codedMsg :: String
codedMsg = "V'Z GELVAT GB GRNPU GUR PNIRZRA GB CYNL FPENOOYR." ++
"VG'F HCUVYY JBEX. GUR BAYL JBEQ GURL XABJ VF 'HAU'," ++
"NAQ GURL QBA'G XABJ UBJ GB FCRYY VG."
freqTable_EN :: [Char]
freqTable_EN = ['E', 'T', 'A', 'O', 'I', 'N', 'S', 'H', 'R'] ++
['D', 'L', 'C', 'U', 'M', 'W', 'F', 'G', 'Y'] ++
['P', 'B', 'V', 'K', 'X', 'J', 'Q', 'Z']
不要使用太长的行 - 它使代码的可读性降低,姓氏freqTable_EN
非常不寻常,但在这种情况下,我可以随意偏离标准,因为它更易读。我还使用[Char]
而不是String
(相当于)来更清楚地表明它是一个字母表。
-- weed out non alphabetical characters from the list
filterAlpha :: String -> String
filterAlpha = filter isAlpha
-- sort a list by length
sortByLength :: [[a]] -> [[a]]
sortByLength = sortBy (compare `on` length)
-- sort the list into most frequent character first
sortByFreq :: [[a]] -> [[a]]
sortByFreq = reverse . sortByLength
好的功能名称
不需要这样的评论-- change the list into one instance of each character
reduceGroups :: [[a]] -> [a]
reduceGroups lst = map head lst
您还可以保留编译器足够智能的lst
内容,以便从类型签名中获取所有信息,以便最后一行也可以是reduceGroups = map head
-- Pairing coded message with frequency table
pairs :: [(Char, Char)]
pairs = nonAlphaPairs ++ zip freqSortedMsg freqTable_EN
where cleanedMsg = (filterAlpha . map toUpper) codedMsg
freqSortedMsg = (reduceGroups . sortByFreq . group . sort) cleanedMsg
nonAlphaPairs = map (\x ->(x,x)) $ filter (not . isAlpha) codedMsg
(\x -> (x,x))
是一个lambda表达式,它只是转换一对中的单个字符,因为它们自己被解密
-- and creating a map for decryption
cipher :: Map Char Char
cipher = fromList pairs
-- replace encoded text by our cipher
decipher :: String -> String
decipher = mapMaybe (uplook cipher)
where uplook = flip lookup
result :: String
result = decipher codedMsg
main :: IO ()
main = print result
最后一行打印结果 - 因为我们想要阅读消息;-) 如果有什么不清楚,请随时询问。
PS。:我非常喜欢你的编码信息 - 尽管频率分析中找不到一个字母。我猜对了你的加密算法。 (对于vim用户g?
),
我认为你必须使用更长的文本。