praxis

Various programming exercises.
git clone git://git.jtobin.io/praxis.git
Log | Files | Refs

Clock.hs (2519B)


      1 {-# OPTIONS_GHC -Wall #-}
      2 {-# LANGUAGE OverloadedStrings #-}
      3 
      4 import qualified Data.Map.Strict as MS
      5 import Data.Monoid ((<>), mconcat)
      6 import qualified Data.Text as T
      7 import qualified Data.Text.IO as TIO
      8 import System.Environment (getArgs)
      9 
     10 main :: IO ()
     11 main = do
     12   args <- getArgs
     13   let parsed = case args of
     14         (input : _) -> parse (T.pack input)
     15         _           -> Nothing
     16 
     17   case parsed of
     18     Nothing -> do
     19       TIO.putStrLn "usage: ./clock HH:MM"
     20       TIO.putStrLn "(where HH in 00 -- 23, MM in 00 -- 59)"
     21 
     22     Just time ->
     23       TIO.putStrLn time
     24 
     25 parse :: T.Text -> Maybe T.Text
     26 parse input = case T.splitOn ":" stripped of
     27     [hrs, mins] -> do
     28       (rhrs, am) <- MS.lookup hrs hourmap
     29       rmin       <- MS.lookup mins minutemap
     30       return (present (rhrs, rmin, am))
     31 
     32     _ -> Nothing
     33 
     34   where
     35     stripped = T.strip input
     36 
     37 hourmap :: MS.Map T.Text (T.Text, Bool)
     38 hourmap = MS.fromList (zip hours rhours)
     39 
     40 minutemap :: MS.Map T.Text T.Text
     41 minutemap = MS.fromList (zip minutes rminutes)
     42 
     43 present :: (T.Text, T.Text, Bool) -> T.Text
     44 present (h, m, am) = "It's " <> h <> " " <> mins <> meridiem where
     45   mins
     46     | m == T.empty = m
     47     | otherwise    = m <> " "
     48   meridiem
     49     | am        = "am"
     50     | otherwise = "pm"
     51 
     52 onesAndTens :: [T.Text]
     53 onesAndTens = [
     54     "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"
     55   , "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen" , "sixteen"
     56   , "seventeen", "eightteen", "nineteen"
     57   ]
     58 
     59 gentext :: T.Text -> T.Text -> [T.Text]
     60 gentext leader prefix = mconcat [
     61     [leader]
     62   , fmap ((prefix <> " ") <>) (take 9 onesAndTens)
     63   ]
     64 
     65 hours :: [T.Text]
     66 hours =
     67   [ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10" , "11"
     68   , "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22" , "23"
     69   ]
     70 
     71 rhours :: [(T.Text, Bool)]
     72 rhours = mconcat
     73     [ ("twelve", True)  : zip hrs (repeat True)
     74     , ("twelve", False) : zip hrs (repeat False)
     75     ]
     76   where
     77     hrs = take 11 onesAndTens
     78 
     79 minutes :: [T.Text]
     80 minutes = mconcat [
     81       fmap ("0" <>) digs
     82     , fmap ("1" <>) digs
     83     , fmap ("2" <>) digs
     84     , fmap ("3" <>) digs
     85     , fmap ("4" <>) digs
     86     , fmap ("5" <>) digs
     87     ]
     88   where
     89     digs = fmap render ([0..9] :: [Int])
     90 
     91     render :: Show a => a -> T.Text
     92     render = T.pack . show
     93 
     94 rminutes :: [T.Text]
     95 rminutes = mconcat [
     96     gentext "" "oh"
     97   , drop (9 :: Int) onesAndTens
     98   , gentext "twenty" "twenty"
     99   , gentext "thirty" "thirty"
    100   , gentext "forty" "forty"
    101   , gentext "fifty" "fifty"
    102   ]
    103