module Main where import Data.List (find) import Data.Char (toUpper) firstNums :: [String] firstNums = [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" ] tens :: [String] tens = ["twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"] biggerNumbers :: [(Int, String)] biggerNumbers = [(100, "hundred"), (1000, "thousand"), (1000000, "million"), (1000000000, "billion"), (1000000000000, "trillion")] cardinal :: Int -> String cardinal n | n' < 20 = negText ++ firstNums !! n' | n' < 100 = negText ++ tens !! (n' `div` 10 - 2) ++ if n' `mod` 10 /= 0 then "-" ++ firstNums !! (n' `mod` 10) else "" | otherwise = let (num, name) = maybe (last biggerNumbers) fst (find (\((num_, _), (num_', _)) -> n' < num_') (zip biggerNumbers (tail biggerNumbers))) smallerNum = cardinal (n' `div` num) in negText ++ smallerNum ++ " " ++ name ++ if n' `mod` num /= 0 then " " ++ cardinal (n' `mod` num) else "" where n' = abs n negText = if n < 0 then "negative " else "" capitalized :: String -> String capitalized (x : xs) = toUpper x : xs capitalized [] = [] magic :: Int -> String magic = go True where go first num = let cardiNum = cardinal num in (if first then capitalized else id) cardiNum ++ " is " ++ if num == 4 then "magic." else cardinal (length cardiNum) ++ ", " ++ go False (length cardiNum) main :: IO () main = do putStrLn $ magic 3 putStrLn $ magic 15 putStrLn $ magic 4 putStrLn $ magic 10 putStrLn $ magic 20 putStrLn $ magic (-13) putStrLn $ magic 999999