import Data.Char
import Data.Map

charToInt :: Char -> Int
charToInt c = ord c - ord '0'



decodeChar :: String -> (Char,String)
decodeChar ('7':'9':r:rs) = (r,rs)
decodeChar ('7':r:rs)     = ("PQUVWXYZ. " !! charToInt r, rs)
decodeChar ('3':r:rs)     = ("ABCDFGIJKN" !! charToInt r, rs)
decodeChar (r:rs)         = ("HOL MES RT" !! charToInt r, rs)


decode :: String -> String
decode [] = []
decode st = let (c, s) = decodeChar st in c:decode s




revEnc :: String -> (Char, String)
revEnc enc = let (dec, rm) = decodeChar enc in (dec, take (length enc - length rm) enc)

ds :: String
ds = ['0'..'9']



encodeMap :: Map Char String
encodeMap = fromList [ revEnc [d2,d1,d0] | d2 <- ds, d1 <- ds, d0 <- ds ]


encodeChar :: Char -> String
encodeChar c = findWithDefault "" c encodeMap 


encode :: String -> String
encode st = concatMap encodeChar $ fmap toUpper st


main = let orig = "One night-it was on the twentieth of March, 1888-I was returning"
           enc = encode orig
           dec = decode enc
       in mapM_ putStrLn [ "Original: " ++ orig
                         , "Encoded: " ++ enc 
                         , "Decoded: " ++ dec ]