Number names: Difference between revisions
(added C++ implementation) |
(→{{header|MAXScript}}: Added maxscript.) |
||
Line 334: | Line 334: | ||
one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine |
one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine |
||
== {{header|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> |
|||
== {{header|OCaml}} == |
== {{header|OCaml}} == |
Revision as of 18:53, 31 March 2009
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>
- 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() {
- 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
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 nonzero(c, n):
if n == 0: return "" else: return c + 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 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>