Packages
A Gleam library for converting between Roman numerals and integers, with support for both string and structured representations.
Retired package: package retired by author
Current section
Files
Jump to
Current section
Files
src/roman.erl
-module(roman).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/roman.gleam").
-export([string_to_roman/1, roman_to_int/1, int_to_roman/1, roman_to_string/1]).
-export_type([numeral/0, roman_error/0]).
-type numeral() :: i | v | x | l | c | d | m.
-type roman_error() :: invalid_numeral_char_input |
zero_or_negative_integer_input.
-file("src/roman.gleam", 23).
-spec numeral_value(numeral()) -> integer().
numeral_value(Numeral) ->
case Numeral of
i ->
1;
v ->
5;
x ->
10;
l ->
50;
c ->
100;
d ->
500;
m ->
1000
end.
-file("src/roman.gleam", 35).
-spec numeral_to_str(numeral()) -> binary().
numeral_to_str(Numeral) ->
case Numeral of
i ->
<<"i"/utf8>>;
v ->
<<"v"/utf8>>;
x ->
<<"x"/utf8>>;
l ->
<<"l"/utf8>>;
c ->
<<"c"/utf8>>;
d ->
<<"d"/utf8>>;
m ->
<<"m"/utf8>>
end.
-file("src/roman.gleam", 47).
-spec numeral_from_str(binary()) -> {ok, numeral()} | {error, roman_error()}.
numeral_from_str(Char) ->
case Char of
<<"i"/utf8>> ->
{ok, i};
<<"v"/utf8>> ->
{ok, v};
<<"x"/utf8>> ->
{ok, x};
<<"l"/utf8>> ->
{ok, l};
<<"c"/utf8>> ->
{ok, c};
<<"d"/utf8>> ->
{ok, d};
<<"m"/utf8>> ->
{ok, m};
_ ->
{error, invalid_numeral_char_input}
end.
-file("src/roman.gleam", 62).
-spec string_to_roman(binary()) -> {ok, list(numeral())} |
{error, roman_error()}.
string_to_roman(Input) ->
Chars = gleam@string:split(Input, <<""/utf8>>),
gleam@list:try_map(Chars, fun numeral_from_str/1).
-file("src/roman.gleam", 67).
-spec roman_to_int_recursive(list(integer()), integer(), integer()) -> integer().
roman_to_int_recursive(Reversed_values, Max, Total) ->
case Reversed_values of
[] ->
Total;
[First | Rest] ->
case First >= Max of
true ->
roman_to_int_recursive(Rest, First, Total + First);
false ->
roman_to_int_recursive(Rest, Max, Total - First)
end
end.
-file("src/roman.gleam", 87).
-spec roman_to_int(list(numeral())) -> integer().
roman_to_int(Roman) ->
_pipe = Roman,
_pipe@1 = gleam@list:map(_pipe, fun numeral_value/1),
_pipe@2 = lists:reverse(_pipe@1),
roman_to_int_recursive(_pipe@2, 0, 0).
-file("src/roman.gleam", 94).
-spec append_primary(integer(), numeral(), list(numeral())) -> {integer(),
list(numeral())}.
append_primary(Val, Primary, Numerals) ->
Primary_val = begin
_pipe = Primary,
numeral_value(_pipe)
end,
case Val >= Primary_val of
true ->
New_val = Val - Primary_val,
append_primary(New_val, Primary, lists:append(Numerals, [Primary]));
false ->
{Val, Numerals}
end.
-file("src/roman.gleam", 109).
-spec loop_mappings(integer(), list({numeral(), numeral()}), list(numeral())) -> {integer(),
list(numeral())}.
loop_mappings(Val, Mappings, Numerals) ->
case Mappings of
[] ->
{Val, Numerals};
[{Secondary, Primary} | Rest] ->
{New_val, Numerals@1} = append_primary(Val, Primary, Numerals),
Diff = numeral_value(Primary) - numeral_value(Secondary),
case Val >= Diff of
true ->
New_val@1 = New_val - Diff,
Numerals@2 = lists:append(Numerals@1, [Secondary, Primary]),
loop_mappings(New_val@1, Rest, Numerals@2);
false ->
loop_mappings(New_val, Rest, Numerals@1)
end
end.
-file("src/roman.gleam", 131).
-spec dec_until_zero(integer(), list(numeral())) -> {integer(), list(numeral())}.
dec_until_zero(Val, Numerals) ->
case Val > 0 of
true ->
dec_until_zero(Val - 1, lists:append(Numerals, [i]));
false ->
{Val, Numerals}
end.
-file("src/roman.gleam", 140).
-spec int_to_roman(integer()) -> {ok, list(numeral())} | {error, roman_error()}.
int_to_roman(Val) ->
case gleam@int:compare(Val, 0) of
gt ->
Mappings = [{c, m}, {c, d}, {x, c}, {x, l}, {i, x}, {i, v}],
{New_val, Numerals} = loop_mappings(Val, Mappings, []),
{_, Numerals@1} = dec_until_zero(New_val, Numerals),
{ok, Numerals@1};
_ ->
{error, zero_or_negative_integer_input}
end.
-file("src/roman.gleam", 153).
-spec roman_to_string(list(numeral())) -> binary().
roman_to_string(Numerals) ->
case Numerals of
[] ->
<<""/utf8>>;
[First | Rest] ->
<<(numeral_to_str(First))/binary, (roman_to_string(Rest))/binary>>
end.