Skip to content

Instantly share code, notes, and snippets.

@lhcopetti
Created February 5, 2018 00:25
Show Gist options
  • Save lhcopetti/ec27f86c54cc31b3c5e9bf98817ec962 to your computer and use it in GitHub Desktop.
Save lhcopetti/ec27f86c54cc31b3c5e9bf98817ec962 to your computer and use it in GitHub Desktop.
An example to the Vigene Cipher implementation using a monadic based solution
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Monad.Trans.State
import Data.Char
import Control.Monad.Loops
import Control.Monad
import Control.Lens
---- Vigenere Cipher, monadic solution -----
data VigenereState = VS { _text :: String
, _cipher :: String
}
makeLenses ''VigenereState
runVigenere :: String -> String -> String
runVigenere text cipher = evalState cipherText
VS { _text = text
, _cipher = cycle cipher
}
vigenereTransform :: Char -> Char -> Char
vigenereTransform l c = chr newOrd
where
initialOrd = ord 'A'
alphabetSize = length ['A' .. 'Z']
newOrd = (ord c + ord l) `mod` alphabetSize + initialOrd
cipherText :: State VigenereState String
cipherText = whileM hasText nextCipher
nextCipher :: State VigenereState Char
nextCipher = do
t <- drawText
if isSpace t then
return t
else do
c <- drawCipher
return (vigenereTransform t c)
drawCipher :: State VigenereState Char
drawCipher = draw' cipher
drawText :: State VigenereState Char
drawText = draw' text
draw' :: Lens' VigenereState String -> State VigenereState Char
draw' f = do
st <- get
let top = head (view f st)
put (over f tail st)
return top
hasText :: State VigenereState Bool
hasText = liftM (not . null) (gets _text)
main = putStrLn $ runVigenere "MEET AT DAWN" "ALLY"
-- expected result = "MPPR AE OYWY"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment