Jim Rogers wrote:
assert ("I" == roman(1));
/* assert (“II” == roman(2));
assert (“III” == roman(3));
assert (“IV” == roman(4));
assert (“V” == roman(5));
assert (“VI” == roman(6));
assert (“VII” == roman(7));
assert (“VIII” == roman(8));
*/
I would change the entire approach to the following:
type Roman_Numerals is (I, II, III, IV, V, VI, VII, VIII);
Your implementation duplicates I, V, etc. If you were to resolve that
duplication, it would form little tables. Then adding L, C, M etc.
would get easier.
I ran the experiment in Ruby, and put the result here:
http://www.xpsd.org/cgi-bin/wiki?TestDrivenDevelopmentTutorialRomanNumerals
The (unfinished) implementation is here:
Symbols = {
1=>'I', 5=>'V', 10=>'X', 50=>'L', 100=>'C',
}
def roman(num)
return Symbols[num] if Symbols.has_key?(num)
[ [100, 1],
[100, 10],
[ 50, 10],
[ 10, 1],
[ 5, 1],
[ 1, 0],
].each do |cutPoint, subtractor|
if num > cutPoint then
return roman(cutPoint) + roman(num - cutPoint)
end
if num >= cutPoint - subtractor and num < cutPoint then
return roman(subtractor) + roman(num + subtractor)
end
end
end
That code can’t do 49 (IL) yet, and it obviously can’t do D or M yet.
But it’s just as obvious how to add those.
That’s the point: Removing duplication while growing a design in ways
that improve its extensibility. There’s plenty of “duplication” of
various sorts in the above code. But merging it wouldn’t make the
design more extensible in the direction of more advanced roman numeral
codes. It turned out that merging the components of the output strings
- I, V etc. - focused the design directly on what was important.
···
–
Phlip
Test First User Interfaces