Number names

From Rosetta Code
Revision as of 20:20, 17 April 2009 by rosettacode>Glennj
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

C++

<lang cpp>#include <string>

  1. include <iostream>

using std::string;

const char* smallNumbers[] = {

 "zero", "one", "two", "three", "four", "five",
 "six", "seven", "eight", "nine", "ten",
 "eleven", "twelve", "thirteen", "fourteen", "fifteen",
 "sixteen", "seventeen", "eighteen", "nineteen"

};

string spellHundreds(unsigned n) {

 string res;
 if (n > 99) {
   res = smallNumbers[n/100];
   res += " hundred";
   n %= 100;
   if (n) res += " and ";
 }
 if (n >= 20) {
   static const char* Decades[] = {
     "", "", "twenty", "thirty", "forty",
     "fifty", "sixty", "seventy", "eighty", "ninety"
   };
   res += Decades[n/10];
   n %= 10;
   if (n) res += "-";
 }
 if (n < 20 && n > 0)
   res += smallNumbers[n];
 return res;

}


const char* thousandPowers[] = {

 " billion", " million",  " thousand", "" };

typedef unsigned long Spellable;

string spell(Spellable n) {

 if (n < 20) return smallNumbers[n];
 string res;
 const char** pScaleName = thousandPowers;
 Spellable scaleFactor = 1000000000;	// 1 billion
 while (scaleFactor > 0) {
   if (n >= scaleFactor) {
     Spellable h = n / scaleFactor;
     res += spellHundreds(h) + *pScaleName;
     n %= scaleFactor;
     if (n) res += ", ";
   }
   scaleFactor /= 1000;
   ++pScaleName;
 }
 return res;

}

int main() {

  1. define SPELL_IT(x) std::cout << #x " " << spell(x) << std::endl;
 SPELL_IT(      99);
 SPELL_IT(     300);
 SPELL_IT(     310);
 SPELL_IT(    1501);
 SPELL_IT(   12609);
 SPELL_IT(  512609);
 SPELL_IT(43112609);
 SPELL_IT(1234567890);
 return 0;

}</lang> Sample output:

99 ninety-nine
300 three hundred
310 three hundred and ten
1501 one thousand, five hundred and one
12609 twelve thousand, six hundred and nine
512609 five hundred and twelve thousand, six hundred and nine
43112609 forty-three million, one hundred and twelve thousand, six hundred and nine
1234567890 one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety

D

<lang cpp>import std.stdio: writefln; import std.string: join;

string spell_integer(long n) {

   static string[] tens = [
       ""[], "", "twenty", "thirty", "forty",
       "fifty", "sixty", "seventy", "eighty", "ninety"];
   static string[] small = [
       "zero"[], "one", "two", "three", "four", "five",
        "six", "seven", "eight", "nine", "ten", "eleven",
        "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen"];
   static string[] bl = [""[], "", "m", "b", "tr", "quadr",
         "quint", "sext", "sept", "oct", "non", "dec"];
   string nonzero(string c, long n) {
       return n == 0 ? "" : c ~ spell_integer(n);
   }
   string big(long e, long n) {
       if (e == 0)
           return spell_integer(n);
       else if (e == 1)
           return spell_integer(n) ~ " thousand";
       else
           return spell_integer(n) ~ " " ~ bl[e] ~ "illion";
   }
   long[] base1000_rev(long n) {
       // generates the value of the digits of n in base 1000
       // (i.e. 3-digit chunks), in reverse.
       long[] result;
       while (n != 0) {
           result ~= n % 1000;
           n /= 1000;
       }
       return result;
   }
   if (n < 0) {
       throw new Exception("spell_integer: negative input");
   } else if (n < 20) {
       return small[n];
   } else if (n < 100) {
       return tens[n / 10] ~ nonzero("-", n % 10);
   } else if (n < 1000) {
       return small[n / 100] ~ " hundred" ~ nonzero(" ", n % 100);
   } else {
       string[] pieces;
       foreach (e, x; base1000_rev(n))
           pieces ~= big(e, x);
       return pieces.reverse.join(", ");
   }

}


void main() { // example

   for (int i; i < 1000; i++)
       writefln(spell_integer(i));

}</lang>

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

MAXScript

This example isn't a very succinct way to solve the problem, but the way it works should be quite obvious. The function will work for values up to 1000 <lang MAXScript> fn NumberToWord myNum = ( local Result = "" while myNum != 0 do ( Result += case of ( (myNum >= 1000):(myNum -= 1000; "one thousand") (myNum > 900): (myNum -= 900 ; "nine hundred and") (myNum == 900): (myNum -= 900 ; "nine hundred") (myNum > 800): (myNum -= 800 ; "eight hundred and") (myNum == 800): (myNum -= 900 ; "eight hundred") (myNum > 700): (myNum -= 700 ; "seven hundred and") (myNum == 700): (myNum -= 900 ; "seven hundred") (myNum > 600): (myNum -= 600 ; "six hundred and") (myNum == 600): (myNum -= 900 ; "six hundred") (myNum > 500): (myNum -= 500 ; "five hundred and") (myNum == 500): (myNum -= 900 ; "five hundred") (myNum > 400): (myNum -= 400 ; "four hundred and") (myNum == 400): (myNum -= 900 ; "four hundred") (myNum > 300): (myNum -= 300 ; "three hundred and") (myNum == 300): (myNum -= 900 ; "three hundred") (myNum > 200): (myNum -= 200 ; "two hundred and") (myNum == 200): (myNum -= 900 ; "two hundred") (myNum > 100): (myNum -= 100 ; "one hundred and") (myNum == 100): (myNum -= 100 ; "one hundred") (myNum >= 90): (myNum -= 90  ; "ninety") (myNum >= 80): (myNum -= 80  ; "eighty") (myNum >= 70): (myNum -= 70  ; "seventy") (myNum >= 60): (myNum -= 60  ; "sixty") (myNum >= 50): (myNum -= 50  ; "fifty") (myNum >= 40): (myNum -= 40  ; "fourty") (myNum >= 30): (myNum -= 30  ; "thirty") (myNum >= 20): (myNum -= 20  ; "twenty") (myNum >= 19): (myNum -= 19  ; "nineteen") (myNum >= 18): (myNum -= 18  ; "eighteen") (myNum >= 17): (myNum -= 17  ; "seventeen") (myNum >= 16): (myNum -= 16  ; "sixteen") (myNum >= 15): (myNum -= 15  ; "fifteen") (myNum >= 14): (myNum -= 14  ; "fourteen") (myNum >= 13): (myNum -= 13  ; "thirteen") (myNum >= 12): (myNum -= 12  ; "twelve") (myNum >= 11): (myNum -= 11  ; "eleven") (myNum >= 10): (myNum -= 10  ; "ten") (myNum >= 9): (myNum -= 9  ; "nine") (myNum >= 8): (myNum -= 8  ; "eight") (myNum >= 7): (myNum -= 7  ; "seven") (myNum >= 6): (myNum -= 6  ; "six") (myNum >= 5): (myNum -= 5  ; "five") (myNum >= 4): (myNum -= 4  ; "four") (myNum >= 3): (myNum -= 3  ; "three") (myNum >= 2): (myNum -= 2  ; "two") (myNum >= 1): (myNum -= 1  ; "one") ) if myNum != 0 then result += " " ) result ) </lang>

Example: <lang MAXScript> NumberToWord(123) </lang>

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 spell_integer(n):

   tens = [None, None, "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 = [None, None, "m", "b", "tr", "quadr",
         "quint", "sext", "sept", "oct", "non", "dec"]
   def nonzero(c, n):
       return "" if n == 0 else c + spell_integer(n)
   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"
   def base1000_rev(n):
       # generates the value of the digits of n in base 1000
       # (i.e. 3-digit chunks), in reverse.
       while n != 0:
           n, r = divmod(n, 1000)
           yield r
   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([big(e, x) for e, x in
                         enumerate(base1000_rev(n)) if x][::-1])
  1. example

print spell_integer(1278)</lang>

Tcl

<lang tcl>proc int2words {n} {

   if { ! [regexp -- {^(-?\d+)$} $n -> n]} {
       error "not a decimal integer"
   }
   if {$n == 0} {
       return zero
   }
   if {$n < 0} {
       return "negative [int2words [expr {abs($n)}]]"
   }
   if {[string length $n] > 36} {
       error "value too large to represent"
   }
   
   set groups [get_groups $n]
   set l [llength $groups]
   foreach group $groups {
       incr l -1
       # ensure any group with a leading zero is not treated as octal
       set val [scan $group %d]
       if {$val > 0} {
           lappend result [group2words $val $l]
       }
   }
   return [join $result ", "]

}

set small {"" one two three four five six seven eight nine ten eleven twelve

          thirteen fourteen fifteen sixteen seventeen eighteen nineteen}

set tens {"" "" twenty thirty forty fifty sixty seventy eighty ninety} set powers {"" thousand} foreach p {m b tr quadr quint sext sept oct non dec} {lappend powers ${p}illion}

proc group2words {n level} {

   global small tens powers
   if {$n < 20} {
       lappend result [lindex $small $n]
   } elseif {$n < 100} {
       lassign [divmod $n 10] a b
       set result [lindex $tens $a]
       if {$b > 0} {
           append result - [lindex $small $b]
       }
   } else {
       lassign [divmod $n 100] a b
       lappend result [lindex $small $a] hundred
       if {$b > 0} {
           lappend result and [group2words $b 0]
       }
   }
   return [join [concat $result [lindex $powers $level]]]

}

proc divmod {n d} {

   return [list [expr {$n / $d}] [expr {$n % $d}]]

}

proc get_groups {num} {

   # from http://wiki.tcl.tk/5000
   while {[regsub {^([-+]?\d+)(\d\d\d)} $num {\1 \2} num]} {}
   return [split $num]

}

foreach test {

       0 -0 5 -5 10 25 99 100 101 999 1000 1001 1234 54321 1234567890
       0x7F
       123456789012345678901234567890123456
       1234567890123456789012345678901234567

} {

   catch {int2words $test} result
   puts "$test -> $result"

}</lang> produces

0 -> zero
-0 -> zero
5 -> five
-5 -> negative five
10 -> ten
25 -> twenty-five
99 -> ninety-nine
100 -> one hundred
101 -> one hundred and one
999 -> nine hundred and ninety-nine
1000 -> one thousand
1001 -> one thousand, one
1234 -> one thousand, two hundred and thirty-four
54321 -> fifty-four thousand, three hundred and twenty-one
1234567890 -> one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety
0x7F -> not a decimal integer
123456789012345678901234567890123456 -> one hundred and twenty-three decillion, four hundred and fifty-six nonillion, seven hundred and eighty-nine octillion, twelve septillion, three hundred and forty-five sextillion, six hundred and seventy-eight quintillion, nine hundred and one quadrillion, two hundred and thirty-four trillion, five hundred and sixty-seven billion, eight hundred and ninety million, one hundred and twenty-three thousand, four hundred and fifty-six
1234567890123456789012345678901234567 -> value too large to represent