# Haskell Quiz/English Numerals/Solution Michael Sloan

### From HaskellWiki

< Haskell Quiz | English Numerals(Difference between revisions)

(fix cat syntax) |
m |

## Latest revision as of 20:47, 14 December 2009

Probably not as elegant as it could be, but handles a huge number of... numbers. More than any of the ruby programs, I'm sure. Feel free to edit it for elegance.

prefixes = ["", "un", "duo","tre","quattuor","quin", "sex", "septen","octo", "novem"] suffixes = ["dec"]++(map (++"gint") ["vi", "tri","quadra", "quinqua","sexa","septua","octo", "nona"]) aname 0 = "" aname 1 = "thousand" aname 101 = "centillion" aname n | n > 101 = error "Can't name american numbers over with more than 303 decimal digits" aname n = (if n <= 10 then ["m", "b", "tr", "quadr", "quint", "sext","sept", "oct", "non"] !! (n-2) else (prefixes !! ((n-1) `mod` 10)) ++ (suffixes !! ((n-1) `div` 10 - 1)) ) ++ "illion" ename 0 = "" ename 1 = "thousand" ename 200 = "centillion" ename 201 = "centilliard" ename n | n > 201 = error "Can't name european numbers over with more than 603 decimal digits" ename n = (if n < 20 then ["m", "b", "tr", "quadr", "quint", "sext","sept", "oct", "non"] !! ((n `div` 2)-1) else (prefixes !! ((n `div` 2) `mod` 10)) ++ (suffixes !! (n `div` 20 - 1)) ) ++ "illi" ++ (if even n then "on" else "ard") digits = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"] triple :: Integer -> Int -> (Int -> String) -> String triple 0 _ _ = "" triple n i f | n > 999 = triple (n `div` 1000) (i+1) f ++ (if n `mod` 1000 /= 0 then ", " ++ triple (n `mod` 1000) i f else "") triple n 0 _ | n > 99 && (n `mod` 100) == 0 = digits !! (fromIntegral $ n `div` 100) ++ " hundred" triple n 0 f | n > 99 = triple (n `div` 100 * 100) 0 f ++ " and " ++ triple (n `mod` 100) 0 f triple n 0 _ | n `mod` 10 == 0 = ["", "ten", "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety"] !! (fromIntegral $ n `div` 10) triple n 0 _ | n > 10 && n < 20 = ["eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] !! (fromIntegral $ n - 11) triple n 0 _ | n < 10 = digits !! (fromIntegral n) triple n 0 f = triple (n `div` 10 * 10) 0 f ++ " " ++ triple (n `mod` 10) 0 f triple n i f | n <= 999 = triple n 0 f ++ " " ++ f i americanNumber 0 = "zero" americanNumber x = triple x 0 aname europeanNumber 0 = "zero" europeanNumber x = triple x 0 ename