Advertisement
Guest User

Untitled

a guest
Aug 4th, 2015
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.10 KB | None | 0 0
  1. defmodule Roman do
  2.  
  3. @num_to_roman %{1 => "I", 2 => "II", 3 => "III", 4 => "IV", 5 => "V",
  4. 6 => "VI", 7 => "VII", 8 => "VIII", 9 => "IX", 10 => "X", 20 => "XX",
  5. 30 => "XXX", 40 => "XL", 50 => "L", 60 => "LX", 70 => "LXX", 80 => "LXXX",
  6. 90 => "XC", 100 => "C", 200 => "CC", 300 => "CCC", 400 => "CD", 500 => "D",
  7. 600 => "DC", 700 => "DCC", 800 => "DCCC", 900 => "CM", 1000 => "M",
  8. 2000 => "MM", 3000 => "MMM"}
  9.  
  10. @roman_to_num %{"I" => 1, "II" => 2, "III" => 3, "IV" => 4, "V" => 5,
  11. "VI" => 6, "VII" => 7, "VIII" => 8, "IX" => 9, "X" => 10, "XX" => 20,
  12. "XXX" => 30, "XL" => 40, "L" => 50, "LX" => 60, "LXX" => 70, "LXXX" => 80,
  13. "XC" => 90, "C" => 100, "CC" => 200, "CCC" => 300, "CD" => 400, "D" => 500,
  14. "DC" => 600, "DCC" => 700, "DCCC" => 800, "CM" => 900, "M" => 1000,
  15. "MM" => 2000, "MMM" => 3000}
  16.  
  17. @roman Map.keys @roman_to_num
  18. @invalid ["IIII", "VV", "XXXX", "LL", "CCCC", "DD", "MMMM"]
  19.  
  20. def translate(input) when is_integer(input) do
  21. find_num(input) |> Enum.map_join(&Map.get(@num_to_roman, &1))
  22. end
  23.  
  24. def translate(input) do
  25. if :binary.match(input, @invalid) == :nomatch and
  26. Regex.match?(~r/^["I", "V", "X", "L", "C", "D", "M"]*$/, input) do
  27. find_roman(input)
  28. else
  29. raise ArgumentError, message: "Erratum. Numerus invalidus est."
  30. end
  31. end
  32.  
  33. defp find_num(number) when number > 3999 do
  34. raise ArgumentError, message: "Erratum. Numerus nimis magni est."
  35. end
  36. defp find_num(number) when number > 999 do
  37. [1000 * div(number, 1000), 100 * div(rem(number, 1000), 100),
  38. 10 * div(rem(number, 100), 10), rem(number, 10)]
  39. end
  40. defp find_num(number) when number > 99 do
  41. [100 * div(number, 100), 10 * div(rem(number, 100), 10), rem(number, 10)]
  42. end
  43. defp find_num(number) when number > 9 do
  44. [10 * div(number, 10), rem(number, 10)]
  45. end
  46. defp find_num(number) when number > 0, do: [number]
  47. defp find_num(_) do
  48. raise ArgumentError, message: "Erratum. Numerus invalidus est."
  49. end
  50.  
  51. defp find_roman(input) do
  52. :binary.matches(input, @roman)
  53. |> Enum.map(&Map.get(@roman_to_num, :binary.part(input, &1)))
  54. |> Enum.sum
  55. end
  56. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement