Roman Numerals Encoder in Java


The challenge

Create a function taking a positive integer as its parameter and returning a string containing the Roman Numeral representation of that integer.

Modern Roman numerals are written by expressing each digit separately starting with the left most digit and skipping any digit with a value of zero. In Roman numerals 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC. 2008 is written as 2000=MM, 8=VIII; or MMVIII. 1666 uses each Roman symbol in descending order: MDCLXVI.

Example:

conversion.solution(1000); //should return "M"

Help:

Symbol    Value
I          1
V          5
X          10
L          50
C          100
D          500
M          1,000

Remember that there can’t be more than 3 identical symbols in a row.

More about roman numerals – http://en.wikipedia.org/wiki/Roman_numerals

The solution in Java code

Option 1:

public class Conversion {

    public String solution(int number) {
        String romanNumbers[] = {"M", "CMXC", "CM", "D", "CDXC", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
        int arab[] = {1000, 990, 900, 500, 490, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        StringBuilder result = new StringBuilder();
        int i = 0;
        while (number > 0 || arab.length == (i - 1)) {
            while ((number - arab[i]) >= 0) {
                number -= arab[i];
                result.append(romanNumbers[i]);
            }
            i++;
        }
        return result.toString();
    }
}

Option 2:

public class Conversion {

    public String solution(int n) {
        final String[] digit = {"", "I", "II", "III", "IV", "V", "VI", "VII",
                                  "VIII", "IX"};
        final String[] ten = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX",
                                  "LXXX", "XC"};
        final String[] hundred = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC",
                                  "DCCC", "CM"};
        final String[] thousand = {"", "M", "MM", "MMM"};
        
        String result="";
        result = thousand[n/1000] + hundred[n%1000/100] + ten[n%100/10] +
                  digit[n%10];
        return result;
    }
}

Option 3:

public class Conversion {

    public String solution(int n) {
        String[] strs = new String[n];
        java.util.Arrays.fill(strs, "I");
        String result = java.util.Arrays.toString(strs).replaceAll("[ \\[\\],]","");
        result = result.replaceAll("[I]{5}","V");
        result = result.replaceAll("[V]{2}","X");
        result = result.replaceAll("[X]{5}","L");
        result = result.replaceAll("[L]{2}","C");
        result = result.replaceAll("[C]{5}","D");
        result = result.replaceAll("[D]{2}","M");
        result = result.replaceAll("D[C]{4}","CM");
        result = result.replaceAll("[L]{4}","CD");
        result = result.replaceAll("L[X]{4}","XC");
        result = result.replaceAll("[X]{4}","XL");
        result = result.replaceAll("V[I]{4}","IX");
        result = result.replaceAll("[I]{4}","IV");
        return result;
    }
}

Test cases to validate our solution

import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ConversionTest {

    private Conversion conversion = new Conversion();

    @Test
    public void shouldConvertToRoman() {
        assertEquals("solution(1) should equal to I", "I", conversion.solution(1));
        assertEquals("solution(4) should equal to IV", "IV", conversion.solution(4));
        assertEquals("solution(6) should equal to VI", "VI", conversion.solution(6));
    }
}