# Data flow with pipe and solving a Roman numerals problem

This is an interesting problem I encountered while solving some challenges in the Exercism site. The challenge is the idea of transforming a number into its roman numeral.

Some examples:

``````1 # => I
2 # => II
4 # => IV
27 # => XXVII
48 # => XLVIII
141 # => CXLI
575 # => DLXXV
1024 # => MXXIV
``````

One idea to solve this problem is to transform each digit of the number and then join them together. To transform each digit, we need to know two pieces of information: the digit and if the digit is from the digit, dozens, hundreds, or thousands box.

To know that, we can use the help of an index. Let's see the algorithm:

What are we doing here?

• Transform the integer to a string
• Reverse the string: we only reverse the string because we want to make it easier to use the index.
• Split string into a list of chars: transform the string into a list to reduce it.
• Reduce to build the roman numeral: for each digit, we use the digit and the index to map to a roman numeral and then concat them all.

To transform a number into a string, we can use the `Integer.to_string()`, then we reverse the string with `String.reverse()`, split each string character with the `String.split("", trim: true)` function, and finally we can use the reduce function to build the final roman string.

As I showed in the illustration above, we will use the index to know the type of the digit (digit, dozens, hundreds, thousands), and then map the roman numeral. To map from digit to roman, I created 3 maps:

• for digit
``````@digit_to_roman %{
"0" => "",
"1" => "I",
"2" => "II",
"3" => "III",
"4" => "IV",
"5" => "V",
"6" => "VI",
"7" => "VII",
"8" => "VIII",
"9" => "IX"
}
``````
• for dozens
``````@dozens_to_roman %{
"0" => "",
"1" => "X",
"2" => "XX",
"3" => "XXX",
"4" => "XL",
"5" => "L",
"6" => "LX",
"7" => "LXX",
"8" => "LXXX",
"9" => "XC"
}
``````
• for hundreds
``````@hundreds_to_roman %{
"0" => "",
"1" => "C",
"2" => "CC",
"3" => "CCC",
"4" => "CD",
"5" => "D",
"6" => "DC",
"7" => "DCC",
"8" => "DCCC",
"9" => "CM"
}
``````
• for thousands
``````@thousands_to_roman %{
"0" => "",
"1" => "M",
"2" => "MM",
"3" => "MMM",
"4" => "MMMM"
}
``````

Now we can implement a simple function to use the index to choose which map it'll use:

``````defp to_roman(digit, index) do
case index do
0 ->
@digit_to_roman[digit]
1 ->
@dozens_to_roman[digit]
2 ->
@hundreds_to_roman[digit]
3 ->
@thousands_to_roman[digit]
end
end
``````

And finally, the reducer function to build the roman numeral string:

``````defp build_roman_numeral({string_digit, index}, roman) do
to_roman(string_digit, index) <> roman
end
``````

The flow looks like this:

``````def numeral(number) do
number
|> Integer.to_string()
|> String.reverse()
|> String.split("", trim: true)
|> Enum.with_index()
|> Enum.reduce("", &build_roman_numeral/2)
end
``````

And the code looks like this:

``````defmodule RomanNumerals do
@digit_to_roman %{
"0" => "",
"1" => "I",
"2" => "II",
"3" => "III",
"4" => "IV",
"5" => "V",
"6" => "VI",
"7" => "VII",
"8" => "VIII",
"9" => "IX"
}

@dozens_to_roman %{
"0" => "",
"1" => "X",
"2" => "XX",
"3" => "XXX",
"4" => "XL",
"5" => "L",
"6" => "LX",
"7" => "LXX",
"8" => "LXXX",
"9" => "XC"
}

@hundreds_to_roman %{
"0" => "",
"1" => "C",
"2" => "CC",
"3" => "CCC",
"4" => "CD",
"5" => "D",
"6" => "DC",
"7" => "DCC",
"8" => "DCCC",
"9" => "CM"
}

@thousands_to_roman %{
"0" => "",
"1" => "M",
"2" => "MM",
"3" => "MMM",
"4" => "MMMM"
}

def numeral(number) do
number
|> Integer.to_string()
|> String.reverse()
|> String.split("", trim: true)
|> Enum.with_index()
|> Enum.reduce("", &build_roman_numeral/2)
end

defp build_roman_numeral({string_digit, index}, roman) do
to_roman(string_digit, index) <> roman
end

defp to_roman(digit, index) do
case index do
0 ->
@digit_to_roman[digit]
1 ->
@dozens_to_roman[digit]
2 ->
@hundreds_to_roman[digit]
3 ->
@thousands_to_roman[digit]
end
end
end
``````

It's so fun to think in functional programming when solving a problem.