75 lines
2.1 KiB
Elixir
75 lines
2.1 KiB
Elixir
defmodule Say do
|
|
@in_english_19 %{
|
|
1 => "one",
|
|
2 => "two",
|
|
3 => "three",
|
|
4 => "four",
|
|
5 => "five",
|
|
6 => "six",
|
|
7 => "seven",
|
|
8 => "eight",
|
|
9 => "nine",
|
|
10 => "ten",
|
|
11 => "eleven",
|
|
12 => "twelve",
|
|
13 => "thirteen",
|
|
14 => "fourteen",
|
|
15 => "fifteen",
|
|
16 => "sixteen",
|
|
17 => "seventeen",
|
|
18 => "eighteen",
|
|
19 => "nineteen"
|
|
}
|
|
|
|
@in_english_100 %{
|
|
2 => "twenty",
|
|
3 => "thirty",
|
|
4 => "forty",
|
|
5 => "fifty",
|
|
6 => "sixty",
|
|
7 => "seventy",
|
|
8 => "eighty",
|
|
9 => "ninety"
|
|
}
|
|
|
|
@doc """
|
|
Translate a positive integer into English.
|
|
"""
|
|
@spec in_english(integer) :: {atom, String.t()}
|
|
def in_english(number) when number < 0 or number > 999_999_999_999,
|
|
do: {:error, "number is out of range"}
|
|
|
|
def in_english(0), do: {:ok, "zero"}
|
|
|
|
def in_english(number) do
|
|
{:ok,
|
|
number
|
|
|> Integer.digits()
|
|
|> Enum.reverse()
|
|
|> Enum.chunk_every(3)
|
|
|> Enum.with_index(fn element, index -> in_english_part(element, index) end)
|
|
|> Enum.reverse()
|
|
|> List.flatten()
|
|
|> Enum.reject(&is_nil/1)
|
|
|> Enum.join(" ")
|
|
}
|
|
end
|
|
|
|
@spec in_english_part([integer], integer) :: String.t()
|
|
defp in_english_part([0, 0, 0], _index), do: []
|
|
defp in_english_part(element, 3), do: [do_in_english_part(element) | ["billion"]]
|
|
defp in_english_part(element, 2), do: [do_in_english_part(element) | ["million"]]
|
|
defp in_english_part(element, 1), do: [do_in_english_part(element) | ["thousand"]]
|
|
defp in_english_part(element, 0), do: [do_in_english_part(element)]
|
|
|
|
defp do_in_english_part([d1, d2, d3]) when d3 != 0, do: [@in_english_19[d3], "hundred" | [do_in_english_part([d1, d2])]]
|
|
defp do_in_english_part([d1, d2, 0]), do: do_in_english_part([d1, d2])
|
|
defp do_in_english_part([d1, d2]) when d2 < 2, do: @in_english_19[Integer.undigits([d2, d1])]
|
|
defp do_in_english_part([0, d2]) when d2 > 1, do: @in_english_100[d2]
|
|
|
|
defp do_in_english_part([d1, d2]) when d2 > 1,
|
|
do: @in_english_100[d2] <> "-" <> @in_english_19[d1]
|
|
|
|
defp do_in_english_part([d1]), do: @in_english_19[d1]
|
|
end
|