It's pronounced Diane. I do data architecture, operations, and backend development. In my spare time I maintain Massive.js, a data mapper for Node.js and PostgreSQL.
/**
* Find the appropriate divisor for a value, which, in the equation
* (val - val / divisor) will resolve to the threshold at or above which
* a subtractive maneuver is necessary to convert to Roman numerals.
*/privateintgetDivisor(intvalue){while(value>10){value=value/10;}returnvalue;}publicStringconvert(intarabic){StringBuildersb=newStringBuilder();// preserve a pointer to the last subtractable numeralMap.Entry<String,Integer>lastEntry=null;for(Map.Entry<String,Integer>e:numerals.entrySet()){if(lastEntry!=null){if(arabic>=4*e.getValue()){// we have a valid subtraction!sb.append(e.getKey());sb.append(lastEntry.getKey());arabic-=(lastEntry.getValue()-e.getValue());}else{// e isn't small enough for us to have a valid subtraction// yet, keep goingcontinue;}}// basic additive calculation: as long as the number is bigger than// e, keep appending ewhile(arabic>=e.getValue()){sb.append(e.getKey());arabic-=e.getValue();}if(arabic>=e.getValue()-(e.getValue()/getDivisor(e.getValue()))){// the remaining number is close enough to e that we will need// to perform a subtractive maneuver with reversed numeralslastEntry=e;}}returnsb.toString();}
pro:
the mapping only includes each Roman digit once
the algorithm is aesthetically pleasing (even if Java isn't the kindest to it)
con:
the algorithm is extremely complicated and the simpler mapping is absolutely not worth it
although it satisfied the battery of unit tests I was given, one of the interviewers had run an extra on it that demonstrated a bug. We all had fun picking it apart, but I don't recall what the exact problem is.
It's pronounced Diane. I do data architecture, operations, and backend development. In my spare time I maintain Massive.js, a data mapper for Node.js and PostgreSQL.
The way it works is by subtracting until you can add based only on the one-to-one mapping in descending order. So if you're trying to convert 1990, it goes like this:
1990, evaluate M (1000); 1990 > 1000 so we have an M, leaving 990 for the next iteration
990 is less than 1000 so MM is wrong, but it's more than 900 (1000 - (1000 / 10)), so we set the lastEntry pointer to M and proceed
Now we're evaluating C (100), but lastEntry is set. 990 > 900 which is CM, giving us MCM so far and leaving 90. I think this is where the bug is but it works in this case :)
90 > (100 - (100 / 10)) so lastEntry is now C
Evaluate L (50); lastEntry is set, but the calculation to test whether L can be subtracted fails, so we proceed
Evaluate X (10): the subtraction test succeeds, so 90 becomes XC and the full result is MCMXC.
The last code test I took for an interview involved writing a calculator in Java:
pro:
con:
Whew man, I donβt know Java at all, so this looks really complicated to me.
The way it works is by subtracting until you can add based only on the one-to-one mapping in descending order. So if you're trying to convert 1990, it goes like this:
1000 - (1000 / 10)
), so we set thelastEntry
pointer to M and proceedlastEntry
is set. 990 > 900 which is CM, giving us MCM so far and leaving 90. I think this is where the bug is but it works in this case :)100 - (100 / 10)
) solastEntry
is now ClastEntry
is set, but the calculation to test whether L can be subtracted fails, so we proceedNice thatβs such a cool way of thinking about it!