I was going over the ICT Proficiency sample exam earlier because apparently I’ve got to take it pretty soon — nevermind that I’m a design guy, and not, you know. A geek. Yeah, go figure. But wish me luck, too, because this is what I’ll have to deal with:
Hobson's Choice
Needless to say, this had me silently cursing: PHP I can do just fine; and I’m still in awe of the possibilities with Python (I always end up thinking: whoa… you can do that in Python?! Is this a noob thing? Because so many things are just darn easy in Python!). But I haven’t even looked sideways at any C code since 1997, never got over my fear of Java, and the last version of Visual Basic I used was VB4. Oh, and I don’t even know what COBOL code looks like. So yeah, SOL. I’ve decided to go the C/C++ route because it’s the most familiar, and for the life of me, I cannot do the simplest things in Java without needing to look something up. Same goes, strangely enough, for VB.
So anyway, here’s the sample problem from NCC:
Write a program that will convert a Roman number into its equivalent Hindu Arabic number, and vice versa. The program should ask the user what type of number to convert (Roman or Hindu Arabic).
Hindu to Roman is pretty simple, and I started visualizing a switch block in my head when it hit me: Dictionaries. Does C++ have those? I’m still not sure, but I’m pretty sure C doesn’t, so I went with two arrays for the conversion table instead. I was eager to get my feet wet, and here’s where Ubuntu really pisses me off: doesn’t a Linux distro, y’know, have to have a C/C++ compiler pre-installed? I wouldn’t know, Ubuntu and Mint are the only ones I’ve tried, but you’d think, right? So, a sudo aptitude install build-essential later and I felt good to go. And a funny thing happened.
See, I wrote a short pseudocode on some paper scraps, and I noticed: damn, that almost looks like Python code. And what’d it hurt, right? I’d try to get it running on Python to see if it works first, then translate it to C/C++. That way, I’d only be worrying about one thing at a time. Python it is for the moment, then.
So Hindu to Roman was relatively straightforward, though in retrospect I’ve thought of a better implementation, but I digress. I had some real trouble with Roman to Hindu, though. My problem was with those pesky IV’s, IX’s, XL’s and such, because I’d originally planned to read the characters one by one and just add them all up. But that won’t work with those special cases, so (here it comes) I thought: regex.
Right. Several minutes later I was kicking myself, too. There’s got to be another way!
And it’s really obvious, but it wasn’t to me until I started looking for patterns, so in a way, trying to use regular expressions helped. In a really roundabout way. See, it’s only in those special instances (XC, XL, IV, IX, etc) that a lower value comes before a higher one (reading left to right). Everything else, it’s VIII, XI, LX and such. And in those instances, it basically means that the left value is subtracted from the right value, so in IV, 1 is subtracted from 5 to produce 4, and so on. I took a moment to congratulate myself until I realized that that’s really how Roman Numerals are translated in the first place. So yeah, fail.
So tomorrow I’m gonna take this code and try to translate it to C/C++. Gah, I feel like gouging my eyes out already.
def hindu_to_roman(num):
if not 0 < num < 4000:
return "Invalid input."
temp = num
roman = ""
i = 0
romans = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
numbers = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
while temp > 0:
if temp < numbers[i]:
i += 1
elif temp >= numbers[i]:
roman += romans[i]
temp -= numbers[i]
return roman
def roman_to_hindu(num):
romans = ["M", "D", "C", "L", "X", "V", "I"]
numbers = [1000, 500, 100, 50, 10, 5, 1]
total = 0
temp = num.upper()
for i in range(len(temp)):
try:
currval = numbers[romans.index(temp[i])]
if i < len(temp) - 1:
nextval = numbers[romans.index(temp[i+1])]
if currval < nextval:
currval *= -1
total += currval
except:
total = "Invalid input."
return total
def main():
choice = input("[1] Roman to Hindu\n[2] Hindu to Roman\n[3] Quit\nChoose: ")
while choice != 3:
if choice == 1:
num = raw_input("Enter a valid Roman numeral. Please? : ")
res = roman_to_hindu(num)
print res
elif choice == 2:
num = input("Enter a positive integer less than 4000: ")
res = hindu_to_roman(num)
print res
elif choice == 3:
pass
else:
print "\nInvalid choice.\n"
choice = input("\n[1] Roman to Hindu\n[2] Hindu to Roman\n[3] Quit\nChoose: ")
main()
Updated: Now with C++ procedural code
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
int roman_to_hindu(string);
string hindu_to_roman(int);
int roman_to_hindu(string toConvert){
const int ARRSIZE = 7;
int intlist[ARRSIZE] = {1000, 500, 100, 50, 10, 5, 1};
char charlist[ARRSIZE] = {'M', 'D', 'C', 'L', 'X', 'V', 'I'};
int total = 0;
string upper = toConvert;
// convert to uppercase
for(int i = 0; i < toConvert.length(); i++){
upper[i] = toupper(toConvert[i]);
}
// create temporary storage
int* temp = NULL;
temp = new int[upper.length()];
// cycle every item in upper
for( int i = 0; i < upper.length(); i++ ){
// for every item in upper, cycle charlist
for( int j = 0; j < ARRSIZE; j++ ){
if( upper[i] == charlist[j] ){
temp[i] = intlist[j];
}
}
}
// cycle temp
for( int i = 0; i < upper.length(); i++ ){
int currval = temp[i], nextval = temp[i+1];
// make sure the test doesn't exceed the array size
if( currval < nextval && i < upper.length() - 1){
temp[i] *= -1;
}
total += temp[i];
}
return total;
}
string hindu_to_roman(int iConvert){
const int ARRSIZE = 13;
int temp = iConvert;
string total;
int intlist[ARRSIZE] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
string charlist[ARRSIZE] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
int i = 0;
while( temp > 0 ){
if( temp < intlist[i] ){
i++;
}
else{
total += charlist[i];
temp -= intlist[i];
}
}
return total;
}
int main(void){
int iChoice;
do{
cout << "[1] Roman to Hindu\n[2] Hindu to Roman\n[3]Quit\n\nChoose: ";
cin >> iChoice;
iChoice = (iChoice > 3 || iChoice < 1) ? 3 : iChoice;
switch(iChoice){
case 1:
{
string toConvert;
cout << "Enter a valid Roman numeral: ";
cin >> toConvert;
cout << "\n" << toConvert << " converted to Hindu numerals is: " << roman_to_hindu(toConvert) << "\n" << endl;
break;
}
case 2:
{
int toConvert;
cout << "Enter a positive integer: ";
cin >> toConvert;
cout << "\n" << toConvert << " converted to Roman numerals is: " << hindu_to_roman(toConvert) << "\n" << endl;
break;
}
}
}while(iChoice != 3);
cout << "\nBye!" << endl;
return 0;
}
Related posts:







Subscribe via Email
7 Comments
limitation ba ng requirement na less than 4000?
kasi sabi sa tanong e
“Write a program that will convert a Roman number into its equivalent Hindu Arabic number, and vice versa. The program should ask the user what type of number to convert (Roman or Hindu Arabic).”
wala namang sinabi na less than 4000 lang ang input…
baka madale ka sa numbers greater than 4000 (yung mga may bar sa taas nung roman numerals)
kasi wala namang roman numeral above 4000 e :p haka haka lang ang mga un (at sige nga, pakita mo saken pano lagyan ng bar ang M sa text na terminal ;p)
btw blind..na flag ka as spam.. ^^
di naman kelangan ilagay yung bar
gagawin ko nang condition yung input sa Roman to Hindu:
Is your input greater than 4000? (Y/N)
tapos
if y then input roman numeral
else
input roman numeral
gawa ka ng dalawang procedure, yung sa Y e times 1000 sa input
yung N yung original procedure mo.
bat pa dalawang procedure? tanggalin ko lang ang
if not 0 < num < 4000automatic nang magdidisplay ng maraming M :pang point don kasi hanggang 3999 lang ang classic roman number system kaya linagyan ko ng limit
Low Sir Jeorge. Great programming skills talaga. :)
See you tomorrow on the testing center. I am very afraid to take the examination. But I’ll be somehow read and follow your programming logic on the patterns. Thanks for the code.
Wish I’d seen this code before my job interview :P
There is one definite bug in it, though: you need to delete[] temp because it leaks!