49 lines
1.7 KiB
Plaintext
49 lines
1.7 KiB
Plaintext
defmodule RC do
|
|
@small ~w(zero one two three four five six seven eight nine ten
|
|
eleven twelve thirteen fourteen fifteen sixteen seventeen
|
|
eighteen nineteen)
|
|
@tens ~w(wrong wrong twenty thirty forty fifty sixty seventy eighty ninety)
|
|
@big [nil, "thousand"] ++
|
|
(~w( m b tr quadr quint sext sept oct non dec) |> Enum.map(&"#{&1}illion"))
|
|
|
|
def wordify(number) when number<0, do: "negative #{wordify(-number)}"
|
|
def wordify(number) when number<20, do: Enum.at(@small,number)
|
|
def wordify(number) when number<100 do
|
|
rm = rem(number,10)
|
|
Enum.at(@tens,div(number,10)) <> (if rm==0, do: "", else: "-#{wordify(rm)}")
|
|
end
|
|
def wordify(number) when number<1000 do
|
|
rm = rem(number,100)
|
|
"#{Enum.at(@small,div(number,100))} hundred" <> (if rm==0, do: "", else: " and #{wordify(rm)}")
|
|
end
|
|
def wordify(number) do
|
|
# separate into 3-digit chunks
|
|
chunks = chunk(number, [])
|
|
if length(chunks) > length(@big), do: raise(ArgumentError, "Integer value too large.")
|
|
Enum.map(chunks, &wordify(&1))
|
|
|> Enum.zip(@big)
|
|
|> Enum.filter_map(fn {a,_} -> a != "zero" end, fn {a,b} -> "#{a} #{b}" end)
|
|
|> Enum.reverse
|
|
|> Enum.join(", ")
|
|
end
|
|
|
|
defp chunk(0, res), do: Enum.reverse(res)
|
|
defp chunk(number, res) do
|
|
chunk(div(number,1000), [rem(number,1000) | res])
|
|
end
|
|
end
|
|
|
|
data = [-1123, 0, 1, 20, 123, 200, 220, 1245, 2000, 2200, 2220, 467889,
|
|
23_000_467, 23_234_467, 2_235_654_234, 12_123_234_543_543_456,
|
|
987_654_321_098_765_432_109_876_543_210_987_654,
|
|
123890812938219038290489327894327894723897432]
|
|
|
|
Enum.each(data, fn n ->
|
|
IO.write "#{n}: "
|
|
try do
|
|
IO.inspect RC.wordify(n)
|
|
rescue
|
|
e in ArgumentError -> IO.puts Exception.message(e)
|
|
end
|
|
end)
|