Skip to content

Instantly share code, notes, and snippets.

@taiansu
Last active May 24, 2018 18:15
Show Gist options
  • Save taiansu/fbfb4c350b2e8ef00fdcf927eba5d3e9 to your computer and use it in GitHub Desktop.
Save taiansu/fbfb4c350b2e8ef00fdcf927eba5d3e9 to your computer and use it in GitHub Desktop.
Flolac week of code 4: caesar cipher
import Data.List (group, sort, sortOn)
import qualified Data.Map as M
encode :: Int -> String -> String
encode n = fmap (fetchChar . shift . fromEnum) where
shift = (+ n) . subtract 65
fetchChar = (cycle ['A'..'Z'] !!)
decode :: String -> (String, Int)
decode str = fst . head $ sortOn snd matrix where
matrix = [ row offset str | offset <- [0..25]]
row :: Int -> String -> ((String, Int), Double)
row offset str = ((encoded, offset), likelihood) where
encoded = encode offset str
grouped = group . sort $ encoded
likelihood = foldr sumDistance 0.0 grouped
sumDistance xs acc = acc + distance xs
distance xs = abs $ M.findWithDefault 0.0 (head xs) distribution - freq xs
freq xs = fromIntegral (length xs) / len
len = fromIntegral $ length str
distribution :: M.Map Char Double
distribution = M.fromList [ ('A', 0.08167) , ('B', 0.01492) , ('C', 0.02782) , ('D', 0.04253)
, ('E', 0.02702) , ('F', 0.02228) , ('G', 0.02015) , ('H', 0.06094)
, ('I', 0.06966) , ('J', 0.00153) , ('K', 0.00772) , ('L', 0.04025)
, ('M', 0.02406) , ('N', 0.06749) , ('O', 0.07507) , ('P', 0.01929)
, ('Q', 0.00095) , ('R', 0.05987) , ('S', 0.06327) , ('T', 0.09056)
, ('U', 0.02758) , ('V', 0.00978) , ('W', 0.02360) , ('X', 0.00150)
, ('Y', 0.01974) , ('Z', 0.00074)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment