As a mostly-newbie Haskell / fp programmer ﻿(one who only read http://learnyouahaskell.com/) I wanted to exercise my functional coding skills, by resolving non-helloworld programming challenges. So I’ve tried something classical:

Write a program that will convert an integer in the range of [1 .. 3,888,000] to the equivalent roman numeral:

The symbols are: (I = 1); (V = 5); (X = 10); (L = 50); (C = 100); (D = 500); (M = 1,000); (upperscore V = 5,000); (upperscore X = 10,000); (upperscore L = 50,000); (upperscore C = 100,000); (upperscore D = 500,000); (upperscore M = 1,000,000) .

Rules:

• If a letter if followed by another with equal or lesser value, the two numbers are added (eg. XX = 20, LV = 55);
• If a letter is followed by another with greater value, the first is subtracted from the second (eg. IV = 4, XC = 90);

Examples:

The numbers from [1..10]: III, III, IV, V, VI, VII, VIII, IX, X
Other numbers: CDLVI = 456 , MCDXLIV = 1444 , MMMI = 3001 , etc.

and now… The solution (one of them, probably far from the best)

The main idea was to divide my solution into small reusable blocks.

1. First I’ve written a function, figures, that transforms a given number into a (reverse) list of figures. For example, 1113 becomes [3,1,1,1], 1234 becomes [4,3,2,1] and so on…

2. Then I defined a list (of Strings), romans, containing all the roman numerals. The upperscored versions were coded using an underscore :), like (upperscore X) = _X = 10, 000 .

3. Secondly I had to write a function that finds the roman numeral equivalent for a certain figure based on figure’s context. This function was called figureEq and receives two input parameters: the order and the figure.

The order will influence the returning roman numeral equivalent. For example:

4. The next step was to write two functions that make use of the figureEq function . I called them generatorRomOrd and generatorRomRaw .  The idea was simple: recurse over the figures of the number that is going to be converted, apply figureEq with the right order on the current figure, and append the resulting equivalents into a String.

The generatorRomRaw function will be able to convert any number between [0 .. 3,888,000] from the Arab notation to the corresponding Roman notation. The resulting String is still in a raw form (the upperscaped letters still use underscore) .

5. At this step I needed to somehow represent the upperscored letters . The easiest solution was to represent the resulting raw String (“_C_D_X_X_XMMCXXI” ) on two console rows. The upper row will contain only underscores, and the second row will contain the raw String without any “_” .

6. The last step was to combine all functions written so far into a “real” solution.

And the working solution:

Of course you can take a look at a more elegant implementation: here .

The full code: