• Nem Talált Eredményt

fejezet - Listákkal kapcsolatos feladatok (szerző: Hernyák Zoltán)

Hernyák zoltán)

16. fejezet - Listákkal kapcsolatos feladatok (szerző: Hernyák Zoltán)

A feladatok alapszintű listafeldolgozással megoldhatóak. Ennek során kell egy vagy több lista, melynek feltöltése nem feltétlenül fontos része a feladatoknak. A megoldások során a kiinduló adatokat tartalmazó listákat általában nem kell módosítani, új listákat kell előállítani.

16.1. feladat (Maximum – szint: 2). Olvassuk be egy lista tartalmát billentyűzetről valamely, az előző feladatban megadott módszer szerint! Kérjünk be egy újabb értéket (A), mely érték a program kezelője „szerint” a listabeli számok maximuma! A program ellenőrizze, hogy ez valóban a maximum-e!

Magyarázat: Óvatosan lássunk az ellenőrzésnek: nem elég, hogy a listában nem találunk az A értéknél nagyobb számot, az A értéknek szerepelnie kell a listabeli számok között is! Persze nekiláthatunk a megoldásnak oly módon is, hogy meghatározzuk a lista kalkulált maximumát, és összevetjük az A értékkel – de az kevésbé izgalmas (lásd 16.1. forráskód).

16.2. feladat (Páros számok maximuma – szint: 3). Olvassuk be egy lista tartalmát billentyűzetről valamely, az előző feladatban megadott módszer szerint! A program adja meg a listában szereplő páros számok közül a legnagyobb számértéket (ügyeljünk arra az esetre, mikor a listában minden szám páratlan)!

Magyarázat: A maximumkeresés egyszerű feladat, ha tudjuk a megfelelő kezdőértéket. A kezdőértéknek a lista első elemét szoktuk választani, mely választás egyúttal akár a végeredmény, a maximum is lehet. De ez esetben nem tehetjük, mivel nem lehetünk biztosak abban, hogy az első elem páros-e. Azt sem tudhatjuk, hogy a második páros-e. Lehet, hogy egyik sem páros, és nem találunk kezdőértéket.

Meg kellene keresnünk az első páros számot, kiválasztani mint kezdőértéket, majd folytatni a keresést. Ez igazából két ciklust igényel, megoldása a 16.2. forráskódban látható. Kissé erőforrás-pazarlóbb, de algoritmikusan jóval áttekinthetőbb megoldás, ha a lista páros elemeit átmásoljuk egy második listába. A továbbiakban ezen lista elemszáma alapján azonnal megállapítható, hogy van-e egyáltalán páros szám, illetve könnyű megkeresni a maximumot (lásd a 16.3. forráskódot).

16.3. feladat (Unió, metszet – szint: 2). A 15.7. feladatban ismertetett módon olvassunk be egyetlen fájlból két számlistát (A és B)! Fogjuk fel az egyes számlistákat mint egy-egy számhalmazt! Generáljuk le az , számhalmazokat, és írjuk ki az értékeket a képernyőre! Ügyeljünk arra, hogy az unió és metszet listákban ne szerepeljen egyetlen szám sem kétszer!

Magyarázat: Ez az egyszerű alapalgoritmusok használatát jelenti, speciálisan listára kialakítva. Hogy kissé érdekesebb legyen a megoldás, írjuk át olyan függvényekre, melyek a két listát paraméterként megkapva a generált listát adják meg visszatérési értékként! Mindkét részfeladat igényli a listabeli számok egyediségét, így érdemes a 15.11. forráskódban már bemutatott egyediség-ellenőrző függvényt alkalmazni.

Az unio művelet képzése nagyon egyszerű: mindkét listából szükséges minden elemet befogadni, ami még nem szerepelt. A megoldást lásd a 16.4. forráskódban. A metszet kicsit bonyolultabb ellenőrzési mechanizmusú:

olyan elemeket keresünk, amelyek szerepelnek az A és B listában, de nem szerepelnek még a metszetben (16.5.

forráskód).

16.4. feladat (Erdei ösvény – szint: 3). Egy erdei ösvényen vizes pocsolyák és száraz szakaszok váltják egymást. Szimbolizálja a szárazföldet a numerikus 1, a vizes részt a 2 érték!

Töltsünk fel egy listát véletlenszerű 1 és 2 értékekkel oly módon, hogy nagyobb valószínűséggel kerüljön bele víz, mint szárazföld (például 70%-30% arányban)! Legyen a lista első és utolsó eleme garantáltan 1, vagyis szárazföld! A kész listát jelenítsük meg a képernyőn oly módon, hogy a szárazföldet a # (hashmark), a vizet a _ (aláhúzás) karakterrel jelöljük! A konkrét arányokat a program kérje be billentyűzetről!

Az erdei ösvény egyik végén áll Piroska, és szeretne átjutni az ösvény másik végére a nagymamához. Piroska n hosszú pocsolyás szakaszt képes átugorni (n értékét kérjük be

billentyűzetről). A program generálja le a listát adott arányokkal, jelenítse meg a képernyőn, majd adja meg, hogy Piroska át tud-e kelni az ösvényen száraz lábbal (16.1. ábra)!

Magyarázat: A feltöltést adott valószínűséggel a geometriai valószínűségek szerinti módszerrel oldhatjuk meg.

Sorsoljunk véletlen számot intervallumban! Ha az kisebb, mint 30egyenlő, akkor víz. A megjelenítést is egyszerű megoldani a korábbi feladatok alapján.

16.1. ábra. Piroska és az ösvény

Piroska átkelési problémája során érdemes bevezetni egy számlálót, melyben a szomszédos víz elemek számát számoljuk. Ha a lista következő eleme víz – növeljük a számlálót. Ha szárazföld, akkor lenullázzuk. Ekképpen már csak a számláló maximális értékét kell meghatároznunk (a 16.6. forráskód).

16.5. feladat (Szigetek – szint: 3). Tegyük fel, hogy Amerika partjaitól elindul egy repülő Európa partjai felé! A repülő egyenes vonalban egyenletes sebességgel repül végig adott magasságban. A repülés során a felszín magasságát méri, melyet rögzít. A számértékek méterben értendők, és egy listába kerülnek be. A víz felszínén mért magasságérték mindig 0, és negatív magasságot nem lehet mérni. A pozitív értékek a víz fölé kiemelkedő szárazföldet mutatnak. A lista első és utolsó értéke értelemszerűen pozitív szám (Amerika partvidékéről indulunk, és Európa partvidékének elérésekor áll le a mérés). A két pont között vízfelszíni és szárazföldi szakaszok váltják egymást.

A program töltse fel a listát véletlen értékekkel, de a feladat szövegében foglaltaknak megfelelően! Vagyis ne egyszerű nulla és nem nulla értékek váltsák egymást véletlenszerűen, hanem ha vízfelszíni szakasz kezdődik, akkor az folyamatos legyen, valamint a szárazföldi szakasz is felismerhető legyen! A szárazföldi szakaszok mindig egy-egy szigetet képviselnek (16.2. ábra).

A program határozza meg egy feltöltött lista alapján:

• hány sziget található Amerika és Európa között,

• hanyadik sorszámú szigeten található a legmagasabb pont (hegycsúcs),

• milyen hosszú a leghosszabb sziget (egységekben)!

Magyarázat: Ügyeljünk a szélsőséges esetekre: elképzelhető, hogy Amerika és Európa között nincs vizes szakasz (egybefüggő szárazföldet alkot). Másik eset: nincs sziget, a két pont között egybefüggő vizes szakasz terül el. A legmagasabb hegycsúcs esetén elképzelhető, hogy ezen maximális magasság ugyanazon szigeten belül többször vagy több szigeten is előfordulhat. Szintén ügyeljünk arra, hogy a legmagasabb pont ne Európa vagy Amerika partvidékéhez tartozzon, hanem valamely szigeten forduljon elő!

16.2. ábra. A repülőgép útvonala

A lista feltöltése úgy történhet, hogy kisorsoljuk, hogy víz vagy szárazföld következzen, majd a szakasz hosszát.

Ezek után megfelelő mennyiségű 0-t vagy nem 0-t helyezünk el a listában. Ügyeljünk rá, hogy a lista első és utolsó eleme ne 0 legyen! A program maradék részét úgy kell megírnunk, hogy ne függjön a feltöltési mechanizmusunktól (ne építsen semmilyen ott szerzett tudásra)!

Ezek után a piroskás feladatban ismertetett módon meg kell számolni a 0 szakaszok hosszát. Valahányszor 0-ról nem 0-ra váltunk, sziget kezdődik (kivéve az utolsó ilyet, ahol Európa kezdődik). Ügyeljünk rá, hogy ha nem volt, csak 1 ilyen váltás, akkor nincs sziget a két kontinens között! Ha 0 ilyen váltás volt, akkor összefüggő szárazföld van.

A leghosszabb sziget meghatározásához a Piroska leghosszabb vizes szakaszának meghatározásánál leírtakból kell kiindulni. A maximális pont keresése sem problémás, mivel tudjuk, hogy egyik pont sem alacsonyabb 0 méternél, így a maximumkeresés kiinduló értéke lehet a 0. Mivel meg kell számolnunk, hány sziget van, nem nehéz a maximum megtalálásakor feljegyezni a sziget sorszámát is.

1. A fejezet forráskódjai

16.1. forráskód. A lista maximumának ellenőrzése

// List<int> L = new List<int>();

bool nagyobb_volt = false;

bool szerepelt = false;

foreach (int x in L) {

if (x == A) szerepelt = true;

if (x > A) nagyobb_volt = true;

}

if (nagyobb_volt == false && szerepelt == true) Console.WriteLine("eltalalta a maximumot");

else

Console.WriteLine("nem talalta el");

16.2. forráskód. A legnagyobb páros szám keresése

// List<int> L = new List<int>();

int i = 0;

while (i < L.Count && L[i] % 2 != 0) i++;

if (i < L.Count) {

int max = L[i];

for (int j = i + 1; j < L.Count; j++) if (L[j] % 2 == 0 && L[j] > max) max = L[j];

Console.WriteLine("A paros max={0}", max);

}

else Console.WriteLine("Nincs paros eleme a listanak");

16.3. forráskód. Egyszerűbb algoritmus, több memórialekötés

// List<int> L = new List<int>();

List<int> lp = new List<int>();

foreach (int x in L)

if (x % 2 == 0) lp.Add(x);

if (lp.Count == 0)

Console.WriteLine("Nincs paros eleme");

else {

int max = lp[0];

foreach (int x in lp) if (x > max) max = x;

Console.WriteLine("Paros max = {0}", max);

}

16.4. forráskód. Az unió függvénye

static List<int> unio(List<int> A, List<int> B) {

List<int> ret = new List<int>();

foreach (int x in A)

if (szerepel_e(ret, x) == false) ret.Add(x);

foreach (int x in B)

if (szerepel_e(ret, x) == false) ret.Add(x);

return ret;

}

16.5. forráskód. A metszet függvénye

static List<int> metszet(List<int> A, List<int> B) {

List<int> ret = new List<int>();

foreach (int x in A)

if (szerepel_e(ret, x) == false && szerepel_e(B,x)==true) ret.Add(x);

return ret;

}

16.6. forráskód. A leghosszabb vizes szakasz hossza

static int leghosszabb(List<int> L) {

int db = 0;

int max = 0;

foreach (int x in L) {

if (x == 2) db++;

else db = 0;

if (db > max) max = db;

}

return max;

}