package com.pillar;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class RomanNumerals {

	final private Map<Integer, String> numeralByNumber;
	
	public RomanNumerals() {
		Map<Integer, String> numeralByNumber = new LinkedHashMap<Integer, String>();
		numeralByNumber.put(1, "I");
		numeralByNumber.put(5, "V");
		numeralByNumber.put(10, "X");
		numeralByNumber.put(50, "L");
		numeralByNumber.put(100, "C");
		numeralByNumber.put(1000, "M");
		this.numeralByNumber = numeralByNumber;
	}
	
	public String getNumeral(Integer number) {
		List<Entry<Integer,String>> tuple = findAdjacentNumerals(number); 
		return toNumeral(number, tuple);	
	}

	private String toNumeral(Integer number, List<Entry<Integer, String>> tuple) {
		Entry<Integer, String> lower = tuple.get(0);
		if(tuple.size() == 1){
			return lower.getValue();
		} else {
			Entry<Integer, String> upper = tuple.get(1);
			if(upper.getKey() - lower.getKey() == number){
				return lower.getValue() + upper.getValue();
			}else if(upper.getKey() - number < lower.getKey()){
				tuple = findAdjacentNumerals(lower.getKey() - 1);
				return toNumeral(number, Arrays.asList(tuple.get(0), upper));
			}else{
				return String.format("%s%s%s", lower.getValue(),lower.getValue(),lower.getValue());
			}
		}
	}

	private List<Entry<Integer, String>> findAdjacentNumerals(Integer number) {
		Entry<Integer, String> lower = null, upper = null;
		for(Entry<Integer, String> entry : numeralByNumber.entrySet()){
			if(number > entry.getKey()){
				lower = entry;
			}else if(number < entry.getKey()){
				upper = entry;
				break;
			}else{
				return Arrays.asList(entry);
			}
		}
		return Arrays.asList(lower, upper);
	}
	
}

@@ -804,24 +804,61 @@
 %3E%3E tuple) %7B%0A
+%09%09if(number == 0)%7B%0A%09%09%09return %22%22;%0A%09%09%7D%0A
 %09%09Entry%3CInte
@@ -892,16 +892,16 @@
 get(0);%0A
-
 %09%09if(tup
@@ -1004,16 +1004,118 @@
 get(1);%0A
+%09%09%09if(upper == null)%7B%0A%09%09%09%09return lower.getValue() + getNumeral(number - lower.getKey());%0A%09%09%09%7D else %7B%0A%09
 %09%09%09if(up
@@ -1156,16 +1156,17 @@
 umber)%7B%0A
+%09
 %09%09%09%09retu
@@ -1204,24 +1204,25 @@
 Value();%0A%09%09%09
+%09
 %7Delse if(upp
@@ -1218,19 +1218,23 @@
 else if(
-upp
+3 * low
 er.getKe
@@ -1241,159 +1241,565 @@
 y() 
--
+==
  number
- %3C lower.getKey())%7B%0A%09%09%09%09tuple = findAdjacentNumerals(lower.getKey() - 1);%0A%09%09%09%09return toNumeral(number, Arrays.asList(tuple.get(0), upper
+)%7B%0A%09%09%09%09%09return String.format(%22%25s%25s%25s%22, lower.getValue(),lower.getValue(),lower.getValue());%0A%09%09%09%09%7Delse if(upper.getKey() %3E number)%7B%0A%09%09%09%09%09Entry%3CInteger,String%3E lowest = findAdjacentNumerals(lower.getKey() - 1).get(0);%0A%09%09%09%09%09if(upper.getKey() - lower.getKey() == number)%7B%0A%09%09%09%09%09%09return lower.getValue() + upper.getValue() + getNumeral(number - (lower.getKey() - upper.getKey()));%0A%09%09%09%09%09%7Delse if(upper.getKey() - lowest.getKey() %3C= number)%7B%0A%09%09%09%09%09%09return lowest.getValue() + upper.getValue() + getNumeral(number - (upper.getKey() - lowest.getKey()
 ));%0A%09%09%09
+%09%09
 %7Dels
@@ -1809,38 +1809,142 @@
 %09%09%09%09
+%09
+%09
 return 
-String.format(%22%25s%25s%25s%22,
+lower.getValue() + lowest.getValue() + getNumeral(number - (lower.getKey() + lowest.getKey()));%0A%09%09%09%09%09%7D%0A%09%09%09%09%7Delse%7B%0A%09%09%09%09%09return
  low
@@ -1948,36 +1948,38 @@
 lower.getValue()
-,low
+ + upp
 er.getValue(),lo
@@ -1975,35 +1975,78 @@
 tValue()
-,lower.getValue());
+ + getNumeral(number - upper.getKey() - lower.getKey());%0A%09%09%09%09%7D
 %0A%09%09%09%7D%0A%09%09

RomanNumerals.getNumeral for input 1066 is passing (MLXVI)