ryanzidago
What do you think of my solution for converting integers to roman numerals?
What do you think of my solution for converting integers to roman numerals?
defmodule RomanNumerals do
import IO, only: [iodata_to_binary: 1]
@doc """
Convert the number to a roman number.
"""
@spec numeral(pos_integer) :: String.t()
def numeral(0), do: ""
def numeral(1), do: "I"
def numeral(2), do: "II"
def numeral(3), do: "III"
def numeral(4), do: "IV"
def numeral(5), do: "V"
def numeral(6), do: "VI"
def numeral(7), do: "VII"
def numeral(8), do: "VIII"
def numeral(9), do: "IX"
def numeral(10), do: "X"
def numeral(50), do: "L"
def numeral(100), do: "C"
def numeral(500), do: "D"
def numeral(1000), do: "M"
def numeral(n) when n < 40, do: [numeral(10), numeral(n - 10)] |> iodata_to_binary()
def numeral(n) when n < 50, do: [numeral(10), numeral(50), numeral(n - 40)] |> iodata_to_binary()
def numeral(n) when n < 90, do: [numeral(50), numeral(n - 50)] |> iodata_to_binary()
def numeral(n) when n < 100, do: [numeral(10), numeral(100), numeral(n - 90)] |> iodata_to_binary()
def numeral(n) when n < 400, do: [numeral(100), numeral(n - 100)] |> iodata_to_binary()
def numeral(n) when n < 500, do: [numeral(100), numeral(500), numeral(n - 400)] |> iodata_to_binary()
def numeral(n) when n < 900, do: [numeral(500), numeral(n - 500)] |> iodata_to_binary()
def numeral(n) when n < 1000, do: [numeral(100), numeral(1000), numeral(n - 900)] |> iodata_to_binary()
def numeral(n) when n < 5000, do: [numeral(1000), numeral(n - 1000)] |> iodata_to_binary()
end
Most Liked
kokolegorille
Nice, but your spec is wrong. It should be non_neg_integer() as You do include 0 
NobbZ
Also, the spec does make the function appear unbound towards positive infinity.
In reality the spec should be numeral(0..4999) :: String.t().
In general, I do consider this appraoch as quite noisy, and also since iodata_to_binary/1 is used on each recursion step, nothing is gained by it. It might even perform worse than just using <>/2.
Last but not least, I’m not a friend of not using mix format.
ryanzidago
Nice catch!
Thanks @kokolegorille ! This is for such comments that I like to post on this forum.
NobbZ
Macro/Metaprogramming approaches are possible, though my approach usually just takes an ordered list of conversions and iterates over them.
My take inside, it might spoil you!`
defmodule Roman do
@arab_to_roman [
{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"}, {90, "XC"},
{50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}
]
@doc """
Convert the number to a roman number.
"""
@spec numerals(1..3999) :: String.t
def numerals(number) do
Enum.reduce(@arab_to_roman, {"", number}, fn ({ar, rm}, {acc, n}) ->
{acc <> String.duplicate(rm, div(n, ar)), rem(n, ar)}
end) |> elem(0)
end
end
PS: This was created when mix format did not yet exist.







