Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- defmodule Roman do
- @num_to_roman %{1 => "I", 2 => "II", 3 => "III", 4 => "IV", 5 => "V",
- 6 => "VI", 7 => "VII", 8 => "VIII", 9 => "IX", 10 => "X", 20 => "XX",
- 30 => "XXX", 40 => "XL", 50 => "L", 60 => "LX", 70 => "LXX", 80 => "LXXX",
- 90 => "XC", 100 => "C", 200 => "CC", 300 => "CCC", 400 => "CD", 500 => "D",
- 600 => "DC", 700 => "DCC", 800 => "DCCC", 900 => "CM", 1000 => "M",
- 2000 => "MM", 3000 => "MMM"}
- @roman_to_num %{"I" => 1, "II" => 2, "III" => 3, "IV" => 4, "V" => 5,
- "VI" => 6, "VII" => 7, "VIII" => 8, "IX" => 9, "X" => 10, "XX" => 20,
- "XXX" => 30, "XL" => 40, "L" => 50, "LX" => 60, "LXX" => 70, "LXXX" => 80,
- "XC" => 90, "C" => 100, "CC" => 200, "CCC" => 300, "CD" => 400, "D" => 500,
- "DC" => 600, "DCC" => 700, "DCCC" => 800, "CM" => 900, "M" => 1000,
- "MM" => 2000, "MMM" => 3000}
- @roman Map.keys @roman_to_num
- @invalid ["IIII", "VV", "XXXX", "LL", "CCCC", "DD", "MMMM"]
- def translate(input) when is_integer(input) do
- find_num(input) |> Enum.map_join(&Map.get(@num_to_roman, &1))
- end
- def translate(input) do
- if :binary.match(input, @invalid) == :nomatch and
- Regex.match?(~r/^["I", "V", "X", "L", "C", "D", "M"]*$/, input) do
- find_roman(input)
- else
- raise ArgumentError, message: "Erratum. Numerus invalidus est."
- end
- end
- defp find_num(number) when number > 3999 do
- raise ArgumentError, message: "Erratum. Numerus nimis magni est."
- end
- defp find_num(number) when number > 999 do
- [1000 * div(number, 1000), 100 * div(rem(number, 1000), 100),
- 10 * div(rem(number, 100), 10), rem(number, 10)]
- end
- defp find_num(number) when number > 99 do
- [100 * div(number, 100), 10 * div(rem(number, 100), 10), rem(number, 10)]
- end
- defp find_num(number) when number > 9 do
- [10 * div(number, 10), rem(number, 10)]
- end
- defp find_num(number) when number > 0, do: [number]
- defp find_num(_) do
- raise ArgumentError, message: "Erratum. Numerus invalidus est."
- end
- defp find_roman(input) do
- :binary.matches(input, @roman)
- |> Enum.map(&Map.get(@roman_to_num, :binary.part(input, &1)))
- |> Enum.sum
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement