Reputation: 103
My next target is to implement Comparable Interface on Roman Number converter.
Maybe I need to use the interface like this:
public interface Comparable {
public int compareTo(Object x);
}
and after implement RomanNumber with this instruction:
public class RomanNumber implements Comparable<RomanNumber>
but I don't know as to continue. And more I need to test in JUnit this new method. I think this:
@Override
public int compareTo(Object o) {
if(this.number>((RomanNumber)o).convertToInteger()){
return 1;
} else if(this.number<((RomanNumber)o).convertToInteger()){
return -1;
} else{
return 0;
}
}
}
Here is the code under test:
public class RomanNumber{
private String number;
public RomanNumber (String number){
validateState(number);
this.number = number;
}
public int convertToInteger () {
int decimal = 0;
int lastNumber = 0;
number = number.toUpperCase();
for (int x = number.length() - 1; x >= 0; x--) {
char convertNumber = number.charAt(x);
switch (convertNumber) {
case 'M':
decimal = processDecimal(1000, lastNumber, decimal);
lastNumber = 1000;
break;
case 'D':
decimal = processDecimal(500, lastNumber, decimal);
lastNumber = 500;
break;
case 'C':
decimal = processDecimal(100, lastNumber, decimal);
lastNumber = 100;
break;
case 'L':
decimal = processDecimal(50, lastNumber, decimal);
lastNumber = 50;
break;
case 'X':
decimal = processDecimal(10, lastNumber, decimal);
lastNumber = 10;
break;
case 'V':
decimal = processDecimal(5, lastNumber, decimal);
lastNumber = 5;
break;
case 'I':
decimal = processDecimal(1, lastNumber, decimal);
lastNumber = 1;
break;
}
}
return decimal;
}
static int processDecimal(int decimal, int lastNumber, int lastDecimal) {
if (lastNumber > decimal) {
return lastDecimal - decimal;
} else {
return lastDecimal + decimal;
}
}
private void validateState(String number){
if (number == null)
throw new IllegalArgumentException("Null argument");
if (number.isEmpty())
throw new IllegalArgumentException("Empty string");
if (!number.matches("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
throw new IllegalArgumentException("Invalid Roman number");
}
@Override
public boolean equals(Object obj){
if ((obj instanceof RomanNumber)) {
RomanNumber decimal = (RomanNumber)obj;
if (number.equals(decimal.number)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public int hashCode(){
return number.hashCode();
}
}
Upvotes: 0
Views: 498
Reputation: 103
this is my logical idea:
public int compareTo(RomanNumber other){
// Compare RomanNumber
if (this.convertToInteger()<other.convertToInteger())
return -1;
if(this.convertToInteger()>other.convertToInteger())
return 1;
return 0;
and for the JUnit test:
// TODO test instance comparison
@Test
public void shouldCompareInstances() {
RomanNumber rn1 = new RomanNumber("M");
RomanNumber rn2 = new RomanNumber("MM");
Assert.assertTrue(rn1.compareTo(rn2) == -1);
}
Upvotes: 0
Reputation: 140525
Giving you some starting points.
First unit tests could look like
@Test
public void testConversionToIntegerD() {
assertThat(new RomanNumber("D").convertToInteger(), is(500));
}
And you would write many many tests like that; and make them more and complicated, to make sure that your conversion is correct. (ideally, you would have written those tests prior writing your conversion code).
And in order to compare to Roman numbers ... you know, you already implemented an conversion to Integer ... maybe, maybe that could give a hint how to compare to Roman numbers?! A test for that could look like:
@Test
public void testComparingDtoM() {
assertThat(new RomanNumber("D").compareTo(new RomanNumber("M")), is(-1));
}
And a word of warning: you want to spend quite some time thinking about the "corner cases"; those nice roman numbers that are really complicated. Ideally, if you are doing this thing in a class room, you should have other people writing up testcases. When you do such things alone, there is always a certain chance that you overlook those "corner cases" both in tests and backing implementation.
(finally: i used assertThat, as this style of assertions allows for writing all kinds of great conditions; the only downside is that you need to use it with Hamcrest matchers like is. But seriously: it will be worth you time learning about that stuff)
Upvotes: 1