Gyakorlati alapok II.

Váltogassunk tovább: római-arab szám váltó I.

 

Először nézzük meg a kötelező elméleti vonatkozásokat!

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

A római számjelölés úgynevezett additív (hozzáadásos) számábrázolási módszer, amely során bizonyos számértékek önálló jelölést kaptak (római számok esetében ezek a latin ABC bizonyos nagybetűi) és a számösszeg ezen jelölések egymás mellé tevéses, illetve ezek összeadásán alapuló kombinációiból épül fel. Az alapkészlet:

Számok ábrázolásakor a sorrend balról jobbra (→) haladva a következő (ettől azonban logikátlanul vannak eltérések):

  1. ha van - ezresek

  2. ha van - százasok

  3. ha van - tízesek

  4. egyesek

Például:

Tulajdonságai:

Projektügyileg nézve tehát maximálisan 3999 db római számot kell átkonvertálnunk arab számra. Valójában ez adatbázis szempontjából nem olyan sok adat, ezért nagy a kísértés, hogy mind a 3999 db római számot beletegyük 1 db adatbázisba és onnan hajtsuk végre a lekérdezést (íme a lista). Ezt a Számváltás adatbázisból című fejezetben fogjuk megtenni. Ezen megoldás roppant nagy előnye, hogy nem kell vesződnünk validátor (helyesség ellenőrző) függvény írásával. A problémát azonban mégsem kerüljük meg, ezért ki kell egészítenünk a konvertálást logikai algoritmusos megoldással is, illetve bónuszként a rendkívül bonyolult validátor függvény megalkotásával (Utóirat: a korrekt római szám validátor című fejezet).

 

Az alábbi logikai algoritmus magja a www.stackoverflow.com című oldalról származik, amelyet én saját kódokkal egészítettem ki.

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

Ezen ne lepődjünk meg: nem számítva a kötelező szerzői jogi megjegyzést (a mostani esetben ez a forrásmegjelölés, azaz www.stackoverflow.com), a problémák felmerülésekor a gyakorló programozók első dolga az Interneten való rákeresés szokott lenni.

 

A feladat funkcióit természetesen külön metódusokban kell megvalósítanunk, ezek a következők:

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.Scanner;

public class Main {
    static String adatBekeres(){
    Scanner in = new Scanner (System.in);
    String romaiString = new String();
    boolean rosszAdat = false;
    System.out.println ("Kérem, hogy adja meg a római számot!");
    do{
        romaiString = in.nextLine();
        rosszAdat = ellenorzesString(romaiString);
    }while (rosszAdat == true);

    rosszAdat = false;
    return romaiString;
}

static boolean ellenorzesString(String romaiString){
    boolean rosszAdat = false;
    char karakter = romaiString.charAt(0);
    if(karakter == '0'){
        rosszAdat = true;
    }
    for(int i = 0; i < romaiString.length(); i++){
        karakter = romaiString.charAt(i);
        if(karakter != 'I'
        && karakter != 'V'
        && karakter != 'X'
        && karakter != 'L'
        && karakter != 'C'
        && karakter != 'D'
        && karakter != 'M'){
        rosszAdat = true;
        break;
        }
    }
    if(rosszAdat == true){
        System.out.println("Kérem, hogy megfelelő karaktereket adjon meg (I,V,X,L,C,D,M)");
    }
    return rosszAdat;
}

public static void konverter(String romaiString) {

    int decimalisSzam = 0;
    int utolsoSzam = 0;
    String romaiSzam = romaiString.toUpperCase();
    for (int i = romaiSzam.length() - 1; i >= 0 ; i--) {
        char romaiSzamKarakter = romaiSzam.charAt(i);
        switch (romaiSzamKarakter) {
            case 'M':
                decimalisSzam = szamitas(1000, utolsoSzam, decimalisSzam);
                utolsoSzam = 1000;
                break;

            case 'D':
                decimalisSzam = szamitas(500, utolsoSzam, decimalisSzam);
                utolsoSzam = 500;
                break;

            case 'C':
                decimalisSzam = szamitas(100, utolsoSzam, decimalisSzam);
                utolsoSzam = 100;
                break;

            case 'L':
                decimalisSzam = szamitas(50, utolsoSzam, decimalisSzam);
                utolsoSzam = 50;
                break;

            case 'X':
                decimalisSzam = szamitas(10, utolsoSzam, decimalisSzam);
                utolsoSzam = 10;
                break;

            case 'V':
                decimalisSzam = szamitas(5, utolsoSzam, decimalisSzam);
                utolsoSzam = 5;
                break;

            case 'I':
                decimalisSzam = szamitas(1, utolsoSzam, decimalisSzam);
                utolsoSzam = 1;
                break;
            }
      }
    System.out.println(decimalisSzam);
}

public static int szamitas(int decimalisSzam, int utolsoSzam, int utolsoDecimalisSzam) {
    if (utolsoSzam > decimalisSzam) {
        return utolsoDecimalisSzam - decimalisSzam;
    } else {
        return utolsoDecimalisSzam + decimalisSzam;
    }
}

public static void main(java.lang.String args[]) {
    String romaiString = adatBekeres();
    konverter(romaiString);
    }
}

 

Végeredmény:

Kérem, hogy adja meg a római számot!
MMMCMXCIX
3999

 

A kód működőképes, de valójában az ellenőrzési rész (ellenorzesString()) pontatlan, mert a római számok jelölése további belső szabályokat is magában hordoz. Így lehetséges, hogy például a római V (5) helyett IIIII karakterkombinációt is begépelhetünk, ami nem megengedett. Az érvényességi vizsgálatokat az Utóirat: a korrekt római szám validátor című fejezetben tanulmányozhatjuk. Az alábbi, futtatható Java-kód már az ott publikált kódot tartalmazza. Az alábbi Java-kódban az ellenorzesString() nevű metódust romaiSzamValidator() névre neveztük át:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.Scanner;

public class Main {
    static char karakter;
    static boolean rosszAdat = false;
    static int tombIndexOfKarakter[] = new int[7];
    static String [] nemMegengedettString = new String[58];
    static {
        nemMegengedettString[0] = "IIII";
        nemMegengedettString[1] = "IIIII";
        nemMegengedettString[2] = "IIIIII";
        nemMegengedettString[3] = "IIIIIII";
        nemMegengedettString[4] = "IIIIIIII";
        nemMegengedettString[5] = "IIIIIIIII";
        nemMegengedettString[6] = "IIV";
        nemMegengedettString[7] = "IIIV";
        nemMegengedettString[8] = "VV";
        nemMegengedettString[9] = "VVV";
        nemMegengedettString[10] = "VVVV";
        nemMegengedettString[11] = "VVVVV";
        nemMegengedettString[12] = "VVVVVV";
        nemMegengedettString[13] = "VVVVVVV";
        nemMegengedettString[14] = "VVVVVVVV";
        nemMegengedettString[15] = "VVVVVVVVV";
        nemMegengedettString[16] = "IIX";
        nemMegengedettString[17] = "IIIX";
        nemMegengedettString[18] = "XXXX";
        nemMegengedettString[19] = "XXXXX";
        nemMegengedettString[20] = "XXXXXX";
        nemMegengedettString[21] = "XXXXXXX";
        nemMegengedettString[22] = "XXXXXXXX";
        nemMegengedettString[23] = "XXXXXXXXX";
        nemMegengedettString[24] = "XXL";
        nemMegengedettString[25] = "LL";
        nemMegengedettString[26] = "LLL";
        nemMegengedettString[27] = "LLLL";
        nemMegengedettString[28] = "LLLLL";
        nemMegengedettString[29] = "LLLLLL";
        nemMegengedettString[30] = "LLLLLLL";
        nemMegengedettString[31] = "LLLLLLLL";
        nemMegengedettString[32] = "LLLLLLLLL";
        nemMegengedettString[33] = "XXC";
        nemMegengedettString[34] = "CCCC";
        nemMegengedettString[35] = "CCCCC";
        nemMegengedettString[36] = "CCCCCC";
        nemMegengedettString[37] = "CCCCCCC";
        nemMegengedettString[38] = "CCCCCCCC";
        nemMegengedettString[39] = "CCCCCCCCC";
        nemMegengedettString[40] = "CCD";
        nemMegengedettString[41] = "CCCD";
        nemMegengedettString[42] = "DD";
        nemMegengedettString[43] = "DDD";
        nemMegengedettString[44] = "DDDD";
        nemMegengedettString[45] = "DDDDD";
        nemMegengedettString[46] = "DDDDDD";
        nemMegengedettString[47] = "DDDDDDD";
        nemMegengedettString[48] = "DDDDDDDD";
        nemMegengedettString[49] = "DDDDDDDDD";
        nemMegengedettString[50] = "CCM";
        nemMegengedettString[51] = "CCCM";
        nemMegengedettString[52] = "MMMM";
        nemMegengedettString[53] = "MMMMM";
        nemMegengedettString[54] = "MMMMMM";
        nemMegengedettString[55] = "MMMMMMM";
        nemMegengedettString[56] = "MMMMMMMM";
        nemMegengedettString[57] = "MMMMMMMMM";
    }

static String adatBekeres(){
    Scanner in = new Scanner (System.in);
    String romaiString = "";
    boolean rosszAdat = false;
    System.out.println ("Kérem, hogy adja meg a római számot!");
    do{
        romaiString = in.nextLine();
        rosszAdat = romaiSzamValidator(romaiString);
        if(rosszAdat == true){
    System.out.println("Kérem, hogy csak megfelelő karaktereket

                                és kombinációkat adjon meg (I,V,X,L,C,D,M)\nÚjra!");
    }
    }while (rosszAdat == true);
    return romaiString;
}

static boolean romaiSzamValidator(String romaiString){
    rosszAdat = false;
    rosszAdat = hossz(romaiString);
    rosszAdat = karakter(romaiString);
    rosszAdat = nemMegengedettString(romaiString);
    rosszAdat = nemMegengedettString2(romaiString);
    rosszAdat = karakterPozicio(romaiString);
    rosszAdat = karakterPozicio2(romaiString);
    return rosszAdat;
}

//Hiba: például nincs bemeneti String vagy VVVVVVVVVV (10 karakter)
static boolean hossz(String romaiString){
    boolean rosszAdat = false;
    if((romaiString.length() < 1 || romaiString.length() > 9)){
        rosszAdat = true;
    }
    return rosszAdat;
}

//Hiba: például a
static boolean karakter(String romaiString){
    for(int i = 0; i < romaiString.length(); i++){
    karakter = romaiString.charAt(i);
    if(karakter != 'I'
        && karakter != 'V'
        && karakter != 'X'
        && karakter != 'L'
        && karakter != 'C'
        && karakter != 'D'
        && karakter != 'M'){
        rosszAdat = true;
        }
    }
    return rosszAdat;
}

//Hiba: például IIIIIIIII
static boolean nemMegengedettString(String romaiString){
    for(int i = 0; i < nemMegengedettString.length; i++){
    if(nemMegengedettString[i].equals(romaiString)){
        rosszAdat = true;
    }
    else
        continue;
    }
    return rosszAdat;
}

//Hiba: például IIIVVIII
static boolean nemMegengedettString2(String romaiString){
    for(int i = 0; i < romaiString.length(); i++){
        for(int j = 0; j < nemMegengedettString.length; j++){
        if(romaiString.length() >= nemMegengedettString[j].length()){
            if(romaiString.contains(nemMegengedettString[j])){
                rosszAdat = true;
            }
        }
        else
            continue;
        }
    }
    return rosszAdat;
}

//Hiba:
//V nem lehet X előtt
//I, V nem lehet L előtt
//I, V, L nem lehet C előtt
//I, V, X, L nem lehet D előtt
//I, V, X, L, D nem lehet M előtt
static boolean karakterPozicio(String romaiString){
//A tombIndexOfKarakter tömb létrehozása, inicializálása
//M=0 D=1 C=2 L=3 X=4 V=5 I=6
for(int i = 0; i < tombIndexOfKarakter.length; i++){
    tombIndexOfKarakter[i] = 0;
}

for(int i = 0; i < romaiString.length(); i++){
    karakter = romaiString.charAt(i);
    if(karakter == 'M'){
        tombIndexOfKarakter[0] = (romaiString.indexOf('M')) + 1;
    }
    else if(karakter == 'D'){
        tombIndexOfKarakter[1] = (romaiString.indexOf('D')) + 1;
    }
    else if(karakter == 'C'){
        tombIndexOfKarakter[2] = (romaiString.indexOf('C')) + 1;
    }
    else if(karakter == 'L'){
        tombIndexOfKarakter[3] = (romaiString.indexOf('L')) + 1;
    }
    else if(karakter == 'X'){
        tombIndexOfKarakter[4] = (romaiString.indexOf('X')) + 1;
    }
    else if(karakter == 'V'){
        tombIndexOfKarakter[5] = (romaiString.indexOf('V')) + 1;
    }
    else if(karakter == 'I'){
        tombIndexOfKarakter[6] = (romaiString.indexOf('I')) + 1;
    }
}

if(((tombIndexOfKarakter[6] < tombIndexOfKarakter[0]) && ((tombIndexOfKarakter[6] != 0) && (tombIndexOfKarakter[0] != 0))
|| (tombIndexOfKarakter[5] < tombIndexOfKarakter[0]) && ((tombIndexOfKarakter[5] != 0) && (tombIndexOfKarakter[0] != 0))
|| (tombIndexOfKarakter[4] < tombIndexOfKarakter[0]) && ((tombIndexOfKarakter[4] != 0) && (tombIndexOfKarakter[0] != 0))
|| (tombIndexOfKarakter[3] < tombIndexOfKarakter[0]) && ((tombIndexOfKarakter[3] != 0) && (tombIndexOfKarakter[0] != 0))
|| (tombIndexOfKarakter[2] < tombIndexOfKarakter[0]) && ((tombIndexOfKarakter[2] != 0) && (tombIndexOfKarakter[0] != 0))
)){
rosszAdat = true;
}

if(((tombIndexOfKarakter[6] < tombIndexOfKarakter[1]) && ((tombIndexOfKarakter[6] != 0) && (tombIndexOfKarakter[1] != 0))
|| (tombIndexOfKarakter[5] < tombIndexOfKarakter[1]) && ((tombIndexOfKarakter[5] != 0) && (tombIndexOfKarakter[1] != 0))
|| (tombIndexOfKarakter[4] < tombIndexOfKarakter[1]) && ((tombIndexOfKarakter[4] != 0) && (tombIndexOfKarakter[1] != 0))
|| (tombIndexOfKarakter[3] < tombIndexOfKarakter[1]) && ((tombIndexOfKarakter[3] != 0) && (tombIndexOfKarakter[1] != 0))
)){
rosszAdat = true;
}

if(((tombIndexOfKarakter[6] < tombIndexOfKarakter[2]) && ((tombIndexOfKarakter[6] != 0) && (tombIndexOfKarakter[2] != 0))
|| (tombIndexOfKarakter[5] < tombIndexOfKarakter[2]) && ((tombIndexOfKarakter[5] != 0) && (tombIndexOfKarakter[2] != 0))
|| (tombIndexOfKarakter[3] < tombIndexOfKarakter[2]) && ((tombIndexOfKarakter[3] != 0) && (tombIndexOfKarakter[2] != 0))
)){
rosszAdat = true;
}

if(((tombIndexOfKarakter[6] < tombIndexOfKarakter[3]) && ((tombIndexOfKarakter[6] != 0) && (tombIndexOfKarakter[3] != 0))
|| (tombIndexOfKarakter[5] < tombIndexOfKarakter[3]) && ((tombIndexOfKarakter[5] != 0) && (tombIndexOfKarakter[3] != 0))
)){
rosszAdat = true;
}

if(((tombIndexOfKarakter[5] < tombIndexOfKarakter[4]) && ((tombIndexOfKarakter[5] != 0) && (tombIndexOfKarakter[4] != 0))
)){
rosszAdat = true;
}
return rosszAdat;
}

static boolean karakterPozicio2(String romaiString){
//A tombIndexOfKarakter tömb újrafelhasználása
//M=0 D=1 C=2 L=3 X=4 V=5 I=6
for(int i = 0; i < tombIndexOfKarakter.length; i++){
    tombIndexOfKarakter[i] = 0;
}

for(int i = 0; i < romaiString.length(); i++){
    karakter = romaiString.charAt(i);
    if(karakter == 'M'){
        tombIndexOfKarakter[0] += 1;
    }
    else if(karakter == 'D'){
        tombIndexOfKarakter[1] += 1;
    }
    else if(karakter == 'C'){
        tombIndexOfKarakter[2] += 1;
    }
    else if(karakter == 'L'){
        tombIndexOfKarakter[3] += 1;
    }
    else if(karakter == 'X'){
        tombIndexOfKarakter[4] += 1;
    }
    else if(karakter == 'V'){
        tombIndexOfKarakter[5] += 1;
    }
    else if(karakter == 'I'){
        tombIndexOfKarakter[6] += 1;
    }
}

//M-hiba: például MIMI, MIIM, egyetlen kivétel MMCM
if(tombIndexOfKarakter[0] == 2 && !romaiString.contains("MM")){
    rosszAdat = true;
}
else if(romaiString.equals("MMCM") ){
    rosszAdat = false;
    return rosszAdat;
}
else if(tombIndexOfKarakter[0] == 3 && !romaiString.contains("MMM") ){
    rosszAdat = true;
}

//D-hiba: például DMD
else if(tombIndexOfKarakter[1] > 1){
    rosszAdat = true;
}

//C-hiba: például CXC, CCIC, egyetlen kivétel CCXC
else if(tombIndexOfKarakter[2] == 2 && !romaiString.contains("CC")){
    rosszAdat = true;
}
else if(romaiString.equals("CCXC") ){
    rosszAdat = false;
    return rosszAdat;
}
else if(tombIndexOfKarakter[2] == 3 && !romaiString.contains("CCC")){
    rosszAdat = true;
}

//L-hiba: például LIL
else if(tombIndexOfKarakter[3] > 1){
    rosszAdat = true;
}

//X-hiba: XIXI, egyetlen kivétel XIX
else if(romaiString.equals("XIX") ){
    rosszAdat = false;
    return rosszAdat;
}
else if(tombIndexOfKarakter[4] == 2 && !romaiString.contains("XX")){
    rosszAdat = true;
}
//XXVX, egyetlen kivétel XXIX
else if(romaiString.equals("XXIX") ){
    rosszAdat = false;
    return rosszAdat;
}
else if(tombIndexOfKarakter[4] == 3 && !romaiString.contains("XXX")){
    rosszAdat = true;
}

//V-hiba: például VIV
else if(tombIndexOfKarakter[5] > 1){
    rosszAdat = true;
}

//I-hiba: például IXI, IVII
if(tombIndexOfKarakter[6] == 2 && !romaiString.contains("II")){
    rosszAdat = true;
}
else if(tombIndexOfKarakter[6] == 3 && !romaiString.contains("III")){
    rosszAdat = true;
}
    return rosszAdat;
}

public static void konverter(String romaiString) {
int decimalisSzam = 0;
int utolsoSzam = 0;
String romaiSzam = romaiString.toUpperCase();
for (int i = romaiSzam.length() - 1; i >= 0 ; i--) {
    char romaiSzamKarakter = romaiSzam.charAt(i);
    switch (romaiSzamKarakter) {
        case 'M':
            decimalisSzam = szamitas(1000, utolsoSzam, decimalisSzam);
            utolsoSzam = 1000;
            break;

        case 'D':
            decimalisSzam = szamitas(500, utolsoSzam, decimalisSzam);
            utolsoSzam = 500;
            break;

        case 'C':
            decimalisSzam = szamitas(100, utolsoSzam, decimalisSzam);
            utolsoSzam = 100;
            break;

        case 'L':
            decimalisSzam = szamitas(50, utolsoSzam, decimalisSzam);
            utolsoSzam = 50;
            break;

        case 'X':
            decimalisSzam = szamitas(10, utolsoSzam, decimalisSzam);
            utolsoSzam = 10;
            break;

        case 'V':
            decimalisSzam = szamitas(5, utolsoSzam, decimalisSzam);
            utolsoSzam = 5;
            break;

        case 'I':
            decimalisSzam = szamitas(1, utolsoSzam, decimalisSzam);
            utolsoSzam = 1;
            break;
        }
    }
    System.out.println(decimalisSzam);
}

public static int szamitas(int decimalisSzam, int utolsoSzam, int utolsoDecimalisSzam) {
if (utolsoSzam > decimalisSzam) {
    return utolsoDecimalisSzam - decimalisSzam;
} else {
    return utolsoDecimalisSzam + decimalisSzam;
    }
}

public static void main(java.lang.String args[]) {
    String romaiString = adatBekeres();
    konverter(romaiString);
    }
}

 

Végeredmény:

Kérem, hogy adja meg a római számot!
IIIIIIIIII
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
IIIIVII
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
A
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
VX
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
MIMI
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
DMD
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
CCIC
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
LIL
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
XIXI
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
XXVX
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
VIV
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
IVII
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
IIII
Kérem, hogy csak megfelelő karaktereket és kombinációkat adjon meg (I,V,X,L,C,D,M)
Újra!
III
3