In today’s Programming Praxis we have another cipher algorithm. Let’s get started.
A quick import:
import Data.Char
First of all, we need a function to add and subtract characters.
combine :: (Int -> Int -> Int) -> Char -> Char -> Char combine f a b = chr $ mod (f (ord a) (ord b) - 2 * 65) 26 + 65
Encrypting or decrypting is just a matter of using this combine function on all the letter pairs of the key and the message.
cipher :: (Int -> Int -> Int) -> String -> String -> String cipher f key msg = zipWith (combine f) (clean msg) (clean key) where clean = map toUpper . filter isLetter
When encrypting, we can simply append the message to the key.
encrypt :: String -> String -> String encrypt key msg = cipher (+) (key ++ msg) msg
When decrypting, we instead need to append the unencrypted message, which we do not have yet. Fortunately, thanks to lazy evaluation we can simply recursively call the decrypt function. This means it will produce a stack overflow when fed an empty key, but since that would be useless anyway we don’t really care.
decrypt :: String -> String -> String decrypt key msg = cipher (-) (key ++ decrypt key msg) msg
All that’s left is to test our functions:
main :: IO () main = do print $ encrypt "BONSAI" "Pablo Picasso" print $ decrypt "BONSAI" "QOODOXXCBDGD"
That seems to work just fine. Another one down.
Tags: autokey, bonsai, cipher, code, Haskell, kata, praxis, programming