Number names: Difference between revisions
Content added Content deleted
(Ada solution added) |
|||
Line 253: | Line 253: | ||
us 123456789 |
us 123456789 |
||
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|OCaml}} == |
|||
<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 big = function |
|||
| 0, n -> spell_integer n |
|||
| 1, n -> (spell_integer n) ^ " thousand" |
|||
| e, n -> |
|||
let l = [| ""; ""; "m"; "b"; "tr"; "quadr"; "quint"; |
|||
"sext"; "sept"; "oct"; "non"; "dec" |] in |
|||
(spell_integer n) ^ " " ^ l.(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 left part "zero" *) |
|||
List.filter |
|||
(function (_,0) -> false | _ -> true) |
|||
segn |
|||
in |
|||
join(List.map big fsegn) |
|||
;;</ocaml> |
Revision as of 20:34, 5 December 2008
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Ada
<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; </ada> 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
<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 big = function
| 0, n -> spell_integer n | 1, n -> (spell_integer n) ^ " thousand" | e, n -> let l = [| ""; ""; "m"; "b"; "tr"; "quadr"; "quint"; "sext"; "sept"; "oct"; "non"; "dec" |] in (spell_integer n) ^ " " ^ l.(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 left part "zero" *) List.filter (function (_,0) -> false | _ -> true) segn in join(List.map big fsegn)
- </ocaml>