58 lines
1.6 KiB
OCaml
58 lines
1.6 KiB
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)
|
|
;;
|