# Convert arbitrary roman numeral input to integer output [duplicate]

This question already has an answer here:

The usual rules: no external resources, or the like. Input will be a positive integer in valid Roman numeral format less than 10 thousand, say.

Use all the Roman numeral characters:

• I = 1
• V = 5
• X = 10
• L = 50
• C = 100
• D = 500
• M = 1,000

Respect subtractive notation (copied from the Wikipedia page):

• the numeral I can be placed before V and X to make 4 units (IV) and 9 units (IX) respectively
• X can be placed before L and C to make 40 (XL) and 90 (XC) respectively
• C can be placed before D and M to make 400 (CD) and 900 (CM) according to the same pattern

## marked as duplicate by copy, Timtech, Johannes Kuhn, ProgramFOX, JustinDec 28 '13 at 9:38

• How should we represent ten thousand? MMMMMMMMMM or something else? – ProgramFOX Dec 27 '13 at 15:34
• @ProgramFOX That sounds right. I've changed the spec to under 10,000. – Ben Reich Dec 27 '13 at 15:37

# Mathematica, 33 chars

FromDigits[InputString[],"Roman"]

• I'd say "FromDigits" violates "no external resources, or the like". – Sverre Rabbelier Dec 28 '13 at 1:53

JavaScript, 98 91 characters:

for(k=d=l=0,a=prompt();i={I:1,V:5,X:10,L:50,C:100,D:500,M:1e3}[a[k++]];l=i)d+=i>l?i-2*l:i;d


Expanded form:

a = prompt(), // a is input string
d = 0,        // d is result sum
l = 0,        // l is last value processed (for comparison with current val)
k = 0,        // k is current position in string

v = {I:1,V:5,X:10,L:50,C:100,D:500,M:1e3}; // map of values

// for each char in string a[k] (left to right), put its base-10 value in i
while(i = v[a[k++]]) {

// if previous left-side value is lower than this value,
//     it should have been substracted, so subject twice its value
//     (once to negate the past addition, and again to apply negative value)
// regardless, add this value
if(i>l) {
d += i - 2*l;
} else {
d += i;
}

// store this value as previous value
l=i;
}

// yield result
d;

• You can save some characters by removing l=i and replacing d+=i>l?i-2*l:i with d+=i>l?i-2*l:l=i – ProgramFOX Dec 27 '13 at 16:37
• @ProgramFOX This doesn't quite seem to work, because l doesn't get reassigned in the true case. (For example: IX is rendered as 11.) This may have worked in my previous right-to-left code, but I think this doesn't apply anymore. – apsillers Dec 27 '13 at 16:50
• Oh yes, that's true. You also need to replace your > condition with >= if you want to remove the l=i condition. I don't know whether it still saves characters then, though. – ProgramFOX Dec 27 '13 at 16:52

Scala 195

val t=Map('I'->1,'V'->5,'X'->10,'L'->50,'C'->100,'D'->500,'M'->1000)
def f(n:String)={val r=n.substring(1).foldLeft((0,t(n.head)))((a,x)=>(if(a._2>=t(x))a._1+a._2 else a._1-a._2,t(x)));r._1+r._2}


## GolfScript: 83

0\{[77 68 67 76 88 86 73]?[1000 500 100 50 10 5 1]=}%{)@.@.@<{~)}{}if@.}do;{+\.}do;

• If only we could make the mapping shorter... – Dan G Dec 27 '13 at 21:57
• Props to @DanG for the help – Ben Reich Dec 27 '13 at 21:57

# MS Excel,12

Enter a value in A1, then enter this in A2

=ARABIC(A1)

• If you change the language to Google Sheets you can drop the terminal ) for -1 Byte – Taylor Scott Nov 5 '17 at 15:07

Python 201 characters

m={'IV':4,'IX':9,'XL':40,'XC':90,'CD':400,'CM':900,'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
f=lambda s:m[s] if s in m else(m[s[:2]]+f(s[2:])if s[:2]in m else m[s]+f(s[1:]))
f(raw_input())


Example:

>>> m={'IV':4,'IX':9,'XL':40,'XC':90,'CD':400,'CM':900,'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000};f=lambda s:m[s] if s in m else(m[s[:2]]+f(s[2:])if s[:2]in m else m[s]+f(s[1:]));f(raw_input())
MMMCMLXXXVII
3987


119 117 characters

>>> X=[dict(zip('MDCLXVI',(1e3,500,100,50,10,5,1)))[x]for x in raw_input()];sum((x,-x)[x<y]for x,y in zip(X,X[1:]))+X[-1]
MMMCMLXXXVII
3987.0


Expanded form:

>>> # Maps roman numbers to their decimal counterpart
>>> roman_map = dict(zip('MDCLXVI',(1e3,500,100,50,10,5,1)))
>>> # Maps the list of input number to the corresponding decimals
>>> X=[roman_map[x]for x in raw_input()]
>>> # A number will be added (x) or subtracted (-x) depending on its value vs the next number
>>> # For instance CM -> [100, 1000], 100 < 1000, therefore -100, +1000
>>> result = sum((x,-x)[x<y] for x,y in zip(X,X[1:])) # True = 1, False = 0
>>> # Adding the last element (which is always added)
>>> result += X[-1]

• I dig the 1e3 one-char savings but the question demands "integer output". – Darren Stone Dec 27 '13 at 19:01

## JavaScript, 198 characters

n={I:1,V:5,X:10,L:50,C:100,D:500,M:1e3,IV:4,IX:9,XL:40,XC:90,CD:400,CM:900},s=prompt(),a=i=0;for(;i<s.length;i++){b=(j)=>s.substr(j,1);c=b(i);d=b(i+1);e=n[c+d];if(e){a+=e;i++}else{a+=n[c]}}alert(a);


The ungolfed code:

n = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1e3,
IV: 4,
IX: 9,
XL: 40,
XC: 90,
CD: 400,
CM: 900
}, s = prompt(), a = i = 0;
for (; i < s.length; i++) {
b = (j) => s.substr(j, 1);
c = b(i);
d = b(i + 1);
e = n[c + d];
if (e) {
a += e;
i++
} else {
a += n[c]
}
}

How this works: first, you store all values inside an object. Then, you prompt for input and you loop over all characters in the string. If the current character + the next character are a number (CM for example), then look up current char + next char in the object. If current char + next char isn't available in the object, just look up the current char.
i=gets