Gyakorlati alapok

Mobilszámok osztályozása

 

Az egyik előző, kombinatorikai fejezetben a mobilszámokat listáztuk ki (Mobilszámok listázása). Ismételjük meg ezzel kapcsolatos legfontosabb megállapításainkat!
 

Amint az mindannyiunk előtt ismeretes, a mobiltelefonszám a kötelező előhívószámokon kívül 7 db számjegyből áll. Például magyar Telekom-hívószám esetén:
 

0036 - 30 - 0123456
országhívószám - tartományi hívószám - egyéni hívószám
 

Most az előhívószámokkal nem foglalkozunk, csakis a mobiltelefonszámok lehetséges variációival. Ennek tartományát könnyen felvázolhatjuk, mert az 0000000 és 9999999 között változik, tehát összvariációs mennyisége 10.000.000 db.
A mobiltelefonszám tehát 7 számjegyből áll és hasonlít egy konkrét, hétjegyű számjegyhez (például 1234567), de valójában nem az, hiszen míg itt elméletileg megengedettek olyan számvariációk, mint például 0000000, 0001111, 0123456, addig a “klasszikus” matematikában már nem.

 

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

 

Tehát ez a 7 számjegy csak 7 db összeillesztett számvariáció 0 és 9 között.

 

A konkrét számításra a kombinatorikai lehetőségek közül az ismétléses variációt alkalmazhatjuk, mert nk képlet alapján 107 = 10.000.000. Implementációs listázó motorunk a már jól bevált egybeágyazott ciklusok, amelyekben kiválóan felhasználhatjuk az összes iterátort (i, j, k, l, m, n, o), sőt még feltételeket sem kell állítanunk.


Ugyanakkor köztudott (vagy ha mégsem, akkor kikövetkeztethető), hogy a szolgáltatók használhatósági szempontból osztályozzák a mobilszámokat. A jól megjegyezhető számokat nyilvánvalóan extraárért biztosítják. Hogy ezt konkrétan miképpen menedzselik, nem tudom, de egyéni tapasztalatok és egy kis fantázia bevetésével eljátszhatunk a gondolattal és a kóddal.

Nos, a teljes számegyezős mobilszámokat az eszelős bennfentesek nyilvánvalóan maguknak tartják fent (például 1111111, de szerintem a legdurvább a 0000000), ám a sorozatokat (például 1234567, 7654321, 1234321, 4321234), illetve az egymás mellett lévő egyezéseket is extraárért kínálhatják főleg a marketingeseknek, például 1234444. Szerintem a mobilszolgáltató által vizsgált legkisebb egymás mellett lévő számegyezés 4 (én már láttam 3 számegyezést egyszerű mobiltelefonszámban, az tehát még biztosan nem definiált). Ettől a szinttől kezdve tehát a mobilszámokat nagy valószínűséggel külön algoritmussal szűrik és osztályozzák. Ugyanakkor garantáltan nem zárják ki a 0-val kezdődő mobilszámokat sem.

A fentiek alapján a feladat legyen a mobilszámok számegyezés szerinti osztályozása 4 és 7 egyezés között, külön állományokban (a Filekezelés című fejezetcsomagban leírtak szerint). A kódmotor ilyen esetekben a jól bevált egymásbaágyazott for ciklusok használata, amelyekhez speciális feltételeket kell beállítanunk. Utóbbiakat természetesen külön függvényekbe helyezzük. Mivel a feltételek jellege hasonló, elég csak egy függvényt implementálnunk és letesztelnünk, a többit pedig a már meglévőkhöz hozzáigazítanunk.

Az algoritmus ugyanakkor nem foglalkozik az egyértelmű szekvenciák keresésével, mert ennek szűrése viszonylag könnyű. Például:

Itt kell azonban megjegyeznünk, hogy további, sokszor “vizuális” és egyéb számegyezések, valamint érdekes számszekvenciák is észrevehetők, amelyek szintén kiemelkedhetnek a kaotikus mobilszámok jeltelen tömegéből. Például:

Ezek szűrőalgoritmusait viszont bízzuk a mobilszolgáltató programozóira vagy éppen lehet a Tisztelt Olvasó házi feladata is.

A kódanalízist ne a for ciklusokkal, hanem a feltételek magyarázatával kezdjük (majd később megértjük, hogy miért)!

 

Az alábbi, boolean típusú különutas függvény 7 számjegyhosszban összehasonlít egymás mellett lévő 4 számjegyet és ha ezek azonosak, akkor true értékkel jelzi:

static boolean isEquals4Digits(int i, int j, int k, int l, int m, int n, int o) {
    boolean isValid = false;
    if(i == j && j == k && k == l) {
        isValid = true;
        return isValid;
    }

    if(j == k && k == l && l == m) {
        isValid = true;
        return isValid;
    }

    if(k == l && l == m && m == n) {
        isValid = true;
        return isValid;
    }

    if(k == l && l == m && m == n) {
        isValid = true;
        return isValid;
    }

    if(l == m && m == n && n == o) {
        isValid = true;
        return isValid;
    }
    return isValid;
}


A külön függvényes megoldások egészen hasonlók 5-6-7 számegyezésre, ezért ezeket itt most nem részletezzük tovább.

A már említett egybeágyazott for ciklusok hajtják végre a listázást a main() főprogramban.

 

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

 

Figyelem! Ügyeljünk az állományok elérési útjainak pontos beállítására

(például: "E:\\List4.txt")!


public static void main(String[] args) throws IOException {
    PrintWriter writer4 = new PrintWriter(new FileWriter("E:\\List4.txt"));
    PrintWriter writer5 = new PrintWriter(new FileWriter("E:\\List5.txt"));
    PrintWriter writer6 = new PrintWriter(new FileWriter("E:\\List6.txt"));
    PrintWriter writer7 = new PrintWriter(new FileWriter("E:\\List7.txt"));
    int count4 = 1;
    int count5 = 1;
    int count6 = 1;
    int count7 = 1;
    int countAll = 0;
    for(int i = 0; i <= 9; i++) {
        for(int j = 0; j <= 9; j++) {
            for(int k = 0; k <= 9; k++) {
                for(int l = 0; l <= 9; l++) {
                    for(int m = 0; m <= 9; m++) {
                        for(int n = 0; n <= 9; n++) {
                            for(int o = 0; o <= 9; o++) {
                                countAll++;
                                if(isEquals4Digits(i, j, k, l, m, n, o)
                                    && !isEquals5Digits(i, j, k, l, m, n, o)
                                    && !isEquals6Digits(i, j, k, l, m, n, o)
                                    && !isEquals7Digits(i, j, k, l, m, n, o)
                                    ) {
                                    writer4.println(count4 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count4++;
                                }
                                if(isEquals5Digits(i, j, k, l, m, n, o)
                                    && !isEquals6Digits(i, j, k, l, m, n, o)
                                    && !isEquals7Digits(i, j, k, l, m, n, o)
                                ) {
                                    writer5.println(count5 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count5++;
                                }
                                if(isEquals6Digits(i, j, k, l, m, n, o)
                                    && !isEquals7Digits(i, j, k, l, m, n, o)
                                ) {
                                    writer6.println(count6 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count6++;
                                }
                                if(isEquals7Digits(i, j, k, l, m, n, o)) {
                                    writer7.println(count7 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count7++;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    writer4.close();
    writer5.close();
    writer6.close();
    writer7.close();
    System.out.println("Printing done!");
    System.out.println("Sum: " + countAll);
}

A kulcs a feltételek helyes beállítása a legbelső ciklusban, bár első pillanatra úgy tűnhet, hogy mindezekért csupán a validáló függvények felelősek. Ez igaz is, ám van itt egy érdekes szemantikai bökkenő. Mivel a isEquals4Digits() függvény szekvenciálisan lépked a számjegyeken, nem érzékeli az 5 és ennél nagyobb egyezéseket. Ezért pusztán az említett függvény meghívása nem elég…

if(isEquals4Digits(i, j, k, l, m, n, o)

...hanem 1 feltételen belül ki kell zárni az összes többi lehetőséget is:

if(isEquals4Digits(i, j, k, l, m, n, o)
    && !isEquals5Digits(i, j, k, l, m, n, o)
    && !isEquals6Digits(i, j, k, l, m, n, o)
    && !isEquals7Digits(i, j, k, l, m, n, o)
)


A szűrés további szigorítása már az elvárt eredményeket fogja eredményezni. További érdekesség, hogy a kapott listaelemeket az állományokban meg is számláljuk.

 

Azonban külső állományhasználat miatt kötelezően kivételkezeléssel is foglalkoznunk kell, bár ebben a kódban ezt nem visszük túlzásba, hiszen a main() főprogram fejlécében csak jelezzük, hogy kivételdobás, azaz valamilyen IO-műveleti hiba történhet (throws IOException). Amint az az illetékes fejezetcsomagban kidolgozásra került, ez a fajta deklaráció még nem jelent hibamegoldást, pusztán a kötelező kivételkezelés egyik definíciója.

Nézzük meg a futtatható Java-kódot:
 

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

 

 

 

 

 

 

 


import java.io.*;

public class Main {

public static void main(String[] args) throws IOException {
    PrintWriter writer4 = new PrintWriter(new FileWriter("E:\\List4.txt"));
    PrintWriter writer5 = new PrintWriter(new FileWriter("E:\\List5.txt"));
    PrintWriter writer6 = new PrintWriter(new FileWriter("E:\\List6.txt"));
    PrintWriter writer7 = new PrintWriter(new FileWriter("E:\\List7.txt"));
    int count4 = 1;
    int count5 = 1;
    int count6 = 1;
    int count7 = 1;
    int countAll = 0;
    for(int i = 0; i <= 9; i++) {
        for(int j = 0; j <= 9; j++) {
            for(int k = 0; k <= 9; k++) {
                for(int l = 0; l <= 9; l++) {
                    for(int m = 0; m <= 9; m++) {
                        for(int n = 0; n <= 9; n++) {
                            for(int o = 0; o <= 9; o++) {
                                countAll++;
                                if(isEquals4Digits(i, j, k, l, m, n, o)
                                    && !isEquals5Digits(i, j, k, l, m, n, o)
                                    && !isEquals6Digits(i, j, k, l, m, n, o)
                                    && !isEquals7Digits(i, j, k, l, m, n, o)
                                    ) {
                                    writer4.println(count4 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count4++;
                                }
                                if(isEquals5Digits(i, j, k, l, m, n, o)
                                    && !isEquals6Digits(i, j, k, l, m, n, o)
                                    && !isEquals7Digits(i, j, k, l, m, n, o)
                                ) {
                                    writer5.println(count5 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count5++;
                                }
                                if(isEquals6Digits(i, j, k, l, m, n, o)
                                    && !isEquals7Digits(i, j, k, l, m, n, o)
                                ) {
                                    writer6.println(count6 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count6++;
                                }
                                if(isEquals7Digits(i, j, k, l, m, n, o)) {
                                    writer7.println(count7 + ".: " + "0630-" + i + j + k + l + m + n + o);
                                    count7++;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    writer4.close();
    writer5.close();
    writer6.close();
    writer7.close();
    System.out.println("Printing done!");
    System.out.println("Sum: " + countAll);
}

static boolean isEquals4Digits(int i, int j, int k, int l, int m, int n, int o) {
    boolean isValid = false;
    if(i == j && j == k && k == l) {
        isValid = true;
        return isValid;
    }

    if(j == k && k == l && l == m) {
        isValid = true;
        return isValid;
    }

    if(k == l && l == m && m == n) {
        isValid = true;
        return isValid;
    }

    if(k == l && l == m && m == n) {
        isValid = true;
        return isValid;
    }

    if(l == m && m == n && n == o) {
        isValid = true;
        return isValid;
    }
    return isValid;
}


static boolean isEquals5Digits(int i, int j, int k, int l, int m, int n, int o) {
    boolean isValid = false;
    if(i == j && j == k && k == l && l == m) {
        isValid = true;
        return isValid;
    }

    if(j == k && k == l && l == m && m == n) {
        isValid = true;
        return isValid;
    }

    if(k == l && l == m && m == n && n == o) {
        isValid = true;
        return isValid;
    }
    return isValid;
}

static boolean isEquals6Digits(int i, int j, int k, int l, int m, int n, int o) {
    boolean isValid = false;
    if(i == j && j == k && k == l && l == m && m == n) {
        isValid = true;
        return isValid;
    }

    if(j == k && k == l && l == m && m == n && n == o) {
        isValid = true;
        return isValid;
    }
    return isValid;
}

static boolean isEquals7Digits(int i, int j, int k, int l, int m, int n, int o) {
    boolean isValid = false;
    if(i == j && j == k && k == l && l == m && m == n && n == o) {
        isValid = true;
        return isValid;
    }
    return isValid;
    }
}

 

Végeredmény:

A szűrt mobilszámok külön állományokban:

 

www.informatika-programozas.hu - Letöltés - List4

List4

 

www.informatika-programozas.hu - Letöltés - List5

List5

 

www.informatika-programozas.hu - Letöltés - List6

List6

 

www.informatika-programozas.hu - Letöltés - List7

List7