Skip to content

Instantly share code, notes, and snippets.

@vo
Created September 11, 2010 03:25
Show Gist options
  • Save vo/574749 to your computer and use it in GitHub Desktop.
Save vo/574749 to your computer and use it in GitHub Desktop.
// Problem H: Reverse Roman Notation
// Author: Christopher Vo
#include <iostream>
#include <stack>
#include <string>
using namespace std;
stack<int> sys;
// exceptions
class Underflow {};
class DivByZero {};
class OutOfRange {};
class IllegalChar {};
// roman number digits
const string d[] = {"M","CM","D","CD","C","XC",
"L","XL","X","IX","V","IV","I"};
const int v[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
// get num at top of stack
int top() {
if(sys.empty()) throw Underflow();
return sys.top();
}
// get two arguments from the stack
void pop_args(int & a1, int & a2) {
if(sys.size()<2) throw Underflow();
a1 = sys.top();
sys.pop();
a2 = sys.top();
sys.pop();
}
// convert integer to roman
string ator(int a) {
int i; string r;
for(i=0;a>0&&i<13;i++) {
while(v[i]<=a) {
r+=d[i];
a-=v[i];
}
}
return r;
}
// get index of roman string
int get_index(string x) {
for(int i=0;i<13;i++)
if(d[i]==x) return i;
return -1;
}
// convert roman to integer
int rtoa(string r) {
int i,res=0,last=0,n=r.length();
for(i=n-1;i>=0;--i) {
int p = get_index(r.substr(i,1));
if(p==-1) throw IllegalChar();
// add bigger numbers, subtract smaller numbers
v[p]>=last?res+=v[p]:res-=v[p];
last=v[p];
}
return res;
}
// perform an arithmetic operation
int perform(char op, int & a1, int & a2) {
int res(0);
switch(op) {
case '+': res=a1+a2; break;
case '-': res=a2-a1; break;
case '*': res=a2*a1; break;
case '/':
if(a1==0) throw DivByZero();
res=a2/a1;
break;
}
return res;
}
// perform an operation on the input
void do_op(string op) {
int arg1, arg2, res;
try {
switch(op[0]) {
case '=':
if(top()<0||top()>4999) throw OutOfRange();
cout << ator(top()) << endl;
break;
case '+': case '-': case '/': case '*':
pop_args(arg1,arg2);
sys.push(perform(op[0],arg1,arg2));
break;
default:
sys.push(rtoa(op));
}
} catch(Underflow) {
cout << "stack underflow" << endl;
} catch(DivByZero) {
cout << "division by zero exception" << endl;
sys.push(arg2);
} catch(OutOfRange) {
cout << "out of range exception" << endl;
} catch(IllegalChar) {
cout << "illegal character in roman string" << endl;
}
}
int main()
{
string op;
while(cin>>op) do_op(op);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment