content: 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
  