Fun with Roman Numerals

This is my small code snippet that I found really enjoyable to program. This is only a small piece of code that I just hacked my way through in 2 hours, but the one thing that made me want to publish this one instead of all of the freelance, work related, or university related projects was that the case context of turning Roman numerals into real integer numbers was harder than I thought.

I can build Java EE and Spring applications, with the latest standards and deploy it, but trying to figure crack a nut like this, was unbelievably engaging as you had to look the problem from left to right, right to left, top to bottom, and from bottom up.  In the end, the problem was much simpler than I thought. This first breakthrough of getting at least few number combinations right is shown below (in Finnish).

 

MainController class

import java.util.Scanner;
import java.util.Set;

/**
* @author Kurosh Farsimadan
*
*/

public class MainController {

public static RomanNumerals romanToInteger = new RomanNumerals();
// Halutaan käyttäjän syotto, joten käytämme alla olevaa luokkaa syötön saamista varten
private static Scanner input = new Scanner(System.in);

/** Main metodi ohjelman käynnistämiseksi **/
public static void main(String[] args) {
mainMethod();
}

/** Pääohjelma, sovelluksen algoritmien rakentamiseen **/
private static void mainMethod() {
String syotto;
System.out.println(“Syötä roomalainen numeraali: “);
syotto = input.nextLine();

// Mennään jokaisen roomalaisen aakkosen läpi, jotta voidaan algoritmiä käyttäen
// laskea lopputulos
int kokonaisArvo = 0;
for (int i = 0; i < syotto.length(); i++) {
int j = i + 1;
// Ensimmäinen if lauseke varmistaa, että ei iteroida syoton yli, koska meidän pitää tarkistaa
// sellaiset roomalaiset numeraalit, kuten CCXII, jotka eivät ole parillisia esim. CC on kaksi
// aakkosta, XI on kaksi aakkosta, mutta lopussa oleva I ei ole parillinen ja sen tarkistus pitää
// tehdä aikaisemmalla roomalaisella aakkosella/numerolla. Sama pätee myös VII päätteisiin jne.
if(j == syotto.length()) {
j = i – 1; // halutaan aikaisempi aakkonen
int syotettyArvo = rkMetodi(syotto.charAt(i));
int aiempiArvo = rkMetodi(syotto.charAt(i-1));
if(syotettyArvo >= aiempiArvo) {
kokonaisArvo += syotettyArvo + aiempiArvo;
}
} else { // Tässä else metodissa haluamme käydä läpi kaikki roomalaiset aakkoset ennen viimeistä aakkosta
int syotettyArvo = rkMetodi(syotto.charAt(i)); // Läpikäydyn aakkosen arvo
int seuraavaArvo = rkMetodi(syotto.charAt(j)); // Seuraavan aakkosen arvo
if (syotettyArvo >= seuraavaArvo) {
kokonaisArvo += syotettyArvo + seuraavaArvo;
} else if (syotettyArvo < seuraavaArvo) {
kokonaisArvo += seuraavaArvo – syotettyArvo;
}
}
i = i + 1; // koska tarkistamme kaksi roomalaista aakkosta niin hyppäämme jo katsomamme roomalaisen aakkosen yli
// Esimerkkinä voidaan ottaa CCXII. Haluamme ensin katsoa CC aakkoset. Sitten XI jne. Emme halua käydä läpi
// CCXII jonoa seuraavanlaisesti esim. CC, CX, XI, II, koska laskualgoritmi menee sekaisin.
}
System.out.println(“Kokonaisarvo on: ” + kokonaisArvo);
}

/** Roomalainen numero kokonaisluvuksi metodi, joka palauttaa kokonaisluvun **/
private static int rkMetodi(char syotettyArvo) {
String muutosSyottoon = syotettyArvo + “”;
int parsettuAvainArvo = 0;
Set<String> avaimet = romanToInteger.getRomanToIntegerKeySet();
for(String avain: avaimet){ // Looppi pitää optimoida, muistinkäytön parantamiseksi
if(avain.equals(muutosSyottoon)) {
parsettuAvainArvo = Integer.parseInt(romanToInteger.getRomanToInteger(avain));
break;
}
}
return parsettuAvainArvo;
}
}

 

RomanNumerals class

import java.util.Hashtable;
import java.util.Set;

/**
*
*/

/**
* @author Kurosh Farsimadan
*
*/
public class RomanNumerals {

// “private modifier” — muuttujan arvo on vain saatavissa tämän luokan sisällä (the field is accessible only within its own class).
// “The static modifier” — Muuttujan arvoa ei voida muuttaa (in combination with the final modifier, is also used to define constants. The final modifier indicates that the value of this field cannot change.)
private static Hashtable<String, String> romanToInteger = new Hashtable<String, String>();

public RomanNumerals() {
super();
romanToInteger.put(“I”, “1”);
romanToInteger.put(“V”,”5″);
romanToInteger.put(“X”,”10″);
romanToInteger.put(“L”,”50″);
romanToInteger.put(“C”,”100″);
romanToInteger.put(“D”,”500″);
romanToInteger.put(“M”,”1000″);
}

/**
* @return the romanToInteger
*/
public Set<String> getRomanToIntegerKeySet() {
return romanToInteger.keySet();
}

/**
* @return the romanToInteger
*/
public String getRomanToInteger(String avain) {
return romanToInteger.get(avain);
}

/**
* @return the romanToInteger
*/
public Hashtable<String, String> getRomanToInteger() {
return romanToInteger;
}

/**
* @param romanToInteger the romanToInteger to set
*/
public void setRomanToInteger(Hashtable<String, String> romanToInteger) {
RomanNumerals.romanToInteger = romanToInteger;
}

@Override
public String toString() {
return “RomanNumerals ” + getClass() + “, ”
+ hashCode() + “, ” + super.toString() + “]”;
}

}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s