RosettaCodeData/Task/Four-is-magic/Haskell/four-is-magic.hs
2023-07-01 13:44:08 -04:00

60 lines
1.8 KiB
Haskell

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