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.
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:
-
0123456,
-
1234567,
-
7654321,
-
6543210,
-
1234321,
-
4321234.
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:
-
2323232 és ehhez hasonlók,
-
1233321 és ehhez hasonlók,
-
1117111 és ehhez hasonlók,
-
0011223 és ehhez hasonlók,
-
0001112 és ehhez hasonlók.
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.
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:
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:
List4
List5
List6
List7