今天的课程内容是:
第 5 章:函数的定义 [幻灯片 ]
第 6 章:List Comprehension [幻灯片 ]
第 7 章:递归函数 [幻灯片 ]
为什么讲了这么多我也不清楚。然后作业也挺多,最烧脑的想必是:
为了对字符串文本进行加密,凯撒发明了如下的加密方式:
把一个英文字母替换为它在字母表中后面的第 3 个字母。
如果到达了字母表的末尾 (即:字母 z),则回转到第一个字母
a。
也即,字母 z 的后继字母是 a。
下面,我们按照这种方式,分别定义 加密 和 解密 两个函数。
加密 / encode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import Data.Char(ord , chr , isLower )encode :: Int -> String -> String encode n xs = [ shift n x | x <- xs ]shift :: Int -> Char -> Char shift n c | isLower c = int2let $ mod (let2int c + n) 26 | otherwise = c let2int :: Char -> Int let2int c = ord c - ord 'a' int2let :: Int -> Char int2let n = chr $ ord 'a' + n
解密 / crack
对凯撒加密后的字符串进行解密的关键:
下面定义 table 依次记录了 26
个英文字母的出现百分比:
1 2 3 4 table :: [Float ]table = [ 8.1 , 1.5 , 2.8 , 4.2 , 12.7 , 2.2 , 2.0 , 6.1 , 7.0 , 0.2 , 0.8 , 4.0 , 2.4 , 6.7 , 7.5 , 1.9 , 0.1 , 6.0 , 6.3 , 9.0 , 2.8 , 1.0 , 2.4 , 0.2 , 2.0 , 0.1 ]
chi-square statistic :一种对一组 期望频率 (expected
frequencies) 和 一组 观察频率 (observed frequencies)
进行比较的标准方法。
假设存在两个长度为 n
的频率序列:期望频率序列 e s ;观察频率序列 o s 。则两者的 chi-square
statistic 定义如下: $$
\sum\limits_{i=0}^{n-1}\dfrac{(es_i-os_i)^2}{es_i^2}
$$ 注:你可能需要用到函数
fromIntegral :: (Integral a, Num b) => a -> b,它可以实现从整数类型到浮点数类型的转换。
我们来看一下这个题目。主要思想是:暴力枚举 26
个偏移量,偏移后得到一段文字,再根据各种字母的出现频率与英文语料中的统计学数据,从而根据最小的
chi-square statistic 确定哪个偏移量对应的文字“最像”英文。
看下我的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 module HW5 where import Data.Char (chr , isLower , ord )table :: [Float ] table = [ 8.1 , 1.5 , 2.8 , 4.2 , 12.7 , 2.2 , 2.0 , 6.1 , 7.0 , 0.2 , 0.8 , 4.0 , 2.4 , 6.7 , 7.5 , 1.9 , 0.1 , 6.0 , 6.3 , 9.0 , 2.8 , 1.0 , 2.4 , 0.2 , 2.0 , 0.1 ] crack :: String -> String crack xs = encode (-factor) xs where factor = position (minimum chitab) chitab chitab = [ chisqr (rotate n table') table | n <- [0 ..25 ] ] table' = freqs xs position :: Eq a => a -> [a] -> Int position x' [] = 0 position x' (x:xs) = if x == x' then 0 else 1 + position x' xsrotate :: Int -> [a] -> [a]rotate n s = [ p | r <- [0 ..25 ], (p,q) <- zip s [0 ..25 ], q == mod (r + n) 26 ]freqs :: String -> [Float ]freqs s = [ fromIntegral (100 * length [ z | z <- s, z == chr ((ord 'a' ) + x) ]) / fromIntegral (length s) | x <- [0 ..25 ] ]chisqr :: [Float ] -> [Float ] -> Float chisqr [] _ = fromIntegral 0 chisqr _ [] = fromIntegral 0 chisqr (o:os) (e:es) = (o - e) ^ 2 / (e ^ 2 ) + chisqr os es
为了测试之,我从 2025 年 9 月 25 日 The Economist
网站上发布的 Donald
Trump is trying to silence his critics. He will fail
中节选了第一段进行测试。相符甚好。