abc Programski jezik Java
Objektno orijentisano programiranje

22. Pretvaranje iz rimskog u arapski i arapskog u rimski broj.

Opis rješenja:

Napomena citaocu: klasa prezentovana ovde ce da pretvori u arapski broj i"neispravan" rimski broj. Naime, Rimski broj ne smije da sadrzi vise od tri uzastopna
znaka: I, X, C, M, sto znaci da XIIII nije ispravno napisano 14, ispravno bi bilo XIV.

Takodje, prilikom oduzimanja (cifra sa manjom vrijednoscu se nadje prije cifre sa vecom)
Dozvoljene su samo sledece kombinacije: IV - 4, IX - 9, XL - 40, XC - 90, CD - 400, CM - 900.
Tako je recimo IC neispravan rimski broj, a ne 99.

S obzirom da broj pravila i moguce komplikacije prilikom njihovog implementiranja, dati kod ce pretvarati i neispravne rimske brojeve, a dopuna koda se ostavlja kao vjezba citaocu.

import java.util.*;
/*
 * Napomena citaocu: klasa prezentovana ovde ce da pretvori u arapski broj i
 * "neispravan" rimski broj. Naime, Rimski broj ne smije da sadrzi vise od tri uzastopna
 * znaka: I, X, C, M, sto znaci da XIIII nije ispravno napisano 14, ispravno bi bilo XIV.
 * 
 * Takodje, prilikom oduzimanja (cifra sa manjom vrijednoscu se nadje prije cifre sa vecom)
 * Dozvoljene su samo sledece kombinacije: IV - 4, IX - 9, XL - 40, XC - 90, CD - 400, CM - 900.
 * Tako je recimo IC neispravan rimski broj, a ne 99.
 * 
 * S obzirom da broj pravila i moguce komplikacije prilikom njihovog implementiranja, dati kod
 * ce pretvarati i neispravne rimske brojeve, a dopuna koda se ostavlja kao vjezba citaocu.
 */

class RimskiBroj {

	// Cjelobrojna decimalna reprezentacija
	private int n;

	// Konstruktori
	public RimskiBroj(int n) {
		/*
		 * Rimski brojevi ne mogu predstaviti negativne vrijednost te nulu. Za
		 * predstavljanje brojeva preko 4000 potrebno je koristi dodatne oznake
		 * koje Java ne podrzava.
		 */
		if (n < 1)
			this.n = 1;
		else if (n > 3999)
			this.n = 3999;
		else
			this.n = n;
	}

	public RimskiBroj(String r) {
		/*
		 * Problem kod pretvaranja Rimskog broja u "normalni", arapski, jeste sto 
		 * X ne mora uvijek predstavljati broj 10. Naime ako se X nadje ispred C, tada kombinacija XC postaje 90,
		 * sto znaci da ne mozemo na osnovu samo jednog slova odrediti njegovu vrijednost.
		 */
		
		r = r.toUpperCase(); // Pretvori sva slova u velika da ne binemo o tome.
		this.n = 0; // Na pocetku je nula, kako saznajemo cifre, povecavacemo ovu vrijednost.
		
		for(int i = 0; i < r.length(); ++i)
		{
			int prvaCifra = vrijednostRimskeCifra(r.charAt(i));
			int drugaCifra;
			
			/*	 Ako provjeravamo zadnju cifru, ocigledno ne postoji sledeca, tako da stavimo njenu 
				vrijednost na nulu tako da ne prodje donji uslov */
			if(i == r.length() - 1)
				drugaCifra = 0;
			else
				drugaCifra = vrijednostRimskeCifra(r.charAt(i + 1));
			
			/* Vrijednost ce se oduzimati samo ako je vrijednost prve manja od vrijednosti druge */
			if(prvaCifra < drugaCifra)
				n += drugaCifra - prvaCifra;
			else
				n += prvaCifra; // Drugu ostavljamo, jer ce ona biti prvaCifra u drugom krugu.
		}
	}

	private int vrijednostRimskeCifra(char cifra)
	{
		int vrijednost = 0;
	    switch (cifra)
	    {
	    case 'I':
	        vrijednost = 1;
	        break;
	    case 'V':
	        vrijednost = 5;
	        break;
	    case 'X':
	        vrijednost = 10;
	        break;
	    case 'L':
	        vrijednost = 50;
	        break;
	    case 'C':
	        vrijednost = 100;
	        break;
	    case 'D':
	        vrijednost = 500;
	        break;
	    case 'M':
	        vrijednost = 1000;
	        break;
	    default:
	        vrijednost = -1;
	    }
	    return vrijednost;
	}
	
	// Pretvaranje rimskog u decimalni broj
	public int toInt() {
		return n;
	}

	// Pretvaranje decimalnog u rimski broj
	public String toString() {
		return arapskiURimski(n);
	}

	// Pomocni rekurzivni metod za pretvaranje
	// decimalnog broja u rimski broj
	private String arapskiURimski(int n) {
		if (n >= 1000) return "M" + arapskiURimski(n - 1000);
		if (n >= 900) return "CM" + arapskiURimski(n - 900);
		if (n >= 500) return "D" + arapskiURimski(n - 500);
		if (n >= 400) return "CD" + arapskiURimski(n - 400);
		if (n >= 100) return "C" + arapskiURimski(n - 100);
		if (n >= 90) return "XC" + arapskiURimski(n - 90);
		if (n >= 50) return "L" + arapskiURimski(n - 50);
		if (n >= 40) return "XL" + arapskiURimski(n - 40);
		if (n >= 10) return "X" + arapskiURimski(n - 10);
		if (n >= 9) return "IX" + arapskiURimski(n - 9);
		if (n >= 5) return "V" + arapskiURimski(n - 5);
		if (n >= 4) return "IV" + arapskiURimski(n - 4);
		if (n >= 1) return "I" + arapskiURimski(n - 1);
		return "";
	}

	// Staticki metod za sabiranje dva rimska broja:
	// RimskiBroj z = RimskiBroj.zbir(x, y)
	public static RimskiBroj zbir(RimskiBroj a, RimskiBroj b) {
		return new RimskiBroj(a.n + b.n);

	}

	// Objektni metod za sabiranje dva rimska broja:
	// RimskiBroj z = x.dodaj(y);
	public RimskiBroj dodaj(RimskiBroj a) {
		return new RimskiBroj(this.n + a.n);
	}

	// Staticki metod za proizvod dva rimska broja:
	// RimskiBroj z = RimskiBroj.proizvod(x, y)
	public static RimskiBroj proizvod(RimskiBroj a, RimskiBroj b) {
		return new RimskiBroj(a.n * b.n);

	}

	// Objektni metod za proizvod dva rimska broja:
	// RimskiBroj z = x.pomnoži(y);
	public RimskiBroj pomnoži(RimskiBroj a) {
		return new RimskiBroj(this.n * a.n);
	}
	
public static void main(String[] args) {

		
		RimskiBroj x = new RimskiBroj("xxxiiii"); // 34
		System.out.println("x = " + x.toInt());
		System.out.println("x = " + x); // x.toString()

		RimskiBroj y = new RimskiBroj("mdclxvi"); // 1666
		System.out.println("y = " + y.toInt());
		System.out.println("y = " + y); // y.toString()

		System.out.println();

		// RimskiBroj.zbir(x,y).toString()
		System.out.println("x+y = " + RimskiBroj.zbir(x, y));
		System.out.println("x+y = " + RimskiBroj.zbir(x, y).toInt());

		// x.dodaj(y).toString()
		System.out.println("x+y = " + x.dodaj(y));
		System.out.println("x+y = " + x.dodaj(y).toInt());

		System.out.println();

		// RimskiBroj.proizvod(x,y).toString()
		System.out.println("x*y = " + RimskiBroj.proizvod(x, y));
		System.out.println("x*y = " + RimskiBroj.proizvod(x, y).toInt());

		// x.pomnoži(y).toString()
		System.out.println("x*y = " + x.pomnoži(y));
		System.out.println("x*y = " + x.pomnoži(y).toInt());
	}

}

Ispis na ekranu:

Index