Skip to content

Instantly share code, notes, and snippets.

@vderyagin
Last active December 11, 2015 10:08
Show Gist options
  • Save vderyagin/4584716 to your computer and use it in GitHub Desktop.
Save vderyagin/4584716 to your computer and use it in GitHub Desktop.
module CaesarCipher
(
encrypt
, decrypt
, cipher
) where
import Data.Char
isAsciiLetter :: Char -> Bool
isAsciiLetter ch = isAscii ch && isLetter ch
alphabetLength :: Int
alphabetLength = length ['a'..'z']
substitution :: Int -> Char -> Char
substitution offset ch
| isAsciiLetter ch = chr $ ord 'a' + (ord (toLower ch) - ord 'a' + offset) `mod` alphabetLength
| otherwise = ch
encrypt :: Int -> String -> String
encrypt = map . substitution
decrypt :: Int -> String -> String
decrypt = encrypt . negate
cipher :: Int -> (String -> String, String -> String)
cipher offset = (encrypt offset, decrypt offset)
import CaesarCipher
import Test.Hspec
main :: IO ()
main = hspec $ do
describe "encrypt" $ do
it "does nothing with zero offset" $
encrypt 0 "some string" `shouldBe` "some string"
it "does nothing to strings without latin letters" $
encrypt 8 " ,. " `shouldBe` " ,. "
it "shifts latin letters by constant offset" $
encrypt 1 "abc" `shouldBe` "bcd"
it "wraps letters around alphabet" $
encrypt 1 "zab" `shouldBe` "abc"
it "converts uppercase letters to lowercase" $
encrypt 3 "FOO" `shouldBe` "irr"
it "reverses encryption used with negated offset" $
encrypt (-3) "irr" `shouldBe` "foo"
describe "decrypt" $ do
let offset = 3
cipherText = "WKH TXLFN EURZQ IRA MXPSV RYHU WKH ODCB GRJ"
plainText = "the quick brown fox jumps over the lazy dog"
it "decrypts strings, encryptd by 'encrypt'" $
decrypt offset cipherText `shouldBe` plainText
describe "cipher" $ do
let (e, d) = cipher 83
s = "some string"
it "encrypts" $
e s `shouldSatisfy` (not . (==s))
it "decrypts encryption result" $
(d . e $ s) `shouldBe` s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment