Roman Numerals

Test Driven Development (TDD) is the concept of first writing a failing test for your code then coding to pass then test and refactoring to meet all possible test cases.

The challenge used to practice TDD focuses on loops and iteration with some simple math and string manipulation. Included in each level is a basic solution, look to it if you get stuck.

The Challenge

This is a simple variant of the Roman Numerals Code Kata where we will be taking arabic numbers and converting them to roman numbers (I, V, X, L, C, D, M).

The Romans developed a numbering system using letters. They were clever about this with rules so that you will not see more than three of the same letter together. Therefore 3 in roman numerals is “III” and 5 is “V” and then added these together to get higher numbers like 7 which is “VII”. To get 4 they had to subtract one from 5. They did this by placing the “I” to the left of the “V” so 4 is “IV”.

1
2
3
4
5
6
7
I = 1
V = 5
X = 10
L = 50
C = 100
D = 500
M = 1,000

Creating a Test Case

No matter the level you choose to work with write a test case before you start your code. Then write just enough code to pass the test. Once you have passing code refactor to pass other test cases.

Some languages and frameworks have testing suites available to help build test driven apps. Here is a simple example of a test for this challenge written in JavaScript:

1
2
3
4
5
6
7
8
9
function TestCase() {
var testNum = 3;
var result = ConvertToRoman(testNum);
if (result == "III"){
console.log("Test Passed");
} else {
console.log("Test Failed");
}
}

Your initial failing code would look as follows:

1
2
3
function ConvertToRoman(num){
return "";
}

In this case your initial passing code before refactoring would look as follows:

1
2
3
function ConvertToRoman(num){
return "III";
}

Why would we write such a useless function just to pass the test when we know we will have to refactor? In a way it tests the test to show that we are testing what we think we are testing. In this example it seems silly but with some of the testing available for advanced frameworks this is good because you may not be testing what you think and your passing code that will does not do what it is supposed to do.

Level 1

Create a simple tick counter so that if the number 3 is entered the output will be “///“. Then group the ticks into sets of five so that if 15 is entered the output will look like “///// ///// /////“.

A Step further

Going a step further replace the “/////“ with a simpler way of recognizing a unit of 5 ticks. For example if 12 is entered the output would be “V V //“. Don’t forget to adjust your test case to accommodate the change in output.

Solution

Level 2

Start out writing a simple function to pass your test case. So for the example test case the following code would pass just the test case:

1
2
3
function ConvertToRoman(num){
return "III";
}

Next refactor convert any number up to 3. Then add logic to convert 5 through 7. Next have your function determine if a number is between 5 and 3 and add the appropriate amount of “I” to the left of the “V” to subtract down. Continue refactoring to add 10’s, 50’s and 100’s. If you have time try to get any number up to 3,000.

A Step Further

Now that you’ve written your code to accept any number up to 3,000 go back and look at your code. You probably used a lot of if statements. Refactor your code to use less if statements and make it more legible to someone looking at it for the first time.

Solution

Level 3

In this level we are doing the reverse of the kata. Take an input of a roman numeral and convert it back to an arabic number.

Start with writing a test case. Then code to the test and refactor to accept any test case. A sample in JavaScript will be:

1
2
3
4
5
6
7
8
9
function TestCase(){
var testRom = "III";
var result = ConvertToArabic(testRom);
if (result == 3){
console.log("Test Passed");
} else {
console.log("Test Failed");
}
}

In this case the return value is an integer but you can have it return a string just set your test case up for the return type.

Hint

The only characters allowed are I, V, X, L, C, and M. Also romans did not have a concept of zero so you will not return that number.

A step further

Taking this a step further write your code so that it will return an error if the characters are not roman numerals or in the correct order of roman numerals but allow for both upper and lowercase on the characters allowed.

Solution

All Levels Bonus

If you have extra time build a user interface so that numbers can be entered byt he user then converted via your code then displayed in the new format.