Computer Science Canada

Roman numeral challenge!

Author:  Martin [ Sun Apr 23, 2006 8:26 pm ]
Post subject:  Roman numeral challenge!

Part 1: Your task is to convert an integer in base 10 to its roman numeral equivalent. Write a function integer_to_roman_numeral in the language of your choice that accepts a positive integer and returns a string that is the roman numeral in capital letters. All input will be an integer in the range of 1 to 3999. You do not need to worry about bad input.

Part 2: Write the function roman_numeral_to_integer that, given a string representation of a roman numeral in mixed case letters (ie. XiiI, XIII, xiii and xIiI are all valid representations of the roman numeral for 13) return an integer that is the base 10 integer representation of the roman numeral. All input will be from 1 (I) to 3999 (MMMCMXCIX). All given roman numerals will be valid.

Part 3: Write the function is_roman_numeral that, given a string returns true or false whether the string is a roman numeral from 1 (I) to 3999 (MMMCMXCIX). Roman numerals in capital and lower case letters are valid (ie. 'XiI' is a valid roman numeral for 12)

Examples:
integer_to_roman_numeral(14) => 'XIV'
integer_to_roman_numeral(1000) => 'M'
roman_numeral_to_integer('XxxIiI') => 33
roman_numeral_to_integer('XLII') => 42
is_roman_numeral('hello!') => false
is_roman_numeral('CcXXxiV') => true
is_roman_numeral('XIIII') => false

More information on roman numerals can be found here here. A web based roman numeral to integer calculator can be found here.

You may use the language of your choice, although obviously you may not use any pre-existing roman numeral conversion functions. You may impliment a solution to any or all parts. Prize is 250 bits per correct part, to all contestants whose entries work. The best solution to each (as chosen by me) gets an additional 100 bits. This means that you can potentially win 1050 bits - 250 for each of the three parts, plus 100 bits for each of the three best solution prizes. All entries will be posted after the contest closes. PM all submissions to me, and make sure you tell me what language you are using. The contest closes on May 1st.

Author:  [Gandalf] [ Sun Apr 23, 2006 11:20 pm ]
Post subject: 

Alrighty, I'll try it out when I find some extra free time.

Is a "solution" the answer to one "part" of the question, or the whole question? I think the latter, but just making sure. If I am correct, do solutions in two different languages count as two solutions?

Author:  Martin [ Sun Apr 23, 2006 11:25 pm ]
Post subject: 

[Gandalf] wrote:
Alrighty, I'll try it out when I find some extra free time.

Is a "solution" the answer to one "part" of the question, or the whole question? I think the latter, but just making sure. If I am correct, do solutions in two different languages count as two solutions?


A solution is the answer to one part of the question. Therefore, the most number of bits that someone can get would be 250 * 3 + 100 * 3 = 1050, if they got all three parts and all three 'best' solution prizes.

Author:  ZeroPaladn [ Mon Apr 24, 2006 11:43 am ]
Post subject: 

im in! finnaly, something i can do!

Author:  Tony [ Mon Apr 24, 2006 1:15 pm ]
Post subject: 

ZeroPaladn wrote:
finnaly, something i can do!

well you're always welcome to suggest new activities for us to put together.. or take the initiative yourself, we'll help out if available

Author:  Cervantes [ Mon Apr 24, 2006 4:22 pm ]
Post subject: 

We did this last year in my compsci class. Except it was a one or two day activity, so the code was really rushed... and terrible. I wouldn't mind redo-ing this problem properly. Maybe, maybe.

Good idea, Martin!

Author:  MysticVegeta [ Mon Apr 24, 2006 5:23 pm ]
Post subject: 

oh wtf? This should be limited to non-mods only, otherwise it gets UNFAIR! Mod geniuses will make this unfair, *cough* zylum *cough* *cough* Cervantes *cough*

Author:  zylum [ Mon Apr 24, 2006 6:11 pm ]
Post subject: 

how about since mods cant win bits we try to make the shortest solution (character wise) in any language we choose.. that should be fun Wink

Author:  MysticVegeta [ Mon Apr 24, 2006 6:23 pm ]
Post subject: 

but separate division of contest for them? Then it would be ok Smile

Author:  Martin [ Mon Apr 24, 2006 7:09 pm ]
Post subject: 

Nah, anyone can enter. Mods won't win the best code thing (but they can have 250 bits if they want Wink).

We have three entries for part 1 so far after only a day. Great response guys, thank you very much. Smile

Author:  Drakain Zeil [ Mon Apr 24, 2006 7:37 pm ]
Post subject: 

Hmm, wasn't this a past ECOO question?

Author:  zylum [ Mon Apr 24, 2006 9:00 pm ]
Post subject: 

hmm, why dont people post their code? well since we are being so secretive, ill pm my solution too..

just to make things interesting, i will note that my solution to integer_to_roman_numeral is 9 lines in java and 12 in turing Wink

Author:  MysticVegeta [ Tue Apr 25, 2006 5:41 pm ]
Post subject: 

I made one in 9 lines in java too

Author:  zylum [ Tue Apr 25, 2006 8:42 pm ]
Post subject: 

MysticVegeta wrote:
I made one in 9 lines in java too


make that 6 in java and 10 in turing Laughing

Author:  MysticVegeta [ Wed Apr 26, 2006 1:37 pm ]
Post subject: 

I hate you

Author:  [Gandalf] [ Wed Apr 26, 2006 11:55 pm ]
Post subject: 

I hate spam.

There are many styles of writing Java out there, what are we talking about? Sun's guidelines?
For exampe:
code:
if (somethingIsTrue) System.out.println("Yay!");

as opposed to:
code:
if (somethingIsTrue)
    System.out.println("Yayaya!");

Author:  Andy [ Thu Apr 27, 2006 11:16 am ]
Post subject: 

or better yet

somethingIsTrue?System.out.println("Yayaya!"):System.out.print("");

a better way would to be count the number of semicolons. a for loop requires 2 semicolons, and so does a while.

Author:  zylum [ Thu Apr 27, 2006 1:17 pm ]
Post subject: 

dont worry, im not using any cheap short cuts.. although i do put my expression on the same line as an if statement.

Author:  MysticVegeta [ Thu Apr 27, 2006 1:33 pm ]
Post subject: 

yup same here, no cheap short cuts

Author:  Andy [ Thu Apr 27, 2006 1:36 pm ]
Post subject: 

how is that a cheap shortcut? it's more logical to me..

Author:  zylum [ Thu Apr 27, 2006 2:58 pm ]
Post subject: 

[mod:81158a5e7d="rizzix"]Yea thanks for screwing things up. Razz[/mod:81158a5e7d]

Author:  zylum [ Thu Apr 27, 2006 3:03 pm ]
Post subject: 

Confused wtf is that... each time i submit it says error, 30 seconds of execution exceeded or something like that. now i go and its posted like 5 times!

anyways, you get my point Laughing

now.. how to delete those Question

Author:  MysticVegeta [ Thu Apr 27, 2006 7:41 pm ]
Post subject: 

wow you hardly get to see zylum going psycho

Author:  Andy [ Fri Apr 28, 2006 12:05 am ]
Post subject: 

wow, you hardly not see mysticvegeta spam.. this is your first warning

Author:  MysticVegeta [ Sat Apr 29, 2006 7:37 pm ]
Post subject: 

hey! I wasnt spamming dude calm down. it was a legitimate comment you know to add a little comic relief. Anyways, zylum, what does the "?" do? Is it like "{" for the if statement?

Author:  Cervantes [ Sat Apr 29, 2006 8:00 pm ]
Post subject: 

Note: Because zylum has so skillfully destroyed the page layout, the quotes and code in this post got shifted a long ways over to the right.
MysticVegeta wrote:
hey! I wasnt spamming dude calm down. it was a legitimate comment you know to add a little comic relief.

He only gave you a warning, so you should calm down yourself. But his warning is valid. You've been spamming a lot lately.
Re: "comic relief": zylum gave the comic relief. Why do we need comic relief in response to comic relief? *Rhetorical

MysticVegeta wrote:
Anyways, zylum, what does the "?" do? Is it like "{" for the if statement?

"?" together with the ":" is the ternary operator. It's like an if statement.
code:
a > b ? a : b

is the same as
code:

if a > b
    a
else
    b
end

Author:  Martin [ Sun Apr 30, 2006 7:27 pm ]
Post subject: 

Just a reminder, the contest closes about 24 hours from now (9:00 am tomorrow, my time).

Author:  Martin [ Mon May 01, 2006 6:09 pm ]
Post subject: 

Last call for entries. One hour remaining.

Author:  MysticVegeta [ Mon May 01, 2006 7:35 pm ]
Post subject: 

Are you annoncing the results when the contest ends?

Author:  zylum [ Mon May 01, 2006 10:33 pm ]
Post subject: 

i win?

Author:  Martin [ Mon May 01, 2006 10:41 pm ]
Post subject: 

Hey, sorry, I'll post results tonight - too busy right now.

Author:  [Gandalf] [ Mon May 01, 2006 11:18 pm ]
Post subject: 

I only had time for two pretty crappy solutions since I was doing multiple english essays throughout the week. Crying or Very sad

Author:  MysticVegeta [ Tue May 02, 2006 5:27 pm ]
Post subject: 

I did all 3, part 3 was the easiest, all you had to do was convert the roman into arabic, then that arabic back to roman and cehck the original string argument with the roman you just got, if they match then it is valid else not. lol so basically a mixture of part 1 and 2

Author:  GlobeTrotter [ Tue May 02, 2006 5:32 pm ]
Post subject: 

MysticVegeta wrote:
I did all 3, part 3 was the easiest, all you had to do was convert the roman into arabic, then that arabic back to roman and cehck the original string argument with the roman you just got, if they match then it is valid else not. lol so basically a mixture of part 1 and 2


That won't necessarily work. If my memory serves me well, there are some cases where there are multiple valid ways to write a number as a roman numeral. There is probably a standard, but the other ways are still valid, I believe.

Author:  Cervantes [ Tue May 02, 2006 5:35 pm ]
Post subject: 

GlobeTrotter wrote:
That won't necessarily work. If my memory serves me well, there are some cases where there are multiple valid ways to write a number as a roman numeral. There is probably a standard, but the other ways are still valid, I believe.


No, I'm pretty sure there's only one way for each number. Unless you consider "VIIII" valid - it should be "IV"

Author:  MysticVegeta [ Tue May 02, 2006 6:11 pm ]
Post subject: 

Cervantes wrote:
GlobeTrotter wrote:
That won't necessarily work. If my memory serves me well, there are some cases where there are multiple valid ways to write a number as a roman numeral. There is probably a standard, but the other ways are still valid, I believe.


No, I'm pretty sure there's only one way for each number. Unless you consider "VIIII" valid - it should be "IV"


oh noes, minsc needs more coffee!! "IX"

Author:  GlobeTrotter [ Tue May 02, 2006 8:13 pm ]
Post subject: 

Again, I'm not completely sure, but I was primarily referring to large numbers where C's, L's, and M's are involved.

Author:  MysticVegeta [ Wed May 03, 2006 12:04 am ]
Post subject: 

Nope still you are wrong, it could be written in multiple ways but only 1 is valid, go to the wiki link from Martin and scroll down to see what I and Cervantes are trying to tell you.

Author:  MysticVegeta [ Thu May 04, 2006 5:48 pm ]
Post subject: 

May 4... whens the results coming up??

Author:  Martin [ Thu May 04, 2006 10:52 pm ]
Post subject: 

It's happening, it's happening, don't worry guys. This week has been hectic as hell, I'll do it as soon as I get a moment (I posted the solutions in the mod forum too so if you're really nice someone else might do it Razz)

I'm really sorry for taking so long.

Author:  do_pete [ Fri May 05, 2006 11:24 am ]
Post subject: 

Could you post the solutions here as well so that we can see what others did?

Author:  zylum [ Fri May 05, 2006 2:06 pm ]
Post subject: 

edit: removed...

Author:  do_pete [ Fri May 05, 2006 6:41 pm ]
Post subject: 

What did you do for your solutions zylum?

Author:  zylum [ Fri May 05, 2006 9:21 pm ]
Post subject: 

i really only submitted a solution for the first one... the rest are quite easy once you have that one solved.

Turing:
var R : array 1 .. 13 of string := init ("I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M")
var D : array 1 .. 13 of int := init (1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000)

fcn integer_to_roman_numeral (n : int) : string
    for decreasing i : 13 .. 1
        if D (i) <= n then
            result R (i) + integer_to_roman_numeral (n - D (i))
        end if
    end for
    result ""
end integer_to_roman_numeral

fcn roman_numeral_to_integer (s : string) : int
    for i : 1 .. 3999
        if integer_to_roman_numeral (i) = Str.Upper (s) then
            result i
        end if
    end for
    result 0
end roman_numeral_to_integer

fcn is_roman_numeral (s : string) : boolean
    result Str.Upper (s) = integer_to_roman_numeral (roman_numeral_to_integer (s))
end is_roman_numeral

put roman_numeral_to_integer (integer_to_roman_numeral (3999))
put is_roman_numeral ("ABCDE")
put is_roman_numeral ("XXXIX")
put is_roman_numeral ("MMCCCXXIII")


or in java

Java:
import java.util.*;
class Integer_To_Roman_Numeral {
        static String[] R = new String[] { "I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M" };
        static int[] D = new int[] { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
       
        static String integer_to_roman_numeral (int n) {
                for (int i = R.length-1; i >= 0; i--) if (D[i] <= n) return R[i] + integer_to_roman_numeral(n - D[i]);
                return "";
        }
       
        static int roman_numeral_to_integer (String s) {
                for (int i = 1; i < 4000; i++) if (s.toUpperCase().equals(integer_to_roman_numeral(i))) return i;
                return 0;
        }
       
        static boolean is_roman_numeral (String s) {
                return s.toUpperCase().equals(integer_to_roman_numeral(roman_numeral_to_integer(s)));
        }
       
        public static void main (String[] args) {
                System.out.println(roman_numeral_to_integer(integer_to_roman_numeral(2424)));
                System.out.println(is_roman_numeral("ABCE"));
                System.out.println(is_roman_numeral("XXXIX"));
                System.out.println(is_roman_numeral("MMCCCXXIII"));
        }
}


recursion for the first one Wink

i dont think you were supposed to use those extra parameters in your functions.

Author:  Cervantes [ Sat May 06, 2006 10:34 am ]
Post subject: 

zylum wrote:
i really only submitted a solution for the first one... the rest are quite easy once you have that one solved.

Turing:

fcn roman_numeral_to_integer (s : string) : int
    for i : 1 .. 3999
        if integer_to_roman_numeral (i) = Str.Upper (s) then
            result i
        end if
    end for
    result 0
end roman_numeral_to_integer

Java:

        static int roman_numeral_to_integer (String s) {
                for (int i = 1; i < 4000; i++) if (s.toUpperCase().equals(integer_to_roman_numeral(i))) return i;
                return 0;
        }


Surprised

And zylum, don't you think you should have let Martin decide whether he wanted to post the solutions in this thread?

Author:  zylum [ Sat May 06, 2006 1:53 pm ]
Post subject: 

yeah i guess.. but the contest is over so i didnt think any harm would be done.

oh and yeah, solutions 2 and 3 are just hacks. like i said i only solved the first one.

Author:  MysticVegeta [ Sat May 06, 2006 7:07 pm ]
Post subject: 

I am still wondering who the winners are Confused

Author:  Cervantes [ Sat May 06, 2006 7:28 pm ]
Post subject: 

You're not very patient, are you? The last time you raised this issue, Martin said he hasn't forgotten about it. Do you doubt Martin's ability to remember things? As far as I see it, this is spam.

Author:  Martin [ Sun May 07, 2006 7:18 pm ]
Post subject: 

I live!

Anyway guys, I'm very very sorry for taking this long. Cervantes is right - I didn't forget. Last week was Golden Week here in the land of the rising sun, which means absolutely no free time (and crazy things like partying and spur of the moment trips to Tokyo). I was at home to sleep and that's about it.

So, better late than never.

First, here are the solutions, in the order received (or reverse order received, perhaps).

MysticVegeta wrote:
By: MysticVegeta
Part 3
Lang: Java

code:
class isRomanNumeral {
        public static boolean is_roman_numeral (String n) {
                  //Converting it to a number
                  n = n.toUpperCase();
                  String ro = n;
          char [] roChars = {'I','V','X','L','C','D','M'};
          char [] arabicChars = {1,5,10,50,100,500,1000};
         
          int k = 0;
          int arabic = 0; 
         
          while (k < ro.length()) {
             int number = 0;
             
             for (int j = 0; j < roChars.length; j++)
                   if (roChars[j]==ro.charAt(k)) number = arabicChars[j];
               
             k++;
             
             if (k != ro.length()) {
                int next = 0;
                for (int j = 0 ; j < roChars.length; j++)
                                if (roChars[j] == ro.charAt(k)) next = arabicChars[j];
                               
                if (next > number) {
                   number = next - number;
                   k++;
                }
             }
             arabic += number;
                }
          //Converting to roman again
          String [] ones = {"I","II","III", "IV", "V", "VI", "VII", "VIII", "IX", "X","XX","XXX", "XL", "L", "LX", "LXX", "LXXX", "XC","C","CC","CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "M","MM","MMM", "Mv", "v", "vM", "vMM", "vMMM", "xM"};
                  String finalAnsReversed = ""; //Reverse of answers from ans
                  for (int i = 0; i < 4; i++) {
                        int mod = arabic % 10;
                        arabic /= 10;
                        if (mod == 0) continue; //dont want array[-1] rofl.
                        else finalAnsReversed = ones[(i*9)+(mod-1)] + finalAnsReversed;
                }
                //Main Answer, check to see if they yield the same result, if they do then it is valid, else its not
                if (finalAnsReversed.equals(n)) return true;
                else return false;
        }
       
        public static void main (String [] Args) {
                String n = "IIII";
                System.out.println("WELCOME TO MYSTIC'S ROMAN NUMERAL CHECKER");
                System.out.println();
                System.out.println(n + " is a valid roman numeral? " + is_roman_numeral(n));
                System.out.println();
        }
}


do_pete wrote:
Here are the first two functions (I did them in Turing). I'll PM you the last one when I'm done.

code:
fcn integer_to_roman_numeral (integer : nat, output : string) : string
    var numerals : array 1 .. 2, 1 .. 9 of string := init ("M", "D", "C", "L", "X", "IX", "V", "IV", "I", "1000", "500", "100", "50", "10", "9", "5", "4", "1")
    for i : 1 .. 9
        if integer >= strint (numerals (2, i)) then
            result integer_to_roman_numeral (integer - strint (numerals (2, i)), output + numerals (1, i))
        end if
    end for
    result output
end integer_to_roman_numeral

fcn roman_numeral_to_integer (input : string, total : nat) : nat
    var numerals : array 1 .. 2, 1 .. 9 of string := init ("M", "D", "C", "L", "X", "IX", "V", "IV", "I", "1000", "500", "100", "50", "10", "9", "5", "4", "1")
    for i : 1 .. 9
        if index (Str.Upper (input), numerals (1, i)) = 1 then
            result roman_numeral_to_integer (input (length (numerals (1, i)) + 1 .. length (input)), total + strint (numerals (2, i)))
        end if
    end for
    result total
end roman_numeral_to_integer

put integer_to_roman_numeral (2006, "")
put roman_numeral_to_integer ("MmVi", 0)


[Gandalf] wrote:
Solution to part 2 in Java:
Java:
    private String[] roman_numeral = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
    private int[] numeral_value = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
       
    private int roman_numeral_to_integer(String numeral) {
        int result = 0, index = 0;
        for (int i = 0; i < roman_numeral.length; i++) {
            while (index + roman_numeral[i].length() <= numeral.length() && numeral.substring(index,index+roman_numeral[i].length()).equalsIgnoreCase(roman_numeral[i])) {
                result += numeral_value[i];
                index += roman_numeral[i].length();
            }
        }
        return result;
    }


MysticVegeta wrote:
Author: MysticVegeta
Lang: Java

Java:

// MADE BY MYSTIC VEGETA, CONVERTS ROMANS TO ARABIC
 // NOTE: I COULD PROGRAM THIS IS IN LESSER LINES, BUT IT WOULD BE IMPOSSIBLE TO READ, ROFL. <0_0>
 // LANG: JAVA
 
 
 class RomanToArabic {
 
       public static int roman_numeral_to_integer (String ro) {
          ro = ro.toUpperCase();
          char [] roChars = {'I','V','X','L','C','D','M'};
          char [] arabicChars = {1,5,10,50,100,500,1000};
         
          int k = 0;
          int arabic = 0; 
         
          while (k < ro.length()) {
             int number = 0;
             
             for (int j = 0; j < roChars.length; j++)
                   if (roChars[j]==ro.charAt(k)) number = arabicChars[j];
               
             k++;
             
             if (k != ro.length()) {
                int next = 0;
                for (int j = 0 ; j < roChars.length; j++)
                                if (roChars[j] == ro.charAt(k)) next = arabicChars[j];
                               
                if (next > number) {
                   number = next - number;
                   k++;
                }
             }
             arabic += number;
                }
                return arabic;
       }
         
       public static void main (String [] Args) {
                String n = "MMMCMXCIX";
                        System.out.println("WELCOME TO MYSTIC VEGETA'S CONVERTER");
                        System.out.println ("Edit the n so that its a roman numberal");
                        System.out.println ();
                        System.out.println (n + " = " + roman_numeral_to_integer (n));
                        System.out.println ();
       }
       
}


cool dude wrote:
hi, i tried the first problem and the only problem i have is if the number is 10^i -1. for example if the number is 99 then it should be XL but i get XXXX which is wrong! i'll keep trying. this is the code i have...

code:

var number : int
var remainder : int
var answer : array 1 .. 7 of int

put "enter a base 10 number"
get number


remainder := number mod 1000
answer (1) := number div 1000
for i : 1 .. answer (1)
    put "M" ..
end for

answer (2) := remainder div 500
remainder := number mod 500
for i : 1 .. answer (2)
    put "D" ..
end for

answer (3) := remainder div 100
remainder := number mod 100
for i : 1 .. answer (3)
    put "C" ..
end for

answer (4) := remainder div 50
remainder := number mod 50
for i : 1 .. answer (4)
    put "L" ..
end for

answer (5) := remainder div 10
remainder := number mod 10
for i : 1 .. answer (5)
    put "X" ..
end for

answer (6) := remainder div 5
remainder := number mod 5
for i : 1 .. answer (6)
    put "V" ..
end for

answer (7) := remainder div 1
for i : 1 .. answer (7)
    put "I" ..
end for


[Gandalf] wrote:
Here is my solution to part 1 in Turing:
code:
var roman_numeral : array 1 .. * of string := init ("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I")
var numeral_value : array 1 .. * of int := init (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)

%%% Solution #1 %%%
fcn integer_to_roman_numeral (num : int) : string
    var number : int := num
    var result_numeral : string := ""
    for i : 1 .. upper (roman_numeral)
        loop
            exit when number < numeral_value (i)
            result_numeral := result_numeral + roman_numeral (i)
            number -= numeral_value (i)
        end loop
    end for
    result result_numeral
end integer_to_roman_numeral

More to come, hopefully.


RESULTS! Best solution to each part is in red.

Results.

[Gandalf]
Part 1:(Turing)
Part 2:(Java)
Part 3:Didn't write.
600 bits!

cool_dude
Part 1:(Turing)
Part 2:Didn't write.
Part 3:Didn't write.
250 bits!

MysticVegeta
Part 1:(Java)
Part 2:(Java)
Part 3:(Java)
850 bits!

zylum
Part 1:(Java and Turing)
Part 2:Didn't write.
Part 3:Didn't write.
250 bits!

do_pete
Part 1:(Turing)
Part 2:(Turing)
Part 3:Didn't write.
600 bits!

Author:  MysticVegeta [ Sun May 07, 2006 8:25 pm ]
Post subject: 

yay! I win! Smile I am now richer than admins rofl, just 7000 more to go for webhosting =\


: