Created
January 19, 2015 19:59
-
-
Save manonthemat/22b31d0c4ea9300e6495 to your computer and use it in GitHub Desktop.
first draft of a simple roman calculator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <map> | |
#include <string> | |
#include <cmath> | |
#include <regex> | |
#include <sstream> | |
using namespace std; | |
string toString(const int& i) { | |
stringstream s; | |
s << i; | |
return s.str(); | |
} | |
string roman_from_value(const int& inum) { | |
int temp {inum}; | |
string result; | |
int m = inum / 1000; | |
for(int i=0; i<m; ++i) result += "M"; | |
temp = temp - m*1000; | |
if(temp >= 900) { | |
result += "CM"; | |
temp -= 900; | |
} | |
else if(temp >= 500) { | |
result += "D"; | |
temp -= 500; | |
} | |
else if(temp >=400) { | |
result += "CD"; | |
temp -= 400; | |
} | |
if(temp >= 100) { | |
int c = temp/100; | |
for(int i=0; i<c; ++i) result += "C"; | |
temp = temp - c*100; | |
} | |
if(temp >= 90) { | |
result += "XC"; | |
temp -= 90; | |
} | |
else if(temp >= 50) { | |
result += "L"; | |
temp -= 50; | |
} | |
else if(temp >= 40) { | |
result += "XL"; | |
temp -= 40; | |
} | |
if(temp >= 10) { | |
int x = temp/10; | |
for(int i=0; i<x; ++i) result += "X"; | |
temp = temp - x*10; | |
} | |
if(temp == 9) { | |
result += "IX"; | |
temp -= 9; | |
} | |
else if(temp >= 5) { | |
result += "V"; | |
temp -= 5; | |
} | |
else if(temp == 4) { | |
result += "IV"; | |
temp -= 4; | |
} | |
if(temp >= 1) { | |
int i = temp/1; | |
for(int j=0; j<i; ++j) result += "I"; | |
} | |
return result; | |
} | |
int value_from_roman(const string& rval) { | |
map<char,int> roman; | |
roman['I'] = 1; | |
roman['V'] = 5; | |
roman['X'] = 10; | |
roman['L'] = 50; | |
roman['C'] = 100; | |
roman['D'] = 500; | |
roman['M'] = 1000; | |
int temp {0}; | |
char previous_char {' '}; | |
for(int i=rval.size()-1; i>=0; --i) { | |
if((rval[i] != previous_char) && (roman[rval[i]] < temp)) { | |
temp -= roman[rval[i]]; | |
} else { | |
temp += roman[rval[i]]; | |
} | |
previous_char = rval[i]; | |
} | |
return temp; | |
} | |
class Roman_invalid {}; | |
class Roman_int { | |
public: | |
Roman_int() {}; | |
Roman_int(const string& rnum); | |
Roman_int(const int& inum); | |
int as_int() const { return ival; }; | |
string as_roman() const { return rval; }; | |
private: | |
string rval; | |
int ival; | |
}; | |
Roman_int::Roman_int(const string& rnum) { | |
rval = rnum; | |
ival = value_from_roman(rval); | |
} | |
Roman_int::Roman_int(const int& inum) { | |
rval = roman_from_value(inum); | |
ival = inum; | |
} | |
ostream& operator<<(ostream& os, const Roman_int& r) { | |
return os << r.as_roman(); | |
} | |
istream& operator>>(istream& is, Roman_int& r) { | |
string rval; | |
is >> rval; | |
if(!is) return is; | |
regex re("^[MDCLXVI]+"); | |
if(regex_match(rval, re) != 1) throw Roman_invalid {}; | |
r = Roman_int(rval); | |
return is; | |
} | |
int operator+(const Roman_int& r1, const Roman_int& r2) { | |
return r1.as_int() + r2.as_int(); | |
} | |
int operator-(const Roman_int& r1, const Roman_int& r2) { | |
return r1.as_int() - r2.as_int(); | |
} | |
int operator*(const Roman_int& r1, const Roman_int& r2) { | |
return r1.as_int() * r2.as_int(); | |
} | |
int main() { | |
cout << "Roman Calculator" << endl; | |
try { | |
Roman_int r1, r2, result; | |
char op; | |
while(cin >> r1 >> op >> r2) { | |
if(op == '+') result = Roman_int(r1+r2); | |
else if(op == '-') result = Roman_int(r1-r2); | |
else if(op == '*') result = Roman_int(r1*r2); | |
else { | |
cerr << "Error detected. Exiting..." << endl; | |
} | |
cout << r1 << op << r2 << "=" << result << endl | |
<< r1.as_int() << op << r2.as_int() << '=' << result.as_int() << endl; | |
} | |
cout << "Exiting..." << endl; | |
} catch (Roman_invalid) { | |
cerr << "Invalid Roman detected. Exiting." << endl; | |
return 1; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment