-- -- Encodes/Decodes string in a string of binaries -- -- Each char is converted to a string with eight 0s or 1s -- λ> encode "The darkside of the force is a pathway to many abilities some consider to be unnatural" -- "0101010001101000011001010010000001100100011000010111001001101011011100110110100101100100011001010 -- 01000000110111101100110001000000111010001101000011001010010000001100110011011110111001001100011011 -- 00101001000000110100101110011001000000110000100100000011100000110000101110100011010000111011101100 -- 00101111001001000000111010001101111001000000110110101100001011011100111100100100000011000010110001 -- 00110100101101100011010010111010001101001011001010111001100100000011100110110111101101101011001010 -- 01000000110001101101111011011100111001101101001011001000110010101110010001000000111010001101111001 -- 00000011000100110010100100000011101010110111001101110011000010111010001110101011100100110000101101 -- 100" -- λ> decode $ encode "The darkside of the force is a pathway to many abilities some consider to be unnatural" -- "The darkside of the force is a pathway to many abilities some consider to be unnatural" import Data.Char (chr, intToDigit, ord) import Data.List.Split (chunksOf) import Numeric (showIntAtBase) -- alias type to differentiate a normal string from a string of 0 and 1's type BinString = String -- api encode :: String -> BinString encode = concatMap (fillWithZeroes . showInBin . ord) decode :: BinString -> String decode = map binToChar . chunksOf 8 binStrToInt :: BinString -> [Int] binStrToInt = map readToInt -- private functions binToChar :: BinString -> Char binToChar = chr . sum . zipWith (\idx bin -> bin * (2 ^ idx)) [0 ..] . reverse . map readToInt showInBin :: (Integral a, Show a) => a -> String showInBin n = showIntAtBase 2 intToDigit n "" fillWithZeroes :: String -> BinString fillWithZeroes str = if length str == 8 then str else fillWithZeroes ('0' : str) readToInt :: Char -> Int readToInt = read . pure