Number names

From Rosetta Code
Task
Number names
You are encouraged to solve this task according to the task description, using any language you may know.

Ada

<lang ada> with Ada.Text_IO; use Ada.Text_IO;

procedure Integers_In_English is

  type Spellable is range 0..999_999_999_999_999_999;
  function Spell (N : Spellable) return String is
     function Twenty (N : Spellable) return String is
     begin
        case N mod 20 is
           when  0 => return "zero";
           when  1 => return "one";
           when  2 => return "two";
           when  3 => return "three";
           when  4 => return "four";
           when  5 => return "five";
           when  6 => return "six";
           when  7 => return "seven";
           when  8 => return "eight";
           when  9 => return "nine";
           when 10 => return "ten";
           when 11 => return "eleven";
           when 12 => return "twelve";
           when 13 => return "thirteen";
           when 14 => return "fourteen";
           when 15 => return "fifteen";
           when 16 => return "sixteen";
           when 17 => return "seventeen";
           when 18 => return "eighteen";
           when others => return "nineteen";
        end case;
     end Twenty;
     function Decade (N : Spellable) return String is
     begin
        case N mod 10 is
           when 2 => return "twenty";
           when 3 => return "thirty";
           when 4 => return "forty";
           when 5 => return "fifty";
           when 6 => return "sixty";
           when 7 => return "seventy";
           when 8 => return "eighty";
           when others => return "ninety";
        end case;
     end Decade;
     function Hundred (N : Spellable) return String is
     begin
        if N < 20 then
           return Twenty (N);
        elsif 0 = N mod 10 then
           return Decade (N / 10 mod 10);
        else
           return Decade (N / 10) & '-' & Twenty (N mod 10);
        end if;
     end Hundred;
     function Thousand (N : Spellable) return String is
     begin
        if N < 100 then
           return Hundred (N);
        elsif 0 = N mod 100 then
           return Twenty (N / 100) & " hundred";
        else
           return Twenty (N / 100) & " hundred and " & Hundred (N mod 100);
        end if;
     end Thousand;
     function Triplet
              (  N     : Spellable;
                 Order : Spellable;
                 Name  : String;
                 Rest  : not null access function (N : Spellable) return String
              )  return String is
        High : Spellable := N / Order;
        Low  : Spellable := N mod Order;
     begin
        if High = 0 then
           return Rest (Low);
        elsif Low = 0 then
           return Thousand (High) & ' ' & Name;
        else
           return Thousand (High) & ' ' & Name & ", " & Rest (Low);
        end if;
     end Triplet;
     function Million (N : Spellable) return String is
     begin
        return Triplet (N, 10**3, "thousand", Thousand'Access);
     end Million;
     function Milliard (N : Spellable) return String is
     begin
        return Triplet (N, 10**6, "million", Million'Access);
     end Milliard;
     function Billion (N : Spellable) return String is
     begin
        return Triplet (N, 10**9, "milliard", Milliard'Access);
     end Billion;
     function Billiard (N : Spellable) return String is
     begin
        return Triplet (N, 10**12, "billion", Billion'Access);
     end Billiard;
  begin
     return Triplet (N, 10**15, "billiard", Billiard'Access);
  end Spell;

begin

  Put_Line ("               99 " & Spell (               99));
  Put_Line ("              300 " & Spell (              300));
  Put_Line ("              310 " & Spell (              310));
  Put_Line ("            1_501 " & Spell (            1_501));
  Put_Line ("           12_609 " & Spell (           12_609));
  Put_Line ("          512_609 " & Spell (          512_609));
  Put_Line ("       43_112_609 " & Spell (       43_112_609));
  Put_Line ("   77_000_112_609 " & Spell (   77_000_112_609));
  Put_Line ("2_000_000_000_100 " & Spell (2_000_000_000_100));

end Integers_In_English; </lang> The solution is recursive by the triplets of decimal numbers. The implementation goes up to 1018-1. Sample output:

               99 ninety-nine
              300 three hundred
              310 three hundred and ten
            1_501 one thousand, five hundred and one
           12_609 twelve thousand, six hundred and nine
          512_609 five hundred and twelve thousand, six hundred and nine
       43_112_609 forty-three million, one hundred and twelve thousand, six hundred and nine
   77_000_112_609 seventy-seven milliard, one hundred and twelve thousand, six hundred and nine
2_000_000_000_100 two billion, one hundred

ALGOL 68

PROC number words = (INT n)STRING:(
  # returns a string representation of n in words. Currently
  deals with anything from 0 to 999 999 999. #
    []STRING digits = []STRING
      ("zero","one","two","three","four","five","six","seven","eight","nine")[@0];
    []STRING teens = []STRING
      ("ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen")[@0];
    []STRING decades = []STRING
      ("twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety")[@2];

    PROC three digits = (INT n)STRING: (
      # does the conversion for n from 0 to 999. #
        INT tens = n MOD 100 OVER 10;
        INT units = n MOD 10;
        (n >= 100|digits[n OVER 100] + " " + "hundred" + (n MOD 100 /= 0|" and "|"")|"") +
        (tens /= 0|(tens = 1|teens[units]|decades[tens] + (units /= 0|"-"|""))) +
        (units /= 0 AND tens /= 1 OR n = 0|digits[units]|"")
      );
    INT m = n OVER 1 000 000;
    INT k = n MOD 1 000 000 OVER 1000;
    INT u = n MOD 1000;
    (m /= 0|three digits(m) + " million"|"") +
    (m /= 0 AND (k /= 0 OR u >= 100)|", "|"") +
    (k /= 0|three digits(k) + " thousand"|"") +
    ((m /= 0 OR k /= 0) AND u > 0 AND u < 100|" and " |: k /= 0 AND u /= 0|", "|"") +
    (u /= 0 OR n = 0|three digits(u)|"")
  );

on logical file end(stand in, (REF FILE f)BOOL: stop iteration);
on value error(stand in, (REF FILE f)BOOL: stop iteration);
DO # until user hits EOF #
  INT n;
  print("n? ");
  read((n, new line));
  print((number words(n), new line))
OD;
stop iteration:
  SKIP

Example input with output:

n? 43112609
forty-three million, one hundred and twelve thousand, six hundred and nine

Haskell

spellInteger :: Integer -> String
spellInteger n
 | n < 0     = error "spellInteger: negative input"
 | n < 20    = small n
 | n < 100   = let (a, b) = n `divMod` 10
               in  tens a ++ nonzero '-' b
 | n < 1000  = let (a, b) = n `divMod` 100
               in  small a ++ " hundred" ++ nonzero ' ' b
 | otherwise = join $ map big $ reverse $ filter ((/= 0) . snd) $
               zip [0..] $ unfoldr uff n

 where nonzero :: Char -> Integer -> String
       nonzero _ 0 = ""
       nonzero c n = c : spellInteger n

       join :: [String] -> String
       join [s]      = s
       join (s : ss) = s ++ ", " ++ join ss

       uff :: Integer -> Maybe (Integer, Integer)
       uff 0 = Nothing
       uff n = let (a, b) = n `divMod` 1000
               in  Just (b, a)

       small, tens :: Integer -> String
       small = (["zero", "one", "two", "three", "four", "five",
            "six", "seven", "eight", "nine", "ten", "eleven",
            "twelve", "thirteen", "fourteen", "fifteen", "sixteen",
            "seventeen", "eighteen", "nineteen"] !!) . fromEnum
       tens = ([undefined, undefined, "twenty", "thirty", "forty",
           "fifty", "sixty", "seventy", "eighty", "ninety"] !!) .
           fromEnum

       big :: (Int, Integer) -> String
       big (0, n) = spellInteger n
       big (1, n) = spellInteger n ++ " thousand"
       big (e, n) = spellInteger n ++ ' ' : (l !! e) ++ "illion"
         where l = [undefined, undefined, "m", "b", "tr", "quadr",
                   "quint", "sext", "sept", "oct", "non", "dec"]

J

u=. ;:'one two three four five six seven eight nine'
v=. ;:'ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen'
t=. ;:'twenty thirty forty fifty sixty seventy eighty ninety'
EN100=: '' ; u , v , , t ,&.>/ '';'-',&.>u

z=. '' ; 'thousand' ; (;:'m b tr quadr quint sext sept oct non'),&.> <'illion'
u=. ;:'un duo tre quattuor quin sex septen octo novem'
t=. (;:'dec vigint trigint quadragint quinquagint sexagint septuagint octogint nonagint'),&.><'illion'
ENU=: z , (, t ,~&.>/ '';u) , <'centillion'

en3=: 4 : 0
 'p q'=. 0 100#:y
 (p{::EN100),((*p)#' hundred'),((p*&*q)#x),q{::EN100
)

en=: 4 : 0
 d=. 1000&#.^:_1 y
 assert. (0<:y) *. ((=<.)y) *. d <:&# ENU
 c=. x&en3&.> (*d)#d
 ((0=y)#'zero') , (-2+*{:d) }. ; , c,.(<' '),.(ENU{~I.&.|.*d),.<', '
)

uk=: ' and '&en   NB. British
us=: ' '    &en   NB. American

Example:

   uk 123456789
one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine
   us 123456789
one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine


OCaml

<lang ocaml>let div_mod n d = (n / d, n mod d) let join = String.concat ", " ;;

let rec nonzero = function

 | _, 0 -> ""
 | c, n -> c ^ (spell_integer n)

and tens n =

 [| ""; ""; "twenty"; "thirty"; "forty"; "fifty";
            "sixty"; "seventy"; "eighty"; "ninety" |].(n)

and small n =

 [| "zero"; "one"; "two"; "three"; "four"; "five";
    "six"; "seven"; "eight"; "nine"; "ten"; "eleven";
    "twelve"; "thirteen"; "fourteen"; "fifteen";
    "sixteen";"seventeen"; "eighteen"; "nineteen" |].(n)

and bl = [| ""; ""; "m"; "b"; "tr"; "quadr"; "quint";

                   "sext"; "sept"; "oct"; "non"; "dec" |]

and big = function

 | 0, n -> (spell_integer n)
 | 1, n -> (spell_integer n) ^ " thousand"
 | e, n -> (spell_integer n) ^ " " ^ bl.(e) ^ "illion"

and uff acc = function

   | 0 -> List.rev acc
   | n ->
       let a, b = div_mod n 1000 in
       uff (b::acc) a

and spell_integer = function

 | n when n < 0 -> invalid_arg "spell_integer: negative input"
 | n when n < 20 -> small n
 | n when n < 100 ->
     let a, b = div_mod n 10 in
     (tens a) ^ nonzero("-", b)
 | n when n < 1000 ->
     let a, b = div_mod n 100 in
     (small a) ^ " hundred" ^ nonzero(" ", b)
 | n ->
     let seg = (uff [] n) in
     let _, segn =
       (* just add the index of the item in the list *)
       List.fold_left
         (fun (i,acc) v -> (succ i, (i,v)::acc))
         (0,[])
         seg
     in
     let fsegn =
       (* remove right part "zero" *)
       List.filter
         (function (_,0) -> false | _ -> true)
         segn
     in
     join(List.map big fsegn)
</lang>

Python

<lang python>def nonzero(c, n):

 if n == 0:
   return ""
 else:
   return c + spell_integer(n)

tens = ["", "", "twenty", "thirty", "forty",

       "fifty", "sixty", "seventy", "eighty", "ninety"]

small = ["zero", "one", "two", "three", "four", "five",

        "six", "seven", "eight", "nine", "ten", "eleven",
        "twelve", "thirteen", "fourteen", "fifteen", "sixteen",
        "seventeen", "eighteen", "nineteen"]

bl = ["", "", "m", "b", "tr", "quadr",

     "quint", "sext", "sept", "oct", "non", "dec"]

def big(e, n):

 if e == 0:
   return spell_integer(n)
 elif e == 1:
   return spell_integer(n) + " thousand"
 else:
   return spell_integer(n) + " " + bl[e] + "illion"

Generates the value of the digits of n in base 1000 (i.e. 3-digit chunks), in reverse. def base1000_rev(n):

 while n != 0:
   n, r = divmod(n, 1000)
   yield r

def spell_integer(n):

 if n < 0:
   raise ValueError, "spell_integer: negative input"
 elif n < 20:
   return small[n]
 elif n < 100:
   a, b = divmod(n, 10)
   return tens[a] + nonzero("-", b)
 elif n < 1000:
   a, b = divmod(n, 100)
   return small[a] + " hundred" + nonzero(" ", b)
 else:
   return ", ".join(reversed([big(e, x) for e, x in enumerate(base1000_rev(n)) if x != 0]))</lang>