Roman Number Conversion

This is an update of an older post describing a short program written in ALGOL 68 to convert strings of roman numbers to decimal integer values.

For no particular reason I decided to rewrite this using two operators to do the roman number conversion for a single roman numeral (the simplest case) and strings of roman numbers, and I added a simple procedure to print and check the results. I think the resulting code is a little more ‘elegant’ but that is just my personal view.

{ Roman number conversion - 10 Jan 16 - MEJT }

PROGRAM roman

  { This program is free software: you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  for more details.

  You should have received a copy of the GNU General Public License along
  with this program.  If not, see <http://www.gnu.org/licenses/>

(
  OP DECIMAL = (CHAR roman) INT:

  { Degenerate case corresponding to a single roman numeral, used
    when parsing longer strings of roman numerals. An unrecognized
    numeral or null string will return the value zero.

    Note - To make the code more readable the tokenized syntax of the
    if-then statement has been used. }

    ( roman = "M" | 1000 |:
      roman = "D" |  500 |:
      roman = "C" |  100 |:
      roman = "L" |   50 |:
      roman = "X" |   10 |:
      roman = "V" |    5 |:
      roman = "I" |    1 | 0);

  OP DECIMAL = (STRING roman) INT:

  { Overloaded definition of the operator for more complex strings of roman
    numerals. }

    ( INT result := 0, last := 0, run := 0;
      FOR i FROM LWB roman TO UPB roman DO
        INT value = DECIMAL(roman[i]);
        IF last = value THEN
          run +:= value
        ELSE
          IF last < value THEN
            result -:= run
          ELSE
            result +:= run
          FI;
          run := last := value
        FI
      OD;
      result +:= run );

  PRIO DECIMAL = 9;

  PROC check = (STRING roman, INT value) VOID:
    ( write ((roman," "*(12-UPB(roman)),"= ", fixed(DECIMAL(roman),-6,0),
      ((DECIMAL(roman) = value | " - Ok" | " - Error")),
      newline)) );

  check ("MMXI",2011);
  check ("MIM", 1999);
  check ("MCMXCIX", 1999);
  check ("MCMLXIII", 1963);
  check ("MDCLXIV", 1664);
  check ("XXCIII", 83);
  check ("LXXIIX", 78);
  check ("MDCCCCX", 1910);
  write (newline);
  check ("IX", 9);
  check ("VII", 7);
  check ("V", 5);
  check ("IV", 4);
  check ("III", 3);
  check ("II", 2);
  check ("I", 1);
  check ("", 0) )

FINISH.

The program produces the following output. Both possible forms for 1999 are handled correctly but while ‘MIM’ is shorter and more convenient, the longer version ‘MCMXCIX’ is normally used.

MMXI        =   2011 - Ok
MIM         =   1999 - Ok
MCMXCIX     =   1999 - Ok
MCMLXIII    =   1963 - Ok
MDCLXIV     =   1664 - Ok
XXCIII      =     83 - Ok
LXXIIX      =     78 - Ok
MDCCCCX     =   1910 - Ok

IX          =      9 - Ok
VII         =      7 - Ok
V           =      5 - Ok
IV          =      4 - Ok
III         =      3 - Ok
II          =      2 - Ok
I           =      1 - Ok
            =      0 - Ok

Algol68g Notes

To run this example on a modern system using Algol68g then you will need to make a couple of minor changes to my code.

  • Comments should be delimited using ‘#’ rather than ‘{‘ and ‘}’
  • The ‘PROGRAM’ and ‘FINISH’ statements should be omitted, but you do need to start your program with an opening bracket (or ‘BEGIN’).
Advertisements
This entry was posted in Programming and tagged . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s