fork(2) download
  1. -- this is my first attempt at part one of the optional programming assignment
  2. -- for the stanford Introduction to Artificial Intelligence class
  3. -- it solves a rotating or caesar cypher assuming the most common
  4. -- letter in english is 'e'
  5. -- PAC 9th January, 2012
  6.  
  7. import Data.Char (ord, chr, isUpper, isLower, toLower)
  8. import Data.List (sortBy, elemIndices)
  9. import Data.Ord (comparing)
  10. import qualified Data.Map as M
  11. import System.Environment (getArgs)
  12.  
  13. -- the code to break
  14. defaultEncodedMsg = "Esp qtcde nzyqpcpynp zy esp ezatn zq Lcetqtntlw Tyepwwtrpynp hld spwo le Olcexzfes Nzwwprp ty estd jplc."
  15.  
  16. -- Shifts a character to the right if positive, left if negative. Wraps around.
  17. shift :: Int -> Char -> Char -- Modulus handles the wraparound(shift 1 'z' = 'a')
  18. shift n c | isUpper c = chr $ ord 'A' + ((ord c + n - ord 'A') `mod` 26)
  19. | isLower c = chr $ ord 'a' + ((ord c + n - ord 'a') `mod` 26)
  20. | otherwise = c
  21.  
  22. -- rotate input string by n
  23. shiftString:: Int -> String -> String
  24. shiftString n = map (shift n)
  25.  
  26. --count number of instances of a letter in a string
  27. instances:: Char -> String -> Int
  28. instances x ys = length $ elemIndices (toLower x) (map toLower ys)
  29.  
  30. --calculate frequency of a letter
  31. frequency:: Char -> String -> Float
  32. frequency x string = fromIntegral (instances x string) / fromIntegral (length string)
  33.  
  34. -- creates a sorted descending list list of tuples of letter and its frequency
  35. frequencyAll:: String -> [(Char, Float)]
  36. frequencyAll string = reverse $ sortBy (comparing snd) [ (x , frequency x string) | x <- ['a' .. 'z' ] ]
  37.  
  38. -- assuming 'e' is the most common letter in english
  39. decode:: String -> String
  40. decode string = shiftString (ord 'e' - ord (fst $ head $ frequencyAll string)) string
  41.  
  42. -- parse arguments, if no supplied use default
  43. parseArgs:: [String] -> String
  44. parseArgs args = if null args then defaultEncodedMsg else head args
  45.  
  46. -- entry point
  47. main = do
  48. args <- getArgs
  49. let msg = parseArgs args
  50. putStrLn "Caesar Cypher Solver (ai-class) - naive approach\n"
  51. putStrLn "encoded message:"
  52. putStrLn "\nThe top candidate based on the frequency of the letter 'e' in english is:\n"
  53. putStrLn $ decode msg
  54.  
Success #stdin #stdout 0.01s 3624KB
stdin
Standard input is empty
stdout
Caesar Cypher Solver (ai-class) - naive approach

encoded message:
Esp qtcde nzyqpcpynp zy esp ezatn zq Lcetqtntlw Tyepwwtrpynp hld spwo le Olcexzfes Nzwwprp ty estd jplc.

The top candidate based on the frequency of the letter 'e' in english is:

The first conference on the topic of Artificial Intelligence was held at Dartmouth College in this year.