Created
April 23, 2020 07:41
-
-
Save am-kantox/12d9996289e5c5c210d2fdc7152073e0 to your computer and use it in GitHub Desktop.
Roman → Arabic conversion for unlimited numbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule RomanNumerals do | |
require Integer | |
@romans 'IVXLCDM' | |
@spec numeral(pos_integer()) :: String.t() | |
def numeral(number, romans \\ @romans) do | |
fours = fn | |
<<c, c, c, c>>, [last], _f -> <<c, last>> | |
<<c, c, c, c>>, [c, next | _], _f -> <<c, next>> | |
<<next, c, c, c, c>>, [c, next, result | _], _f -> <<c, result>> | |
<<some, c, c, c, c>>, [c, next | _], _f -> <<some, c, next>> | |
input, [_ | next], f -> f.(input, next, f) | |
end | |
romans | |
|> Enum.with_index() | |
|> Enum.reverse() | |
|> Enum.reduce({number, []}, fn {c, i}, {number, acc} -> | |
denominator = | |
round( | |
if Integer.is_even(i), | |
do: :math.pow(10, i / 2), | |
else: 5 * :math.pow(10, (i - 1) / 2) | |
) | |
{ | |
rem(number, denominator), | |
acc ++ List.duplicate(c, div(number, denominator)) | |
} | |
end) | |
|> elem(1) | |
|> to_string() | |
|> String.replace(~r/.?(.)\1\1\1/, fn m -> fours.(m, romans, fours) end) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment