DaniWeb IT Discussion Community

Code Snippets (http://www.daniweb.com/code/)
-   haskell (http://www.daniweb.com/code/haskell.html)
-   -   Number to word form (http://www.daniweb.com/code/snippet662.html)

Rashakil Fol haskell syntax
Mar 13th, 2007
wordify:
Converts any integer number (such as 123456000999) into a string ("one billion two hundred ninety-three million one hundred two thousand one hundred").

  1. module Wordify (wordifyWords, wordify) where
  2.  
  3. digiteenNames :: [String]
  4. digiteenNames = ["", "one", "two", "three", "four", "five"
  5. ,"six", "seven", "eight", "nine", "ten"
  6. ,"eleven", "twelve", "thirteen", "fourteen"
  7. ,"fifteen","sixteen", "seventeen"
  8. ,"eighteen", "nineteen"
  9. ]
  10.  
  11. -- Returns the string form of a particular digit.
  12. digiteen :: Integer -> String
  13. digiteen n = digiteenNames !! fromIntegral n
  14.  
  15. tenNames :: [String]
  16. tenNames = ["","","twenty", "thirty", "forty", "fifty"
  17. ,"sixty", "seventy", "eighty", "ninety"
  18. ]
  19.  
  20. -- Returns the string form for a particular multiple of ten.
  21. tenName :: Integer -> String
  22. tenName n = tenNames !! fromIntegral n
  23.  
  24. -- Converts a two digit number to its string form.
  25. twodigit :: Integer -> String
  26. twodigit n | n < 20 = digiteen n
  27. | units == 0 = tenName tens
  28. | otherwise = tenName tens ++ "-" ++ digiteen units
  29. where (tens, units) = divMod n 10
  30.  
  31. -- Converts a three digit number to an array of words. For example:
  32. --
  33. -- threedigit 54 = ["fifty-four"]
  34. -- threedigit 923 = ["nine", "hundred", "twenty-three"]
  35. -- threedigit 400 = ["four", "hundred"]
  36.  
  37. threedigit :: Integer -> [String]
  38. threedigit n
  39. | hundi == 0 = [twodigit n]
  40. | twodi == 0 = [digiteen hundi, "hundred"]
  41. | otherwise = [digiteen hundi, "hundred", twodigit twodi]
  42. where (hundi, twodi) = divMod n 100
  43.  
  44.  
  45. -- periodNames = [[], ["thousand"], ["million"], ...
  46. --
  47. -- This list uses fake names after decillion.
  48. periodNames :: [[String]]
  49. periodNames = [] : map (:[]) ps
  50. where ps = ["thousand", "million", "billion", "trillion"
  51. ,"quadrillion", "quintillion", "sextillion"
  52. ,"octillion", "septillion", "novemtillion"
  53. ,"decillion"] ++ fakes 11
  54. fakes n = (wordify n ++ "-tillion") : fakes (n + 1)
  55.  
  56. -- Converts a large (or small) positive number to a list of words.
  57. manydigit :: Integer -> [String]
  58. manydigit m = aux periodNames m []
  59. where aux _ 0 tail = tail
  60. aux (p:ps) n tail
  61. = let (n', front) = divMod n 1000
  62. in aux ps n' (case front of
  63. 0 -> tail
  64. _ -> threedigit front ++ p ++ tail)
  65.  
  66. -- Converts any integer to word form, making a list of words.
  67. wordifyWords :: Integer -> [String]
  68. wordifyWords n
  69. | n < 0 = "negative" : manydigit (negate n)
  70. | n == 0 = ["zero"] -- a special case!
  71. | otherwise = manydigit n
  72.  
  73. -- Converts an integer to string form. For example,
  74. -- wordify 123456000999 = "one hundred twenty-three billion \
  75. -- \four hundred fifty-six million \
  76. -- \nine hundred ninety-nine"
  77. wordify :: Integer -> String
  78. wordify = unwords . wordifyWords