Last active
March 1, 2019 21:24
-
-
Save pjrt/469934cdcbbf3d4f471e4bb3709beb75 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Data.List (intersperse, foldl') | |
import Data.List.Split (chunksOf) | |
numbers :: Int -> String | |
numbers c = | |
case c of | |
0 -> "" | |
1 -> "one" | |
2 -> "two" | |
3 -> "three" | |
4 -> "four" | |
5 -> "five" | |
6 -> "six" | |
7 -> "seven" | |
8 -> "eight" | |
9 -> "nine" | |
otherwise -> error "Unexpected char" | |
teens :: Int -> String | |
teens c = | |
case c of | |
0 -> "ten" | |
1 -> "eleven" | |
2 -> "twelve" | |
3 -> "thirteen" | |
4 -> "fourteen" | |
5 -> "fifteen" | |
6 -> "sixteen" | |
7 -> "seventeen" | |
8 -> "eighteen" | |
9 -> "nineteen" | |
otherwise -> error "Unexpected char" | |
tens :: Int -> String | |
tens c = | |
case c of | |
2 -> "twenty" | |
3 -> "thirty" | |
4 -> "forty" | |
5 -> "fifty" | |
6 -> "sixty" | |
7 -> "seventy" | |
8 -> "eighty" | |
9 -> "ninety" | |
otherwise -> error "Unexpected char" | |
hundred :: Int -> String | |
hundred 0 = "" | |
hundred n = numbers n ++ " hundred" | |
over20 :: Int -> Int -> String | |
over20 x y = tens x ++ numbers y | |
-- Given a number zzzyyyxx, convert it into [[x,x], [y,y,y], [z,z,z]] | |
splitNumReverse :: (Num a, Show a) => a -> [[Int]] | |
splitNumReverse = map (map read . chunksOf 1) . chunksOf 3 . reverse . show | |
nameHundred :: [Int] -> String | |
nameHundred [x] = numbers x | |
nameHundred [1, y] = teens y | |
nameHundred [x, y] = over20 x y | |
nameHundred [x, 1, z] = hundred x ++ " and " ++ teens z | |
nameHundred [x, y, z] = hundred x ++ " and " ++ over20 y z | |
nameHundred o = error $ "Invalid section: " ++ show o | |
nameThousand :: Int -> Maybe String | |
nameThousand n = | |
case n of | |
4 -> Just "billion" | |
3 -> Just "million" | |
2 -> Just "thousand" | |
_ -> Nothing | |
-- Names of thousandth position. The order matters! | |
namesOfThousand :: [String] | |
namesOfThousand = ["", "thousand", "million", "billion"] | |
-- Given two lists, join them via their heads. | |
-- For example: 123 456 -> 142536. Stops at the spot where the first list ends | |
joinOnHeads :: [a] -> [a] -> [a] | |
joinOnHeads [] ys = [] | |
joinOnHeads xs [] = [] | |
joinOnHeads (x:xs) (y:ys) = [x, y] ++ joinOnHeads xs ys | |
-- Given a number, convert it into its English form, up to a billion | |
numberName :: (Num a, Show a) => a -> String | |
numberName n = | |
let splitted = splitNumReverse n | |
namedSections = map nameHundred splitted | |
in concat $ intersperse " " $ reverse $ joinOnHeads namesOfThousand namedSections | |
main :: IO () | |
main = do | |
let testNum = 2340 | |
putStrLn $ show $ reverse $ chunksOf 3 $ reverse $ show testNum | |
putStrLn $ numberName testNum |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment