0

I am currently trying to write a program which converts integers from 0-3999 into Roman Numerals, and I have got the basis of the code correct, as when I type e.g. 6, it produces IIIIII. However, I want it to convert to the correct roman numeral, which would be VI. I feel there is something wrong with my While loop, but cannot seem to figure out why the Key in my TreeMap will always be 1, meaning the numeral will always be I. What is wrong with my code, and how do I alter it to give me the correct Roman Numeral. Any help will be appreciated.

    public String generate(int number) {
    // System.out.println("NUMBER: " + number);
    if (number < MinNumber || number > MaxNumber) {
        System.out.println("Number is out of range");
        return null;
    }

    StringBuilder romanToString = new StringBuilder();
    NavigableMap<Integer, String> romanMap = createRomanMap();
    // TreeMap<Integer, String> romanMap = createRomanMap();
    for (Map.Entry<Integer, String> entries : romanMap.entrySet()) {
        Integer key = entries.getKey();
        String value = entries.getValue();

        while (number >= key) {
            number -= key;
            romanToString.append(value);
        }
    }
    System.out.println("Stringbuilder:  " + romanToString.toString());
    return romanToString.toString();

}
John Lewis
  • 139
  • 1
  • 2
  • 15

1 Answers1

2

The issue is that you are traversing the TreeMap in its natural key ordering.

So consider a minimal Roman map like this, with this key ordering:

key = 1, value = "I"

key = 5, value = "V"

With the input 6 the following occurs:

First key = 1, first value = "I", number = 6

In your while loop you have 6 >= 1 => true, so append "I" and decrement 6 by the key 1.

This then repeats for 5, 4, 3, 2, 1 until the while loop invariant is broken.


However, if the Roman map is in descending order (i.e. reverse of the natural ordering), you will get the expected behavior:

First key = 5, first value = "V", number = 6

You now have 6 >= 5 => true, so append "V" and decrement 6 by the key 5, so 1. Then 1 >= 5 => false, so move onto the next Roman map entry.


How to achieve this?

Option 1

Use the descending map view's entry set:

Map.Entry<Integer, String> entrySet = romanMap.descendingMap().entrySet();

Option 2

Construct your TreeMap with a custom Comparator to change the ordering of the TreeMap, e.g.:

SortedMap<Integer, String> romanMap = new TreeMap<>((int1, int2) -> Integer.compare(int2, int1));

d.j.brown
  • 1,822
  • 1
  • 12
  • 14