Informatika érettségi 2007. Május
Kész felüdülés az eddig megoldott feladatokhoz képest. Itt egy algoritmusra bukkan fel újra és újra a feladatokban. Cserébe viszont nem kell összetett és többszörösen összetett adattípus beolvasással és kiírással bajlódni.
A feladatkiírás
Napjainkban a kommunikáció egy elterjedt formája az SMS-küldés. Az SMS-küldésre alkalmas telefonok prediktív szövegbevitellel segítik az üzenetek megírását. Ennek használatakor a szavakat úgy tudjuk beírni, hogy a telefon számbillentyűjén található betűknek megfelelő számokat kell beírnunk. A számok és betűk megfeleltetését az alábbi táblázat mutatja:
Ha meg szeretnénk jeleníteni az ablak szót, akkor a 22525 kódot kell beírnunk. A telefon a tárolt szótára alapján a kódhoz kikeresi a megfelelő szót. Ha több szóhoz is azonos kód tartozik, akkor a kódhoz tartozó összes szót felkínálja választásra. egy ilyen szógyűjteményt talál a szavak.txt fájlban. A fájlról a következőket tudjuk:
- Legfeljebb 600 szó található benne.
- Minden szó külön sorban található.
- A szavak hossza maximum 15 karakter.
- A szavak mindegyike csak az angol ábécé kisbetűit tartalmazza.
- Minden szó legfeljebb egyszer szerepel
Írjon sms néven programot, ami a szógyűjtemény felhasználásával megoldja az alábbi feladatokat!
- Kérjen be a felhasználótól egy betűt, és adja meg, hogy milyen kód (szám) tartozik hozzá! Az eredményt írassa a képernyőre!
- Kérjen be a felhasználótól egy szót, és határozza meg, hogy milyen számsorral lehet ezt a telefonba bevinni! Az eredményt írassa a képernyőre!
- Olvassa be a szavak.txt fájlból a szavakat, és a továbbiakban azokkal dolgozzon! Ha nem tudja az állományból beolvasni az adatokat, akkor az állományban található „b” kezdőbetűs szavakat gépelje be a programba, és azokkal oldja meg a feladatokat!
- Határozza meg és írassa a képernyőre, hogy melyik a leghosszabb tárolt szó! Amennyiben több azonos hosszúságú van, elegendő csak az egyiket megjeleníteni. Adja meg ennek a szónak a hosszát is!
- Határozza meg és írassa a képernyőre, hogy hány rövid szó található a fájlban! Rövid szónak tekintjük a legfeljebb 5 karakterből álló szavakat.
- Írassa a kodok.txt állományba a szavak.txt fájlban található szavaknak megfelelő számkódokat! Minden szónak feleljen meg egy számkód, és minden számkód külön sorba kerüljön!
- Kérjen be a felhasználótól egy számsort, és határozza meg, hogy melyik szó tartozhat hozzá! Amennyiben több szó is megfelelő, akkor mindegyiket írassa ki! (Teszteléshez használhatja például a 225 számsort, mivel ehhez egynél több szó tartozik a szógyűjteményben.)
- Határozza meg, hogy a szógyűjteményben mely kódokhoz tartozik több szó is! Írassa ki a képernyőre ezeket a szavakat a kódjukkal együtt egymás mellé az alábbi mintának megfelelően (a szavak sorrendje ettől eltérhet):
baj : 225; bal : 225; arc : 272; apa : 272; eb : 32; fa : 32; dal : 325;
fal : 325; eltesz : 358379; elvesz : 358379; fojt : 3658; folt : 3658; ...
- Határozza meg, hogy melyik kódnak megfelelő szóból van a legtöbb! Írassa ki a képernyőre a kódot, és a kódhoz tartozó összes tárolt szót! Ha több kódhoz is azonos számú szó tartozik, akkor elegendő ezen kódok közül csak az egyikkel foglalkozni.
A megoldás
Az egész érettségi lényege, hogy egy olyan algoritmust alkossunk, ami szöveget SMS-ként beírható billentyű lenyomásokká alakít (bőven okostelefon előtti korszak). Ehhez alkotnunk kell egy kódolót, ami szöveget számsorrá alakít. Mint minden programozási feladatot, ezt is többféleképpen meg lehet oldani.
A legfavágóbb módszer az lenne, ha egy monumentális if-else fát alkotnánk. Ennél egy fokkal szofisztikáltabb lenne, ha switch-case utasítással alkotnánk fát. Viszont mindkét módszer hátránya, hogy nehezen bővíthetőek és átláthatatlanok egy bizonyos kombináció szám felett. Ezért a tényleges megoldásunk egy összerendelési táblázatos megoldást alkalmaz. Ennek lényege, hogy minden bemeneti betűhöz letároljuk, hogy milyen kimeneti szám tartozik és ez alapján keressük ki a megfelelő kimenetet.
Az algoritmust egy külön osztályban megvalósított statikus metódusként implementáltuk.
public static class Kodolo
{
private const string _betuk = "abcdefghijklmnopqrstuvwxyz";
private const string _szamok = "22233344455566677778889999";
public static string Kodol(string betuk)
{
var kisbetus = betuk.ToLower();
var eredmeny = new StringBuilder();
foreach(var betu in kisbetus)
{
int index = _betuk.IndexOf(betu);
if (index < 0)
{
//A bemeneti szöveg nem jó
throw new InvalidOperationException();
}
eredmeny.Append(_szamok[index]);
}
return eredmeny.ToString();
}
}
- Kérjen be a felhasználótól egy betűt, és adja meg, hogy milyen kód (szám) tartozik hozzá! Az eredményt írassa a képernyőre!
Az első feladat lényegében az algoritmus leimplementálása és tesztelése. Mivel mi az algoritmust egy külön egységként implementáltuk, ezért az első feladat lényegében ezt hívja meg.
public void Feladat01()
{
Console.WriteLine("Kérek egy betűt: ");
char betu = Console.ReadLine()[0];
Console.WriteLine("Hozzá tartozó szám: {0}", Kodolo.Kodol(betu.ToString()));
}
- Kérjen be a felhasználótól egy szót, és határozza meg, hogy milyen számsorral lehet ezt a telefonba bevinni! Az eredményt írassa a képernyőre!
A második feladat sem sokkal bonyolultabb. Itt egyetlen egy karakter helyett a teljes szöveget kell átadni feldolgozásra. Lényegében ugyanaz, mint az első feladat.
public void Feladat02()
{
Console.WriteLine("Kérek egy szöveget: ");
string bemenet = Console.ReadLine();
Console.WriteLine("Telefonba kódsor: {0}", Kodolo.Kodol(bemenet));
}
- Olvassa be a szavak.txt fájlból a szavakat, és a továbbiakban azokkal dolgozzon! Ha nem tudja az állományból beolvasni az adatokat, akkor az állományban található „b” kezdőbetűs szavakat gépelje be a programba, és azokkal oldja meg a feladatokat!
Az eddig megoldott érettségikhez képest egy üde színfolt a csak magában álló fájlbeolvasás, ami nem tartalmaz extra logikát, csupán a sorokat kell beolvasnunk szavaknak. A szavakat a megoldás osztályunkban található List<string> típusú _szavak változó tárolja.
public void Feladat03()
{
using (var file = File.OpenText("szavak.txt"))
{
string? sor = null;
do
{
sor = file.ReadLine();
if (!string.IsNullOrEmpty(sor))
{
_szavak.Add(sor);
}
}
while (sor != null);
}
}
- Határozza meg és írassa a képernyőre, hogy melyik a leghosszabb tárolt szó! Amennyiben több azonos hosszúságú van, elegendő csak az egyiket megjeleníteni. Adja meg ennek a szónak a hosszát is!
Egy jó kis maximum keresés a szavak között szóhossz alapján. A csavar annyi, hogy nem csak a szó hossza kell, hanem a tényleges szó is. Ezért nem a LINQ Max() metódusát kell alkalmazni, hanem csökkenő sorrendbe rendezve hossz alapján az elsőt kivéve megkapjuk a leghosszabb szót, aminek lekérdezhető a hossza is.
public void Feladat04()
{
var leghosszabb = _szavak.OrderByDescending(sz => sz.Length).FirstOrDefault();
Console.WriteLine("Leghosszabb tárolt szó: {0}", leghosszabb);
Console.WriteLine("Leghosszabb tárolt szó hossza: {0}", leghosszabb.Length);
}
- Határozza meg és írassa a képernyőre, hogy hány rövid szó található a fájlban! Rövid szónak tekintjük a legfeljebb 5 karakterből álló szavakat.
Egy megszámlálásos feladat, ahol a legfeljebb 5 karakterből álló szavakat kell számolnunk. LINQ Count() metódusával pofonegyszerűen megoldható feladat.
public void Feladat05()
{
int rovidszavak = _szavak.Count(sz => sz.Length <= 5);
Console.WriteLine("{0} db rövid szó van", rovidszavak);
}
- Írassa a kodok.txt állományba a szavak.txt fájlban található szavaknak megfelelő számkódokat! Minden szónak feleljen meg egy számkód, és minden számkód külön sorba kerüljön!
Egy egyszerű fájlba írás, annyi csavarral, hogy a szavakhoz tárolt kódolt számsort kell kiírnunk. Ezért kiírás közben meg kell hívnunk a kódoló metódusunkat és az eredményét kiírni.
public void Feladat06()
{
using (var file = File.CreateText("kodok.txt"))
{
foreach (var szo in _szavak)
{
file.WriteLine(Kodolo.Kodol(szo));
}
}
}
- Kérjen be a felhasználótól egy számsort, és határozza meg, hogy melyik szó tartozhat hozzá! Amennyiben több szó is megfelelő, akkor mindegyiket írassa ki! (Teszteléshez használhatja például a 225 számsort, mivel ehhez egynél több szó tartozik a szógyűjteményben.)
Egy visszafelé keresés a szavak között. Leegyszerűsítve ezen algoritmus alapján működnek az autocorrect billentyűzetek a telefonokon, amik javaslatokat tesznek a szavakra. Lényegében a beírt számsornak megfelelő kódolt szavakat kell kiválasztanunk és magát a szavakat visszaadni.
public void Feladat07()
{
Console.WriteLine("Kérek egy számsort: ");
string szamsor = Console.ReadLine();
var illoszavak = _szavak.Where(sz => Kodolo.Kodol(sz) == szamsor);
Console.WriteLine("Talált szavak:");
foreach (var szo in illoszavak)
{
Console.WriteLine(szo);
}
}
- Határozza meg, hogy a szógyűjteményben mely kódokhoz tartozik több szó is! Írassa ki a képernyőre ezeket a szavakat a kódjukkal együtt egymás mellé az alábbi mintának megfelelően (a szavak sorrendje ettől eltérhet):
baj : 225; bal : 225; arc : 272; apa : 272; eb : 32; fa : 32; dal : 325;
fal : 325; eltesz : 358379; elvesz : 358379; fojt : 3658; folt : 3658; ...
Szintén a kódoló algoritmus segítségével megoldandó feladat. A kódolt forma alapján csoportokba kell rendezni a szavakat LINQ segítségével, majd kiválogatni azokat a csoportokat, ahol a csoport elemeinek száma nagyobb, mint egy. Ezután már csak formázottan ki kell írni a szavakat és a csoporthoz tartozó kulcsokat.
public void Feladat08()
{
var azonosak = _szavak.GroupBy(sz => Kodolo.Kodol(sz)).Where(g => g.Count() > 1);
foreach (var kodcsoport in azonosak)
{
foreach (var szo in kodcsoport)
{
Console.Write("{0} : {1}; ", szo, kodcsoport.Key);
}
}
}
- Határozza meg, hogy melyik kódnak megfelelő szóból van a legtöbb! Írassa ki a képernyőre a kódot, és a kódhoz tartozó összes tárolt szót! Ha több kódhoz is azonos számú szó tartozik, akkor elegendő ezen kódok közül csak az egyikkel foglalkozni.
A megoldás hasonló az előző feladathoz. Szintén csoportosítunk a kódolt forma szerint, majd csökkenő sorba rendezzük a csoportokat az elemszám alapján és kiválasztjuk az elsőt LINQ segítségével. Ezután már csak a kiválasztott csoport kulcsát és a szépen formázott szavakat ki kell írni.
public void Feladat09()
{
var legtobbszoegykodhoz = _szavak
.GroupBy(sz => Kodolo.Kodol(sz))
.OrderByDescending(g => g.Count())
.FirstOrDefault();
Console.WriteLine("Legtöbb szóval rendelkező kód: {0}", legtobbszoegykodhoz.Key);
string szavak = string.Join(' ', legtobbszoegykodhoz);
Console.WriteLine(szavak);
}
