elocrypt-2.1.0: src/lib/Data/Elocrypt/Utils.hs
module Data.Elocrypt.Utils where
import Data.Char (isAlphaNum, isSpace)
import Data.Maybe (fromMaybe)
import Data.Ratio
import qualified Data.Map as M
import Control.Monad.Random (MonadRandom(), fromList)
-- |A mapping from letters to numbers that look like them
numeralConversions = M.fromList [
('o', ['0']),
('l', ['1']),
('z', ['2']),
('e', ['3']),
('a', ['4']),
('s', ['5']),
('g', ['6', '9']),
('t', ['7']),
('b', ['8'])]
-- |A mapping from letters to symbols that look like them
symbolConversions = M.fromList [
('a', ['@']),
('l', ['!']),
('s', ['$'])]
-- |Map a letter to one or more digits, if possible
toDigit :: Char -> String
toDigit c = fromMaybe [c] (numeralConversions M.!? c)
-- |Map a letter to one or more symbols, if possible
toSymbol :: Char -> String
toSymbol c = fromMaybe [c] (symbolConversions M.!? c)
-- |Selects special characters
isSymbol :: Char -> Bool
isSymbol c = not (isAlphaNum c || isSpace c)
-- |Randomly update characters at the specified probability
updateR
:: MonadRandom m
=> (Char -> m Char)
-> Rational
-> String
-> m String
updateR f prob = mapM f'
where f' ch = do
ch' <- f ch
fromList [
(ch, toRational $ denominator prob),
(ch', toRational $ numerator prob)]
-- |Update character at position pos
update1
:: Monad m
=> (Char -> m Char) -- ^ Update function
-> String -- ^ the string to update
-> Int -- ^ the position to update
-> m String
update1 _ "" _ = return ""
update1 f s pos = (\ch' -> prefix ++ ch' : suffix) <$> f ch
where (prefix, ch : suffix) = splitAt pos s