2

だから私は周波数分析を使ってコードを解読しようとしています。

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'
4

2 に答える 2

3

すべての最上位関数に型シグネチャを記述します。それからあなたはそれを見つけるでしょう

oneChar :: [[a]] -> [[a]]

使用から、私はあなたが意図したと推測します

oneChar :: [[Char]] -> [Char]

の代わりにtake 1を使用headするかconcat、結果を編集して のリストを取得する必要がありましたChar

そのままでは、作成したマップはキーとしてmsg2持っていますが、キーとして s を[Char]持っているかのように使用しようとしCharます。

于 2012-06-21T18:28:29.437 に答える
3

うーん - 私は座って、あなたのコードについて少し考えました

  • 型シグネチャを使用してください。コードについて考えるのに大いに役立ちます - コンパイラも最適化できます

  • もう少し意味のある名前を付けてください

    • mostFreqLtr-> freqTable_EN(英語のテキストを解読していることは明らかです)
    • alphaSort-> filterAlpha(文字以外の要素をフィルタリングし、何も並べ替えていないため、誤解を招く可能性があります
    • msgSort-> sort(同じだと思うので)
  • headand tail
    ie lst ... head lst ... tail lstではなくパターンマッチングを使用->lst@(c:cs)
    • lst はそれ自体として参照可能でcあり、その先頭と末尾ですcs(単一の要素はしばしば単一の文字として参照され、sが付加された準複数としてリストされます

コード:

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))はラムダ式であり、単一の文字をペアで変換するだけです

-- 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.: あなたのコード化されたメッセージはとても気に入っていますが、周波数分析では 1 文字も見つかりませんでした。私はあなたの暗号化アルゴリズムを推測しました。(g?vimユーザー向け)、より長いテキストを使用する必要があると思います。

于 2012-06-21T20:30:14.177 に答える