Roman numeral converter function
C++: 914 855 chars
#include<map>
#include<string>
#include<iostream>
#include<sstream>
#define I istream
#define T(C) if(C)throw int(1);
#define X(c,v,f,m) D[c]=v;P[c]=D[f];M[c]=m;
#define S second
using namespace std;typedef map<char,int>R;R D,P,M;struct U{U():t(0),l(0),a(0){}int t,l,a;operator int(){return t+l;}I&d(I&s){char c,b;s>>c;if(c=='('){s>>c>>b;T(b!=')')c+=32;}if(s){R::iterator f=D.find(c);T(f==D.end())if(P[c]==l){l=f->S-l;a=0;}else{T(l&&(f->S>l))a=l==f->S?a+1:1;T(a>M[c])t+=l;l=f->S;}}return s;}};I&operator>>(I&s,U&d){return d.d(s);}int main(){D[' ']=-1;X(73,1,32,3)X(86,5,73,1)X(88,10,73,3)X(76,50,88,1)X(67,100,88,3)X(68,500,67,1)X(77,1000,67,3)X(118,5000,77,1)X(120,10000,77,3)X(108,50000,120,1)X(99,100000,120,3)X(100,500000,99,1)X(109,1000000,99,3)string w;while(cin>>w){try{stringstream s(w);U c;while(s>>c);cout<<c<<"\n";}catch(int x){cout<<"0\n";}}}
It could be compressed further.
> ./a.exe
III
3
IIII
0
XVI
16
(C)(D)(L)MMI
452001
Slightly nicer formatting: 1582 char
#include<map>
#include<string>
#include<iostream>
#include<sstream>
#define I istream
#define T(C) if(C)throw int(1);
#define X(c,v,f,m) D[c]=v;P[c]=D[f];M[c]=m;
#define S second
using namespace std;
typedef map<char,int> R;
R D,P,M;
struct U
{
U(): t(0), l(0), a(0) {}
int t,l,a;
operator int()
{
return t + l;
}
I& d(I& s)
{
char c,b;
s >> c;
if (c == '(')
{
s >> c >> b;
T(b != ')')
c = tolower(c);
}
if (s)
{
R::iterator f = D.find(c);
T(f == D.end())
if (P[c] == l)
{
l = f->S - l;
a = 0;
}
else
{
T(l&&(f->S > l))
a=l==f->S?a+1:1;
T(a>M[c])
t += l;
l = f->S;
}
}
return s;
}
};
I& operator>>(I& s,U& d)
{
return d.d(s);
}
int main()
{
D[' ']=-1;
X(73,1,32,3)
X(86,5,73,1)
X(88,10,73,3)
X(76,50,88,1)
X(67,100,88,3)
X(68,500,67,1)
X(77,1000,67,3)
X(118,5000,77,1)
X(120,10000,77,3)
X(108,50000,120,1)
X(99,100000,120,3)
X(100,500000,99,1)
X(109,1000000,99,3)
string w;
while(cin >> w)
{
try
{
stringstream s(w);
U c;
while(s >> c);
cout << c << "\n";
}
catch(int x)
{
cout << "0\n";
}
}
}
Javascript, 317 chars
function f(s){for(r=/\(?(.\)?)/g,t=e=0;a=r.exec(s);l=a[0].length,d='IXCMVLD'.indexOf(a[1][0]),e=e||d<0||l==2||d*4+l==3,t+='+'+(d>3?5:1)*Math.pow(10,d%4+3*(l>1)));t=t&&t.replace(/1(0*).(10|5)\1(?!0)/g,'$2$1-1$1');return e||/[^0](0*)\+(10|5)\1/.test(t)||/(\+10*)\1{3}(?!-)/.test(t)||/-(10*)\+\1(?!-)/.test(t)?0:eval(t)}
Explaination:
function f(s){
// iterate over every character grabbing parens along the way
for(r=/\(?(.\)?)/g,t=e=0;a=r.exec(s);
// get a numerical value for each numeral and join together in a string
l=a[0].length,
d='IXCMVLD'.indexOf(a[1][0]),
e=e||d<0||l==2||d*4+l==3, // find invalid characters, and parens
t+='+'+(d>3?5:1)*Math.pow(10,d%4+3*(l>1))
);
// reorder and subtract to fix IV, IX and the like
t=t&&t.replace(/1(0*).(10|5)\1(?!0)/g,'$2$1-1$1');
return e||
/[^0](0*)\+(10|5)\1/.test(t)|| // find VV,IIV,IC,...
/(\+10*)\1{3}(?!-)/.test(t)|| // find IIII,... but not XXXIX
/-(10*)\+\1(?!-)/.test(t) // find IVI,... but not XCIX
?0:eval(t)
}
Without error detection it is only 180 chars
function g(s){for(r=/\(?(.\)?)/g,t=0;a=r.exec(s);d='IXCMVLD'.indexOf(a[1][0]),t+='+'+(d>3?5:1)+'0'.repeat(d%4+3*(a[1].length>1)));return eval(t.replace(/(1(0*).(10|5)\2)/g,'-$1'))}
This works the same way, but here is better formatting:
function g(s){
for(r=/\(?(.\)?)/g,t=0;a=r.exec(s);
d='IXCMVLD'.indexOf(a[1][0]),
t+='+'+(d>3?5:1)+'0'.repeat(d%4+3*(a[1].length>1))
);
return eval(t.replace(/(1(0*).(10|5)\2)/g,'-$1'))
}