Take the tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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[5]
share|improve this question
 
How should we represent ten thousand? MMMMMMMMMM or something else? –  ProgramFOX yesterday
 
@ProgramFOX That sounds right. I've changed the spec to under 10,000. –  Ben Reich yesterday
add comment

marked as duplicate by copy, Timtech, Johannes Kuhn, ProgramFOX, Quincunx 15 hours ago

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

8 Answers

Mathematica, 33 chars

FromDigits[InputString[],"Roman"]
share|improve this answer
 
I'd say "FromDigits" violates "no external resources, or the like". –  Sverre Rabbelier 23 hours ago
add comment

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;
share|improve this answer
 
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 yesterday
 
@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 yesterday
 
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 yesterday
add comment

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}
share|improve this answer
add comment

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[0]]+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[0]]+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]
share|improve this answer
 
I dig the 1e3 one-char savings but the question demands "integer output". –  Darren Stone yesterday
add comment

GolfScript: 83

0\{[77 68 67 76 88 86 73]?[1000 500 100 50 10 5 1]=}%{)@.@.@<{~)}{}if@.}do;{+\.}do;
share|improve this answer
 
If only we could make the mapping shorter... –  Dan G yesterday
 
Props to @DanG for the help –  Ben Reich yesterday
add comment

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]
    }
}
alert(a);

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.

Demo: http://jsfiddle.net/vSLfM/

share|improve this answer
add comment

Ruby, 134

i=gets
%w[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].map{|s|k,v=s.split ?,;i.gsub!(k,?++v)}
puts eval i
share|improve this answer
add comment

MS Excel,12

Enter a value in A1, then enter this in A2

=ARABIC(A1)
share|improve this answer
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.