Haskell : Caesar Cipher Flashcards
chart2int c = ord c - ord ‘a’
returns 2
int2char i = chr (i + ord ‘a’)
z
shift c offset =
let
converted = char2int c
is_lower = converted >= 0 && converted < 26
in
if is_lower
then int2char ((converted + offset) ‘mod’ 26)
else c
shift ‘a’ 3
Shifts a by three
Mod implements wrap around
caesar_enc [] - = []
caesar_enc (x:xs) offset = shift x offset
: caesar_enc xs offset
caesar_enc “Hello there” 3
“khoor wkhuh”
caesar_dec [] _ = []
caesar_dec (x:xs) offset = shift x (-offset)
: caesar_dec xs offset
caesar_enc “khoor wkhuh” 3
“Hello there”
Chi-squared score
(freq-english)^2/english
Lower the score, closer to english
count _ [] = 0
count c (x:xs)
|c==x = 1+rest
|otherwise = rest
where rest = count c xs
count ‘a’ “aabaa”
4
freq c list = fromIntegral (count c list) / fromIntegral (length list)
freq ‘a’ “aabaa”
0.8
get_freqs _ 26 = []
get_freqs string c = freq (int2char c) string : get_freqs string (c+1)
get_freqs “abc” 0
[“0.3333334”, “0.3333334”, “0.3333334”, 0.0, 0.0…]
chi_squared [] [] = 0
chi_squared (x:xs) (y:ys) =
(x-y)**2/y + chi_squared xs ys
chi_squared [0.1, 0.9] [0.8, 0.2]
3.0624998
eng_freqs = […]
list of all English character frequencies
chi_squared_string string =
let
string_freqs = get_freqs string 0
in
chi_squared string_freqs eng_freqs
chi_squared_string “hello there”
1.5819808
chi_squared_list _ 26 = []
chi_squared_list string i =
let
decoded = caesar_dec string i
score = chi_squared_string decoded
in
(score, decoded) : chi_squared_list string (i+1)
chi_squared_list “ifmmp” 0
[(9.637143,”ifmmp”),(4.4730797,”hello”),(22.258533,”gdkkn”),…
get_best [(socre,string)] = (score = string)
get_best((score, string):xs) =
let
(tail_score, tail_string) = get_best xs
in
if score < tail_score
then (score, string)
else(tail_score,tail_string)
get_best (chi_squared_list “ifmmp” 0)
(4.4730797, “hello”)
caesar_crack string =
let
score = chi_squared_list string 0
(score, best) = get_best scores
in
best
caesar_crack “ifmmp”
“hello”