e r l a n g : c o o k b o o k

/ Erlang.NumberRomanNumerals

This Web


WebHome 
WebChanges 
TOC
NewRecipe 
WebTopicList 
WebStatistics 

All Webs


Chicken
Cookbook
Erlang
Know
Main
Plugins
Sandbox
Scm
TWiki  

Erlang Links


Erlang.org
Erlang Wiki
ErlMan
Erlang Wiki
The Jungerl
Erlang-fr.org
Joe Armstrong
Lambda the Ultimate

Erlang Web Ring


[Prev]: Joe Armstrong's Page
[Next]: Joe Armstrong's Page

Working with Roman Numerals

Problem

You want to convert decimal numbers to Roman numerals and Roman numerals to decimal numbers.

Solution

Here is some example code illustrating the conversion between decimals numbers and Roman numerals.
% dec_to_roman/1 : integer -> string
%   format the integer num using roman numerals
decimal_to_roman(Num) ->
    decimal_to_roman(Num, "",
        [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
        ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX",
         "V", "IV", "I"]).

% dec_to_roman/4 : integer string [t number) (list string) -> string
%   append the numbers num formatted as roman numerals to the string s,
%   using the roman numerals in roman-numbers with corresponding
%   decimal values in decimal-values
decimal_to_roman(0, Accum, Decimals, Romans) -> Accum;
decimal_to_roman(Num, Accum, Decimals, Romans) ->
    F_el = hd(Decimals),
    if
        F_el =< Num -> decimal_to_roman(Num - F_el,
                                        Accum ++ hd(Romans),                    
                                        Decimals, Romans);
        true -> dec_to_roman(Num, Accum, tl(Decimals), tl(Romans))
    end.

% Example of use:
1> decimal_to_roman(1997).
"MCMXCVII"
2> decimal_to_roman(1929).
"MCMXXIX"
3> decimal_to_roman(2112).
"MMCXII"
And here is the reverse transformation (converting between Roman numerals and decimal numbers):
% roman_to_decimal : string -> integer
%  convert a string with (uppercase) roman numerals to an integer
roman_to_decimal("") -> 0;
roman_to_decimal(Str) ->
    case length(Str) of
        1 ->
            case list_to_atom(Str) of
                'I' ->    1;
                'V' ->    5;
                'X' ->   10;
                'L' ->   50;
                'C' ->  100;
                'D' ->  500;
                'M' -> 1000;
                _   -> 0
            end;
        _ ->
            roman_to_decimal( string:substr(Str, 3) )
            + case list_to_atom( string:substr(Str, 1, 2) ) of
                'IV' ->   4;
                'IX' ->   9;
                'XL' ->  40;
                'XC' ->  90;
                'CD' -> 400;
                'CN' -> 900;
                _    -> roman_to_decimal( string:substr(Str, 1, 1) )
                        + roman_to_decimal( string:substr(Str, 2, 1) )
            end
    end.
% Example of use:
4> roman_to_decimal("MM").
2000
5> roman_to_decimal("MMIII").
2003
6> roman_to_decimal("MMIIII").
2004
7> roman_to_decimal("MCMXM"). 
3110 

Discussion

In the first code sample we show a very simple solution; the main procedure takes the number to be converted. It then calls an auxilliary procedure that performs the actual conversion. The auxilliary procedure takes four arguments: (1) the number we want to convert, (2) an accumulator string that will (eventually) contain the result, (3) a list containing the decimal integers that we can represent as roman numerals, and (4) a list of corresponding roman numeral representations of the decimal values.

We have three cases to consider:

In the second code example we use Erlangs term matching features to take pairs of roman numerals for evaluation, until there is only one character left. If the pair of numerals matches a known valid roman number (i.e., IV, IX, XL, XC, CD, CM), we do the conversion; otherwise we interpret the first of the two characters as a number (i.e., I,V,X,L,C,D,M), and then do a recursive call on the remaining elements of the string. Note that the second character from the pair we just evaluated is included in the remaining numerals to be evaluated. This problem would be difficult to solve without Erlang pattern matching features.

Once we determine which condition we are dealing with, we just sum the decimal values of the symbol that we have recognized.

Contributors

Based on work by EmiliaBarajas.

-- BrentAFulgham - 24 Aug 2004

CookbookForm
TopicType: Recipe
ParentTopic: NumberRecipes
TopicOrder: 060

 
 
Copyright © 2004 by the contributing authors. All material on the Erlang Cookbook web site is the property of the contributing authors.
This material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.
Ideas, requests, problems regarding Schematics Cookbook? Send feedback.
/ You are Main.guest