defmodule RomanNumerals do @letters [ %{:unitary => "I", :halfway => "V", :next => "X"}, %{:unitary => "X", :halfway => "L", :next => "C"}, %{:unitary => "C", :halfway => "D", :next => "M"}, %{:unitary => "M", :halfway => "" , :next => ""} ] @doc """ Convert the number to a roman number. """ @spec numeral(pos_integer) :: String.t() def numeral(number) do numeral(number, @letters) end defp numeral(0, _letters) do "" end defp numeral(number, [current | next]) do next_iteration = Integer.floor_div(number, 10) lower_part = number - (next_iteration * 10) numeral(next_iteration, next) <> letter(lower_part, current) end defp letter(single_value, map) do case single_value do 0 -> "" 1 -> String.duplicate(map[:unitary], 1) 2 -> String.duplicate(map[:unitary], 2) 3 -> String.duplicate(map[:unitary], 3) 4 -> map[:unitary] <> map[:halfway] 5 -> map[:halfway] 6 -> map[:halfway] <> String.duplicate(map[:unitary], 1) 7 -> map[:halfway] <> String.duplicate(map[:unitary], 2) 8 -> map[:halfway] <> String.duplicate(map[:unitary], 3) 9 -> map[:unitary] <> map[:next] # OR... # x when x == 0 -> "" # x when x >= 1 and x <= 3 -> String.duplicate(map[:unitary], x) # x when x == 4 -> map[:unitary] <> map[:halfway] # x when x == 5 -> map[:halfway] # x when x > 5 and x <= 8 -> map[:halfway] <> String.duplicate(map[:unitary], x - 5) # _ -> map[:unitary] <> map[:next] end end end