Skip to content

Instantly share code, notes, and snippets.

@wpcarro
Created June 8, 2020 15:52
Show Gist options
  • Select an option

  • Save wpcarro/ed1ed1f2cec77386d38dd29bd3558a2e to your computer and use it in GitHub Desktop.

Select an option

Save wpcarro/ed1ed1f2cec77386d38dd29bd3558a2e to your computer and use it in GitHub Desktop.
Encode and decode text using a Vigenere cipher
module Scratch where
-- This impl. is incomplete. I'm sketching out a basic working proof-of-concept to help
-- me better understand the Vigenere cipher.
--
-- Conceptually, a faster, more complete version exists; this isn't it.
import Data.Function ((&))
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Data.Char as Char
import qualified Data.Maybe as Maybe
import qualified Data.List as List
-- | Create a Vigenere matrix
vSquare :: Map Char [Char]
vSquare =
alpha & fmap (\c -> (c, rotate (Char.ord c - Char.ord 'A') alpha))
& Map.fromList
where alpha = ['A'..'Z']
-- | Attempt to return the ciphertext character at a given `row` and `col` pair.
vSquareGet :: Char -> Char -> Maybe Char
vSquareGet row col =
case Map.lookup row vSquare of
Nothing -> Nothing
Just alpha -> Just (alpha !! (Char.ord col - Char.ord 'A'))
-- | Attempt to return the plaintext character for a ciphertext char, `char` at `row`.
vSquareReverseGet :: Char -> Char -> Maybe Char
vSquareReverseGet row char =
case Map.lookup row vSquare of
Nothing -> Nothing
Just alpha ->
case List.elemIndex char alpha of
Nothing -> Nothing
Just i -> Just $ Char.chr (i + Char.ord 'A')
-- | Return the ciphertext for `x` using `keyword`.
encode :: String -> String -> String
encode x keyword =
zip x (cycle keyword)
& fmap (\(c, c') -> vSquareGet c' c)
& Maybe.catMaybes
-- | Return the plaintext for `x` using `keyword`.
decode :: String -> String -> String
decode x keyword =
zip x (cycle keyword)
& fmap (\(char, row) -> vSquareReverseGet row char)
& Maybe.catMaybes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment