Skip to content

Instantly share code, notes, and snippets.

@mutablestate
Last active August 29, 2015 14:24
Show Gist options
  • Save mutablestate/1bfcfd17d41d4bbf73a1 to your computer and use it in GitHub Desktop.
Save mutablestate/1bfcfd17d41d4bbf73a1 to your computer and use it in GitHub Desktop.
My current Roman numeral exercism.io iteration
defmodule Roman do
@arabic_roman %{
1 => "I",
5 => "V",
10 => "X",
50 => "L",
100 => "C",
500 => "D",
1000 => "M"
}
@doc """
Convert the number to a roman number.
"""
@spec numerals(pos_integer) :: String.t
def numerals(number) do
number
|> digit_list
|> to_roman
end
@doc """
Split an integer into a 4 digit list padded with 0
"""
@spec digit_list(pos_integer) :: [pos_integer]
def digit_list(number) do
number
|> to_string
|> String.rjust(4, ?0)
|> String.codepoints
|> Enum.map &(String.to_integer(&1))
end
@doc """
Convert 4 digit list into Roman numeral string
"""
@spec to_roman([pos_integer]) :: String.t
def to_roman([thousands, hundreds, tens, ones]) do
convert(1000, thousands) <> convert(100, hundreds) <> convert(10, tens) <> convert(1, ones)
end
defp convert(_, 0), do: ""
defp convert(arabic, number) when number < 4, do: duplicate(arabic, number)
defp convert(arabic, 4), do: roman_concat(arabic, 5 * arabic)
defp convert(arabic, number) when number < 9 do
Map.get(@arabic_roman, arabic * 5) <> duplicate(arabic, number - 5)
end
defp convert(arabic, _), do: roman_concat(arabic, arabic * 10)
defp duplicate(arabic, number) do
String.duplicate(Map.get(@arabic_roman, arabic), number)
end
defp roman_concat(first, second) do
Map.get(@arabic_roman, first) <> Map.get(@arabic_roman, second)
end
end
if System.get_env("EXERCISM_TEST_EXAMPLES") do
Code.load_file("example.exs")
else
Code.load_file("roman.exs")
end
ExUnit.start
defmodule RomanTest do
use ExUnit.Case, async: true
test "1" do
assert Roman.numerals(1) == "I"
end
test "2" do
assert Roman.numerals(2) == "II"
end
test "3" do
assert Roman.numerals(3) == "III"
end
test "4" do
assert Roman.numerals(4) == "IV"
end
test "5" do
assert Roman.numerals(5) == "V"
end
test "6" do
assert Roman.numerals(6) == "VI"
end
test "9" do
assert Roman.numerals(9) == "IX"
end
test "27" do
assert Roman.numerals(27) == "XXVII"
end
test "48" do
assert Roman.numerals(48) == "XLVIII"
end
test "59" do
assert Roman.numerals(59) == "LIX"
end
test "93" do
assert Roman.numerals(93) == "XCIII"
end
test "141" do
assert Roman.numerals(141) == "CXLI"
end
test "163" do
assert Roman.numerals(163) == "CLXIII"
end
test "402" do
assert Roman.numerals(402) == "CDII"
end
test "575" do
assert Roman.numerals(575) == "DLXXV"
end
test "911" do
assert Roman.numerals(911) == "CMXI"
end
test "1024" do
assert Roman.numerals(1024) == "MXXIV"
end
test "3000" do
assert Roman.numerals(3000) == "MMM"
end
end
@mutablestate
Copy link
Author

Thanks for the feedback. Updated by removing the guard clauses for those 2 cases and using an integer in for the match.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment