9. Visszavezetés egyedi felsorolókkal



Hasonló dokumentumok
8. Programozási tételek felsoroló típusokra

OAF Gregorics Tibor: Minta dokumentáció a 4. házi feladathoz 1. Feladat. Megoldás

Bevezetés a programozásba. 3. Előadás Algoritmusok, tételek

KOMBINATORIKA ELŐADÁS osztatlan matematika tanár hallgatók számára. Szita formula

1. Számoljuk meg egy számokat tartalmazó mátrixban a nulla elemeket!

Bevezetés a programozásba I.

d(f(x), f(y)) q d(x, y), ahol 0 q < 1.

Programozás(A szakirány) II. beadandó feladat Farkas András HP6S15 1. csoport Veszprémi Anna / Hudoba Péter

Statisztikai próbák. Ugyanazon problémára sokszor megvan mindkét eljárás.

Fuzzy rendszerek. A fuzzy halmaz és a fuzzy logika

VISSZAVEZETÉSES FELADATOK

Bánsághi Anna 2014 Bánsághi Anna 1 of 68

Adatszerkezetek. Nevezetes algoritmusok (Keresések, rendezések)

Programozás Minta programterv a 2. házi feladathoz 1.

OEP Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1. Feladat. Elemzés 1

Programozási tételek. Dr. Iványi Péter

Békefi Zoltán. Közlekedési létesítmények élettartamra vonatkozó hatékonyság vizsgálati módszereinek fejlesztése. PhD Disszertáció

ELEMI PROGRAMOZÁSI TÉTELEK

Alkalmazott modul: Programozás. Programozási tételek, rendezések. Programozási tételek Algoritmusok és programozási tételek

Bevezetés az informatikába

Programozás I. Egyszerű programozási tételek. Sergyán Szabolcs

Egyszerű programozási tételek

ALGORITMUSOK, ALGORITMUS-LEÍRÓ ESZKÖZÖK

Bevezetés a programozásba I 3. gyakorlat. PLanG: Programozási tételek. Programozási tételek Algoritmusok

Algoritmusok és adatszerkezetek I. 10. előadás

Méréselmélet: 5. előadás,

4 2 lapultsági együttható =

Hipotézis vizsgálatok. Egy példa. Hipotézisek. A megfigyelt változó eloszlása Kérdés: Hatásos a lázcsillapító gyógyszer?

Adatbázis és szoftverfejlesztés elmélet. Programozási tételek

Egy negyedrendű rekurzív sorozatcsaládról

Az entrópia statisztikus értelmezése

1.Tartalomjegyzék 1. 1.Tartalomjegyzék

Összetett programozási tételek

Felvételi tematika INFORMATIKA

Programozás I. Egyszerű programozási tételek. Sergyán Szabolcs

A bankközi jutalék (MIF) elő- és utóélete a bankkártyapiacon. A bankközi jutalék létező és nem létező versenyhatásai a Visa és a Mastercard ügyek

METROLÓGIA ÉS HIBASZÁMíTÁS

Tanult nem paraméteres próbák, és hogy milyen probléma megoldására szolgálnak.

Algoritmizálás, adatmodellezés tanítása 1. előadás

Egyszerű algoritmusok

s n s x A m és az átlag Standard hiba A m becslése Információ tartalom Átlag Konfidencia intervallum Pont becslés Intervallum becslés

VARIANCIAANALÍZIS (szóráselemzés, ANOVA)

Algoritmusok és adatszerkezetek gyakorlat 09 Rendezések

Alkalmazott modul: Programozás. Programozási tételek, rendezések Giachetta Roberto

A mágneses tér energiája, állandó mágnesek, erőhatások, veszteségek

1. beadandó feladat: Programozási tételek alkalmazása. Közös követelmények:

HORVÁTH ZSÓFIA 1. Beadandó feladat (HOZSAAI.ELTE) ápr 7. 8-as csoport

9. előadás. Programozás-elmélet. Programozási tételek Elemi prog. Sorozatszámítás Eldöntés Kiválasztás Lin. keresés Megszámolás Maximum.

Algoritmizálás és adatmodellezés tanítása 3. előadás

Rendezések. A rendezési probléma: Bemenet: Kimenet: n számot tartalmazó (a 1,a 2,,a n ) sorozat

II. Mérés SZÉCHENYI ISTVÁN EGYETEM GYŐR TÁVKÖZLÉSI TANSZÉK

Párhuzamos algoritmusok

Az elektromos kölcsönhatás

Philosophiae Doctores. A sorozatban megjelent kötetek listája a kötet végén található

Alkalmazott modul: Programozás

Feladat. Bemenő adatok. Bemenő adatfájlok elvárt formája. Berezvai Dániel 1. beadandó/4. feladat április 13. Például (bemenet/pelda.

Objektum Orientált Programozás VII.

A 2017/2018 tanévi Országos Középiskolai Tanulmányi Verseny első fordulójának feladatai. INFORMATIKA II. (programozás) kategória

7. Laboratóriumi gyakorlat: Vezérlési szerkezetek II.

XI. ERDÉLYI TUDOMÁNYOS DIÁKKÖRI KONFERENCIA

Másolásra épülő algoritmusok

Struktúra nélküli adatszerkezetek

Programozási segédlet

Dr. Ratkó István. Matematikai módszerek orvosi alkalmazásai Magyar Tudomány Napja. Gábor Dénes Főiskola

Amortizációs költségelemzés

Programozási Módszertan definíciók, stb.

/11 Változtatások joga fenntartva. Kezelési útmutató. UltraGas kondenzációs gázkazán. Az energia megőrzése környezetünk védelme

Algoritmusok, adatszerkezetek I.

Periodikus figyelésű készletezési modell megoldása általános feltételek mellett

32. A Knuth-Morris-Pratt algoritmus

The original laser distance meter. The original laser distance meter

Elosztott rendszerek játékelméleti elemzése: tervezés és öszönzés. Toka László

Bevezetés a programozásba I 4. gyakorlat. PLanG: Szekvenciális fájlkezelés. Szekvenciális fájlkezelés Fájlok használata

Szövegfeldolgozás II.

Bevezetés a programozásba. 5. Előadás: Tömbök

Bevezetés a programozásba. 4. Előadás Sorozatok, fájlok

Megjegyzés: A programnak tartalmaznia kell legalább egy felhasználói alprogramot. Példa:

C. A. R. Hoare E. W. Dijkstra Fóthi Ákos

Bevezetés a programozásba I.

Térinformatikai algoritmusok Elemi algoritmusok

Algoritmizálás, adatmodellezés tanítása 2. előadás

Dinamikus programozás

Orosz Gyula: Markov-láncok. 4. Statisztikus golyójátékok

ORVOSI STATISZTIKA. Az orvosi statisztika helye. Egyéb példák. Példa: test hőmérséklet. Lehet kérdés? Statisztika. Élettan Anatómia Kémia. Kérdések!

Szerelési útmutató FKC-1 síkkollektor tetőre történő felszerelése Junkers szolár rendszerek számára

M. 33. Határozza meg az összes olyan kétjegyű szám összegét, amelyek 4-gyel osztva maradékul 3-at adnak!

Műszaki folyamatok közgazdasági elemzése. Kevert stratégiák és evolúciós játékok

Hatékonyság 1. előadás

A korlátozás programozás alapjai

Gyakorló feladatok az 1. nagy zárthelyire

Algoritmizálás és adatmodellezés 2. előadás

INFORMATIKA javítókulcs 2016

Térinformatikai algoritmusok Elemi algoritmusok

Leica DISTOTMD510. X310 The original laser distance meter. The original laser distance meter

Bevezetés a programozásba I 4. gyakorlat. PLanG: Szekvenciális fájlkezelés

Brósch Zoltán (Debreceni Egyetem Kossuth Lajos Gyakorló Gimnáziuma) Számelmélet I.

2. személyes konzultáció. Széchenyi István Egyetem

1. Feladat: beolvas két számot úgy, hogy a-ba kerüljön a nagyobb

Darupályák ellenőrző mérése

Bevezetés a kémiai termodinamikába

Átírás:

9. Vsszavezetés egyed felsorolókkal Ebben a fejezetben a hét általános programozás tételt olyan feladatok megoldására alkalmazzuk, ahol nem lehet nevezetes felsorolókat sználn, azaz a Frst(), Next(), End() és Current() műveletek előállítása egyed tervezést gényel. A 9.1. alfejezetben olyan példát mutatunk, ahol a feladat megoldásához egy teljesen egyed felsorolót vezetünk be, amelynek semm köze a korábban mutatott nevezetes felsorolókhoz, hszen ebben a feladatban nem szerepel nevezetes gyűjtemény. Gyakorak azonban az olyan feladatok s, ahol ugyan nevezetes gyűjteményt dolgozunk fel, de nem a megszokott módon, ezért egyáltalán nem, vagy csak módosítva sználtjuk a nevezetes felsorolókat. Ilyen az, amkor egy nevezetes gyűjteményt nem a megszokott módon kell bejárn (például egy vektor elemet nem egyesével kell feldolgozn, ezért a Next() műveleten változtatn kell; vagy például nem elejétől a vége felé kell bejárn és ehhez a Frst(), Next(), és End() műveleteket kell újra gondoln). Ide értjük a nevezetes gyűjtemények úgynevezett feltétel fennálláság tartó feldolgozását (9.2. alfejezet) s, amkor az elemeket csak addg kell bejárn, amíg egy adott feltétel teljesül. Ehhez az End() művelet megfelelő felülírására van szükség. Igazán zgalmasak azok a feladatok (9.3. alfejezet), melyek megoldásához szükség van egy nevezetes gyűjtemény bejárására, de a bejárt elemek helyett azok csoportjanak feldolgozására van szükség. Ezért olyan egyed felsorolót kell készítenünk, amely egy-egy lyen csoportot tud a feldolgozás számára bztosítan. Egyed felsorolóra van szükség akkor s, egydejűleg több gyűjtemény elemet kell szmultán módon bejárn (9.4. alfejezet). 9.1. Felsoroló gyűjtemény nélkül 9.1. Példa. Határozzuk meg egy n poztív egész szám prímosztónak az összegét! A feladat megfogalmaztó egy feltételes összegzésként, amely során az n 1-től különböző osztót tartalmazó [2..n] ntervallum azon elemet kell összeadnunk, amelyek osztják az n-t és prím számok. A = (n:n, sum:n) Ef = ( n=n' n>0 ) Uf = ( Ef sum = n ) 2 n' prm( ) A feladat közönséges összegzésként s megfogalmaztó, bevezetjük azt a felsorolót, amely közvetlenül az n szám prím osztót sorolja fel, és a feladatot ennek megfelelően újraspecfkáljuk. A = (t:enor(n), sum:n) Ef = ( t=t') t ' Uf = ( sum = t ' ) 1 Ezt vsszavezethetjük az általános összegzésre úgy, hogy abban az E=H=N és mnden e természetes számra f(e)= e. 132

9.3. Csoportok felsorolása sum := 0 t.frst() t.end() sum := sum + t.current() Az n szám prímosztó közül az elsőhöz, mondjuk a legksebbhez, úgy juttunk hozzá, hogy amennyben n legalább 2, akkor egyesével elndul 2-től és az n az első (legksebb) osztóját megkeressük. Ez bztosan prím. (Ez a tevékenység egy kválasztás.) A soron következő prímosztó kereséséhez a korábban megtalált prímosztót ezt tehát meg kell jegyezn k kell valahogy venn az n számból. Ha elosztjuk vele az n-t ahányszor csak tudjuk (hszen egy prímosztó többszörösen s részt vehet az n szám prímtényezős felbontásában), akkor a hányadosnak (az n új értékének) összes prímosztója az eredet n számnak s prímosztó lesznek, és ezek éppen azok, amelyeket eddg még nem soroltunk fel. A felsorolás addg tart, amíg az egyre csökkenő n nem lesz 1. Ez véges lépésben bztosan be fog következn. Látszk, hogy az mplct módon az összes prímosztóját tartalmazó n szám helyett bevezetett t felsorolót egyfelől a folyamatosan csökkenő n, másfelől annak legutoljára talált prímosztója (d) reprezentálja. A Frst() művelet az eredet n legksebb prímosztóját keres meg, n>1, és elhelyez a d változóban (lkpo). A Next() művelet elosztja az n-t a d-vel ahányszor csak tudja, majd így még mndg n>1, akkor megkeres az n legksebb prímosztóját, és elhelyez a d változóban. A Current() művelet a kszámolt d értékét adja vssza. Az End() n=1 esetén ad gazat. t ~ n, d t.frst() ~ d:=lkpo(n) ~ LOOP(d n; n:=n/d); d:=lkpo(n) t.end() ~ n=1 t.current( ~ d A d:=lkpo(n) részfeladatot az IF(n>1, d : select ( d n) ) program oldja meg. Itt alkalmaztjuk a kválasztás korább, egész számegyenesre megfogalmazott változatát éppúgy, mnt a kválasztás általános programozás tételét, amelyben a :EL feltétel most a (d)= d n lesz. A felsoroló az egész számokat járja be 2-től ndítva, és leállásakor a felsorolást végző ndex megegyezk a kválasztás eredményével. sum:=0; d:=lkpo(n) d2 d:=lkpo(n) n>1 n>1 sum := sum + d d:=2 SKIP d n n:=n/d d:=lkpo(n) d n d:=d+1 133

9. Vsszavezetés egyed felsorolókkal 9.2. Feltétel fennálláság tartó felsorolás Sokszor találkozunk olyan feladatokkal, ahol a feldolgozást addg kell végezn, amíg egy bzonyos feltétel ((t,)) fennáll. Természetesen lyenkor fel kell tennünk, hogy a t felsorolása során véges lépés múlva ez a feltétel ms lesz. Ehhez sonló feltétel fennálláság tartó feldolgozásokkal gyűjtemények esetében s találkoztunk. Itt legtöbbször a feltétel két részből áll: egyrészt abból, hogy még nem értünk a gyűjtemény bejárásának végére, másrészt a termnálást már előbb s kváltó extra krtérumból. E kettő konjunkcója (logka és kapcsolata) véges lépésen belül bztos ms lesz, hszen legrosszabb esetben az összes elem bejárása után leáll a feldolgozás. Példa erre az, amkor össze kell adnunk egy egész elemű vektor első nem-poztív számát megelőző értéket, azaz csak az első néhány poztív számot. Hasonló példa, amkor egy bank ügyfelenek tranzakcó között, amelyeket ügyfélazonosító szernt sorba rendeztünk és egy szekvencáls nputfájlba helyeztük el, az első ügyfél legnagyobb pénzfelvételét keressük. Ez egy olyan maxmum-kválasztás, amely addg tart, amíg az első ügyfél azonosítójával megegyező tranzakcókat olvasunk. (A programozás tételenk közül csak a kválasztásnak nncs lyen feltétel fennálláság tartó változata.) Egy gyűjtemény feltétel fennálláság tartó feldolgozásánál egyedül az End() művelet mplementácója tér el a szokásostól: ez a (t,) lesz. A feltétel fennálláság tartó feldolgozásokra s érvényes az, amt korábban a lneárs keresésről vagy a kválasztásról s elmondtunk, nevezetesen, hogy mvel korábban s leállt a feldolgozás, mnt hogy a gyűjtemény összes elemét bejárnánk, a még fel nem sorolt (fel nem dolgozott) elemeket alá lehet vetn tovább feldolgozásnak. Ezért ez a felsoroló s eredménye ezeknek a feldolgozásoknak. A gyűjteményekre alkalmazott feltétel fennálláság tartó feldolgozások specfkácójában a bejárás végét jelző t helyére a (t,) feltételt fogjuk írn. Néhány példa: s, t ( t', ) 1 g( t, ) ( t', ) 1 ( t, ) ( t', )), c, t 1 max, t max g( t ) l, elem, t search ( t' ) 1 ( t', ) 1 9.2. Példa. Egy szekvencáls nputfájl elején álló poztív számok között a párosak száma! A = (f:nfle(z), df:z, sf: Státusz, db:z) Ef = ( f=f ) f ' 0 f ' Uf = ( db, sf, df, f = 1 ) 1 2 f ' A számlálást tt nem feltétlenül a fájl végég, nem csak annak első nem-poztív értékég kell végezn. Ezért utal az utófeltétel arra, hogy a számlálás eredménye a db változón kívül a szekvencáls fájl elkezdett felsorolása s, amelyre az sf, df, f együtt hvatkozk. Ezt a feltétel fennálláság tartó feldolgozást s az általános számlálás programozás tételére vezethetjük vssza úgy, hogy a Frst() és Next() műveleteket most s az sf, df, f : read mplementálja; a Current() művelet a df lesz és ennek megfelelően a számlálás feltétele a 2df 134

9.3. Csoportok felsorolása kfejezés; a End() műveletet azonban az sf=norm helyett a sf=norm df 0 kfejezés helyettesít. db:=0; sf, df, f : read df>0 sf=norm db:=db+1 2df SKIP sf, df, f : read 9.3. Példa. Egy szekvencáls nputfájlban a banknál számlát nytott ügyfelek e v kvét/betét forgalmát (tranzakcót) tároljuk. Mnden tranzakcónál nylvántartjuk az ügyfél azonosítóját, a tranzakcó dátumát és az összegét, am egy előjeles egész szám (negatív a kvét, poztív a betét). A tranzakcók a szekvencáls fájlban ügyfél-azonosító szernt rendezetten helyezkednek el. Keressük meg az első ügyfél legnagyobb befzetésű tranzakcóját. A = (f:nfle(tranzakcó), df: Tranzakcó, sf: Státusz, max: Tranzakcó) Tranzakcó = rec(azon:n, dátum:n, össz:z) Ef = ( f=f f azon szernt rendezett) Uf = ( max, sf, df, f f '. azon f ' 1. azon f ', max f. össz ) 1 Ezt vsszavezethetjük a maxmum-kválasztás tételére. Nem kell külön eredmény a maxmáls értékre, hszen azt a maxmáls elem (a rekord) tartalmazza. Továbbá, mvel a max változóban tárolt tranzakcó bztosan az első ügyfélhez tartozk, így a max.azon = f 1.azon mndg teljesül, amt a cklusfeltétel felírásában k s sználtunk. sf, max, f : read sf, df, f : read df.azon=max.azon sf=norm df.össz>max.össz max:= df SKIP sf, df, f : read 135

9. Vsszavezetés egyed felsorolókkal 9.3. Csoportok felsorolása 9.4. Példa. Több egymás után napon feljegyeztük a nap átlaghőmérsékleteket, és azokat egy szekvencáls nputfájlban rögzítettük. Volt-e olyan nap, amkor a megelőző naphoz képest csökkent az átlaghőmérséklet! A = (f:nfle(r), l:l) Ef = ( f=f ) f ' Uf = ( l search f ' f ' 0) ) 2 ( 1 Vegyük észre, hogy a feladat nem oldtó meg a szekvencáls nputfájl nevezetes bejárásával, hszen az nem ad lehetőséget a szekvencáls nputfájl egymás után következő két elemének vzsgálatára. Helyette olyan felsorolóra van szükség, amely a szekvencáls nputfájl szomszédos elempárjat adja meg egymás után. Ez nem a szekvencáls nputfájl szokásos, nevezetes bejárója, nem egy arra támaszkodó, de attól elvonatkoztatott, absztrakt felsoroló. Újrafogalmazzuk tehát a feladatot egy olyan állapottéren, ahol adottnak vesszük az előbb ktalált felsorolót. A = (t:enor(rec(tegnap:r, ma:r)), l:l) Ef = ( t=t ) t' Uf = ( l search ( t'. ma t'. tegnap 0) ) 1 Az új specfkácó célja az, hogy mnél könnyebben lehessen a feladat megoldását a lneárs keresésre vsszavezetn. Természetesen a bevezetett felsoroló típusát egyed módon kell megvalósítan: az eredet állapottér komponensere támaszkodva reprezentáln kell és a bejárás műveletet pedg mplementáln. Ezzel lényegében részfeladatokra bontottuk az eredet problémát. Részfeladat az új állapottéren megfogalmazott lneárs keresés, és részfeladatok a Frst(), Next(), Current(), End() mplementácó s. Az újrafogalmazott feladat vsszavezethető az általános lneárs keresésre, amelyből mvel ezt specálsan eldöntésre sználjuk az elem:=t.current() értékadást elgytuk. l := ms; t.frst() l t.end() l := (t.current()) Implementáljuk az absztrakt felsoroló műveletet. A Frst() művelet feladata az első felsoroln kívánt elemre, esetünkben az első hőmérséklet-párra, egy tegnap-ma számpárra (ezt nem rekordként, nem két valós számként sználjuk) való ráállás. Ehhez az f szekvencáls nputfájlból az a első hőmérsékletet a tegnap változóba, a másodkat a ma változóba kell beolvasnunk. (A két olvasás akkor s végrejttó, a fájl nem tartalmaz két értéket.) A Next() feladata a soron következő hőmérséklet-párra való ráállás. Ehhez szükség van a korább számpár ma hőmérsékletére (a tegnap mára), amből az aktuáls számpár tegnap 136

9.3. Csoportok felsorolása hőmérséklete (a ma tegnap) lesz, tehát tegnap:=ma, valamnt be kell olvasn f fájlból a ma változóba az aktuáls ma hőmérsékletet s. A Current() a tegnap-ma számpárt adja vssza. Az End() addg ms, amíg skerült újabb számpár előállításához újabb értéket olvasn az f fájlból, azaz amíg sf=norm. A fentekből az s kderül, hogy az absztrakt felsorolót a tegnapma számpár, az f szekvencáls nputfájl, és az utolsó olvasás sf státusza reprezentálja. Behelyettesítve az algortmusba Frst(), Next(), Current(), End() mplementácót, megkapjuk a megoldást. sf, tegnap, f : read sf, ma, f : read l:=ms l sf=norm l:= ma-tegnap< 0 tegnap:=ma sf, df, f : read 9.5. Példa. Egy szekvencáls nputfájlban a banknál számlát nytott ügyfelek e v kvét/betét forgalmát (tranzakcót) tároljuk. Mnden tranzakcónál nylvántartjuk az ügyfél számlaszámát, a tranzakcó dátumát és az összegét, am egy előjeles egész szám (negatív a kvét, poztív a betét). A tranzakcók a szekvencáls fájlban számlaszám szernt rendezetten helyezkednek el. Gyűjtsük k azon számlaszámokat és az ahhoz tartozó tranzakcónak egyenlegét, ahol ez az egyenleg ksebb 100000 Ft-nál! A feladat specfkácóját nem s olyan könnyű formálsan felírn. A = (x:nfle(tranzakcó), v: outfle(egyenleg)) Tranzakcó = rec(sz:strng, dátum:n, össz:z) Egyenleg = rec(sz: Strng, össz:z) Ef = ( x=x az x sz szernt rendezett) Uf = (?) Az utófeltételt csak nagyon körülményesen lehetne leírn, mert a szekvencáls nputfájl nevezetes bejárása nem lleszkedk a feladathoz. Nekünk nem a tranzakcókat, nem egy számla összes tranzakcónak eredőjét kell egy lépésben feldolgozn. Olyan felsorolóra van szükség, amelyk egy számlaszám mellé ezt az eredőt meg tudja adn. Egy lyen ktalált (absztrakt) felsorolóval a specfkácó megfogalmazása s könnyebb. A = (t:enor(egyenleg), v: outfle(egyenleg)) Ef = ( t=t ) ' t, Uf = ( v t ) 1 t'. össz100000 Ez a feladat vsszavezethető az összegzés programozás tételére, ahol a f:egyenlegegyenleg* típusú, és egy e egyenlegre e.össz<-100000, akkor f(e) megegyezk az <e> egyelemű sorozattal, különben f(e) az üres sorozat. 137

9. Vsszavezetés egyed felsorolókkal t.frst() t.end() t.current().össz<-100000 v:wrte(t.current()) SKIP Mnd a Frst(), mnd a Next() művelet a soron következő számlaszám tranzakcót összegz. Mvel az x szekvencáls nputfájl számlaszám szernt rendezett, így az ugyanolyan számlaszámú tranzakcók közvetlenül egymás után helyezkednek el. Ezért az egyenleget az x fájl nevezetes bejárására épülő feltétel fennálláság tartó összegzéssel lehet előállítan. A Next() művelet végrejtásakor feltételezzük, hogy az x szekvencáls nputfájl elemenek felsorolása már korábban elkezdődött, és ezért brtokunkban van a legutolsó olvasásának eredménye: sx, dx, x. Meg kell mondanunk, hogy van-e egyáltalán újabb feldolgozandó tranzakcó-csoport (vége), és gen, m ezek egyenlege (akt). A Next = (x: nfle(tranzakcó), dx: Tranzakcó, sx: Státusz, vége:l, akt:egyenleg) Ef Next = ( x = x 1 dx = dx 1 sx = sx 1 x azon szernt rendezett) Uf Next = ( (sx 1 =abnorm vége=gaz ) ( sx 1 =norm vége=ms akt.azon= dx 1.azon x x. sz akt. sz 1 akt. össz, sx, dx, x x. össz ) ) 1 1 sx=norm vége:=ms akt.azon, akt.össz:=dx.azon, 0 sx=norm dx.azon=e.azon akt.össz:=akt.össz+dx.össz sx, dx, x: read vége:=true A Frst() művelet csak egy előreolvasással több a Next()-nél, hszen tt kell elkezden az x fájlnak a felsorolását. Ezután ugyanarra a kérdésre keressük a választ, mnt előbb. A Frst = (x: nfle(tranzakcó), dx: Tranzakcó, sx: Státusz, vége:l, akte:egyenleg) Ef Frst = ( x = x x azon szernt rendezett) Uf Frst = ( sx 1, dx 1, x 1 =read(x ) (sx 1 =abnorm vége=gaz ) 138

9.3. Csoportok felsorolása (sx 1 =norm vége=ms akt.azon= dx 1.azon x x. sz akt. sz 1 akt. össz, sx, dx, x x. össz ) ) 1 1 t.frst() sx, dx, x:read Az absztrakt felsorolót tehát az sx, a dx, az x, az akt és a vége adatok együttesen reprezentálják. Az aktuáls számlaszám tranzakcónak egyenlegét (akt) a Current() művelettel kérdezhetjük le, az egyenlegek felsorolásának végét a vége változó jelz: ezt adja vssza az End(). 9.6. Példa. Egy repülőgéppel elrepültünk a Csendes Óceán szgetvlágának egy része felett, és megtározott távolságonként megmértük a felszín tengersznt felett magasságát. Ott, ahol óceán felszínét észleltük, ez a magasság nulla, a szgeteknél poztív. A mérést óceán felett kezdtük és óceán felett fejeztük be. Az így kapott nem-negatív valós értékeket egy n hosszúságú x vektorban tároljuk. Adjuk meg a mérések alapján, hogy mekkora a leghosszabb szget, és a repülés hányadk mérésénél kezdődk ezek közül az egyk. A feladat állapottere az alább: A = (x:n n, max:n, kezd:n) Ezt a feladatot már megoldottuk (6.9. példa) ntervallumos maxmum-kválasztással, ahol egy egész számokon értelmezett rekurzív függvény értéke között kerestük a legnagyobbat. Most s maxmum-kválasztást fogunk sználn, de nem a vektor ndextartományát járjuk be közvetlenül, nem a szgetek hosszat. Ehhez egy olyan felsorolót készítünk, amelyk a szgetek hosszat tudja sorban egymás után megadn azok vektorbel kezdőndexével együtt. A feladat specfkácóját ezért nem az eredet állapottéren, nem a ktalált felsorolóra írjuk fel, amely elrejt az eredet megfogalmazásban szereplő x vektort. Elképzelésünk szernt a felsorolt elemek nemcsak a szgetek hosszat, nem a szgetek vektorbel kezdő ndexet s tartalmazzák. A = (t:enor(szget), max:n, kezd:n) Szget = rec(hossz:n, eleje:z) Ef = ( t=t ) t' Uf = ( max, elem = max 1, t. hossz kezd = elem.eleje) A feladatot maxmum-kválasztás programozás tételére vezetjük vssza, ahol f:szgetn és f(e)=e.hossz. A tétel alkalmazásakor elég a megtalált maxmáls elemet eredményként megadn, hszen az tartalmazza a maxmáls értéket s. Ebből az eredményből közvetlenül kolvastó a leghosszabb szget hossza és kezdőndexe. t.frst() 139

9. Vsszavezetés egyed felsorolókkal max, kezd:= t.current().hossz, t.current().eleje t.end() t.current().hossz>max max, kezd := t.current().hossz, t.current().eleje SKIP Mnd a Frst(), mnd a Next() műveletet el lehet készíten úgy, hogy a vektor egy adott pozícójáról ndulva (kezdetben ez az 1) keressék meg a következő szget elejét (az első nemnulla értéket), majd annak a végét (az első nullát), ebből számolják k a szget hosszát és kezdőndexét. Ehhez a felsoroló reprezentálásánál szükségünk van az eredet állapottér 1-től n-g ndexelt x vektorára, és annak ndextartományát befutó ndexre. (A háttérben tehát megjelenk a vektor klasszkus felsorolója.) A Frst() és a Next() művelet közt különbség csak anny, hogy az ndex kezdőértékét a Next() művelet megkapja, míg a Frst() kezdetben 1-re állítja. A Current() művelet a legutoljára talált szget adatat adja meg, ezért a felsoroló reprezentácójában egy akt nevű Szget típusú adatot s rögzíten kell. Az End() azután ad vssza gaz értéket, egy újabb szget keresésénél >n bekövetkezk. Ezt a tényt egy l logka változó fogja jelöln: találtunk újabb szgetet, akkor az értéke gaz, különben ms. Összességében látszk, hogy a szgetek hosszanak felsorolóját a három adat reprezentálja: az l, akt és. Specfkáljuk először a Next() műveletet. A Next = (x:n n, :N, l:n, akt:szget) Q Next = (x = x = ) n R Next = ( x = x l, akt.eleje = search ( x[ ] 0) ' ( l = select ( x[ ] 0 n) akt.hossz=-akt.eleje ) ) akt.eleje Ennek bemenő adata az x vektor és annak egy ndexe (), kmenő adata az akt szget és az ndex. A szget elejének és végének keresését kválasztással oldjuk meg, hszen más nem a vektor vége tárolja ezeket. A Next() még látszólag akkor s előállít egy újabb szgetet, már nncs több szget, és ezt az akt.eleje>n feltétel jelez.a másodk kválasztás előtt nem kell az -nek kezdőértéket adn, hszen az ekkor éppen az akt.eleje értékével azonos. l := ms l n l := x[] = 0 akt.eleje:= :=+1 140

9.3. Csoportok felsorolása l x[] 0 n :=+1 akt.hossz:= -akt.eleje SKIP A Frst() művelet specfkácója egyrészt abban tér el a Next() műveletétől, hogy az nem bemenő adat, és az első kválasztás 1-ről ndul, másrészt abban, hogy mvel egy szget bztosan van, ezért tt nem kell eredményként megadn, hogy találtunk-e egyáltalán szgetet: a szget elejének megkeresése lneárs keresés helyett kválasztással történk, az l értéke pedg gaz. A Frst = (x:n n, :N, akt:szget) Q Frst = (x = x ) R Frst = ( x = x akt.eleje = select ( n x[ ] 0) 1 = select ( n x[ ] 0) akt.hossz=-akt.eleje ) akt.eleje t.frst() :=1 9.7. Példa. Egy karakterekből álló szekvencáls nputfájl egy szöveget tartalmaz. Számoljuk meg, hogy hány w betűt tartalmazó szó találtó a szövegben! (Egy szó az a szóköz karaktert nem tartalmazó karakterlánc, amelyet egy vagy több szóköz, a fájl eleje vagy vége tárol.) A feladat egy számlálás, de nem a szekvencáls nputfájl karaktere felett, nem a szekvencáls nputfájlban találtó szavak felett. A számláláshoz egy olyan felsorolóra lenne szükség, amely anny darab logka értéket sorolna fel, ahány szó szerepel a fájlban, és az - edk logka érték akkor lenne gaz, amkor a az -edk szó tartalmaz w betűt. A = (t:enor(l), db:n) Ef = ( t=t ) t' Uf = ( db 1) 1 t, db:=0; t.frst() db:=db+1 t.end() t.current() SKIP 141

9. Vsszavezetés egyed felsorolókkal Valósítsuk meg az absztrakt felsorolót! A Frst() művelet az első szó kértékelését végz. Ehhez először meg kell keresn az első szó elejét, am a szóközök átlépését, az első nem-szóköz karakter vagy a fájl végének ( nncs egyáltalán szó) megtalálását jelent. Ha megtaláltuk a szó elejét, akkor egy w betűt kezdünk el keresn, de legfeljebb a szó végég. A Next() művelet szóról szóra ugyanazt csnálja, mnt a Frst(), hszen a korább szavak kolvasásuk után már nncsenek az f fájlban, így a soron következő szó a megolvasott fájl első szava. A Current() az utoljára vzsgált szó értékelését adja vssza, az End() pedg azt, hogy elértük-e el a fájl végét a soron következő szó elejének keresése során. Az absztrakt felsoroló reprezentácójába a megolvasott szekvencáls nputfájl (sf:státusz, df:k, f:nfle(k)) mellett tehát két logka értéket s felveszünk: skerült-e újabb szót találn (van_szó:l), és ezen szóban van-e w betű (van_w:l). A szó előtt szóközök átlépése egy kválasztás (nem szóköz vagy fájl végének megtalálása) lesz, a szóban történő w betű keresése egy feltétel fennálláság tartó (amíg a szó tart) lneárs keresés. Ezután mndenképpen el kell jutn a szó végéhez, am egy újabb kválasztás (szóköz vagy fájl vége megtalálása) lesz. A Frst() és a Next() műveletek formáls leírása tehát közös: A = (f: nfle(k), df:k, sf: Státusz, van_szó:l, van_w:l) Ef = ( f = f ) 1 1 1 ' ' Uf = ( sf, df, f select ( f f ' ') van_szó=(sf 1 =norm) 1 2 2 2 1 (van_szó van_ w, sf, df, f search ( f ' w' ) 1 1 f f ' ' 2 2 sf, df, f select ( f f ' ') ) ) Az utófeltételből kolvastó a megoldás három szakasza: az f fájl felsorolására épülő kválasztás, a felsorolás folytatására épülő lneárs keresés, majd tovább folytatva a felsorolást egy újabb kválasztás. Ezen szakaszok tárán a felsoroló állapotat felső ndexekkel különböztettük meg. Nncs vszont szüksége az újabb Next() műveletnek a megelőző Next() vagy Frst() művelet végén végzett utolsó olvasás státuszára és eredményére, ezért az első szakasz kválasztása egy előreolvasással ndul szemben a másk két szakasszal. t.frst()= sf, df, f : read df= sf = norm sf, df, f : read van_szó:= sf=norm van_szó van_w:=ms van_w df sf = norm van_w:=(df= w ) sf, df, f: read df sf = norm SKIP 142

9.3. Csoportok felsorolása sf, df, f: read Valósítsuk meg az absztrakt felsorolót most másképpen! Kössük k a Next() művelet mplementácójánál, hogy a szekvencáls nputfájl olyan megolvasott állapotban legyen, hogy nem értük el a fájl végét ( sf=norm), akkor a soron következő szó elejénél álljunk (df ). (Ez a felsoroló objektum típus-nvaránsa.) Ekkor a Next() művelet mplementácója nem gényel előreolvasást, és rögtön a következő szó vzsgálatával kezdődhet ( w betű lneárs keresése majd a szó végének kválasztása), van egyáltalán következő szó.. Vszont e vzsgálat után gondoskodna kell a szó után szóközök átlépéséről (kválasztás) azért, hogy az újabb Next() művelet számára s bztosítsuk a kívánt előfeltételt. A Frst() művelet annyval több, mnt a Next() művelet, hogy először bztosítana kell a fent típus-nvaránst. Ehhez a vezető szóközök átlépésére (kválasztás) van szüksége. A Current() és az End() mplementácója nem változk. A Next = (f: nfle(k), df:k, sf: Státusz, van_szó:l, van_w:l) Q Next = ( f = f 1 df = df 1 sf = sf 1 (sf = normdf ) ) R Next = ( (van_szó=(sf 1 =norm)) 1 1 f f ' 2 2 2 1 (van_szó ( van_ w, sf, df, f search ( f ' w' ) 3 3 3 2 2 sf, df, f select ( f f ' ') 3 3 sf, df, f select ( f f ' ') ) )) ') A Frst = (f: nfle(k), df:k, sf: Státusz, van_szó:l, van_w:l) Q Frst = ( f = f ) R Frst 1 1 1 ' ' = ( sf, df, f select ( f f ' ') A megfelelő algortmusok: (van_szó=(sf 1 =norm) (van_szó ( lásd R Next -ben ) ) ) t.frst() sf, df, f : read df= sf = norm sf, df, f : read van_szó:= sf=norm van_szó:= sf=norm van_szó van_w:=ms van_w df sf = norm van_w:=(df= w ) sf, df, f: read df sf = norm sf, df, f: read SKIP 143

9. Vsszavezetés egyed felsorolókkal df= sf = norm sf, df, f: read 144

9.3. Csoportok felsorolása 9.4. Összefuttatás Az előző alfejezetekben olyan feladatokat látttunk, ahol a feldolgozáshoz felsorolt értékek egyetlen gyűjteményből származtak. Találkoztunk azonban olyan feladatokkal s, ahol a feldolgozandó elemek több bemenet adatban helyezkednek el. Ilyenkor olyan felsorolást kell adunk, amely során képzeletben egyetlen sorozattá futtatjuk össze a bemenet adatok elem értéket. Vegyük például azt, amkor két lmaz metszetét kell előállítan. Ha fel tudjuk soroln a lmazok összes elemét, akkor készen s vagyunk, hszen ezek közül csak azokat tesszük bele az eredmény lmazba, amelyek mndkét lmazban szerepelnek. Az alább specfkácóban ezt a megközelítést tükröz az utófeltétel másodk alakja, amelyben az unó arra utal, hogy a feldolgozás során nemcsak a közös elemeket kell megvzsgáln, nem az összest. Ezért a megoldás az x y lmaz felsorolására épített összegzés (tt unózás) lesz, amely fokozatosan fogyasztja el a két lmazt. A = (x:set(e), y:set(e), z: set(f)) Ef = ( x = x y = y ) Uf = ( z = x y ) = ( z = U f ( e) ex ' y ' f ( e) ) { e} e x' e y' e x' e y' e x' e y' A feldolgozást azonban nem kell addg végezn, amíg mndkét lmaz üres nem lesz, hszen a közös elemek kgyűjtése véget ér, már az egyk lmaz kürül. Az End() művelet tehát addg ms, amíg egyk lmaz sem üres. A Current() az xy lmazból választ k determnsztkus módon egy elemet (mem(xy)). A Frst() művelet mnt azt a lmazok bejárásánál láttuk az üres program lesz, hszen kezdetben nem kell tenn semmt ahhoz, hogy a Current() műveletet sználssuk. A Next() művelet a felsorolás során aktuálsan kválasztott elemet elvesz az xy lmazból, azaz x-ből, az x-bel, y-ból, y-bel, mndkettőből, mndkettőnek eleme. Ez tehát egy háromágú elágazás. Mvel az aktuálsan kválasztott érték feldolgozásánál s azt kell vzsgáln, hogy az érték melyk lmaznak az eleme, ezért a Next() művelet elágazása a feldolgozás elágazásával összevontó. Így kapjuk az alább programot. z:= x y e:=mem(xy) ex ey ex ey ex ey SKIP SKIP z:= z {e} x:=x {e} y:=y {e} x, y := x {e}, y {e} 145

9. Vsszavezetés egyed felsorolókkal Nehezebb a feladat megoldása akkor, hogy a felsorolandó elemek nem két lmazban, nem mondjuk, két vektorban helyezkednek el. Annak eldöntése ugyans, hogy egy (vektorból kválasztott) érték szerepel-e egy (másk) vektorban egy keresést gényel. (Ha rendezett az a vektor, ahol keresünk, akkor logartmkus keresést.) Gyorsabb lesz a megoldás, mndkettő vektor szgorúan monoton növekvő, azaz egy érték egy vektorban legfeljebb egyszer fordul elő, és mndkét vektor eleme azonos szempont szernt növekvően rendezettek. (Természetesen feltételezzük, hogy a vektorok elemenek E lmazán értelmezett egy teljes rendezés.) Ekkor ugyans meg lehet valósítan egy szmultán (összefuttatott, összefésült) bejárást, amely a vektorokban találtó elemeket a rendezettségüknek megfelelően sorolja fel úgy, hogy mnden elemnél megmondja, hogy az csak az egyk, csak a másk vagy mndkettő vektorban szerepel-e. A bejáráshoz két ndexváltozót sználunk: és j. A Frst() művelet rááll a vektorok első elemere (,j:=1,1). A feldolgozás során még nem érntett x-bel elemek x[..n]-ben vannak (pontosabban az elemek ndexe az [..n] tartományba tartoznak), az y-belek y[j..m]ban találtók. A felsorolás során mndvégg gaz, hogy n és j m ez lesz a End(), akkor az x[] az x vektor legksebb, y[j] pedg az y vektor legksebb még feldolgozatlan értéke. Ha x[]<y[j], akkor a soron következő feldolgozandó érték az x[] lesz, hszen ez a legeslegksebb érték az x[..n] és y[j..m] feldolgozatlan eleme között. Ez nylván nem közös eleme a két vektornak, hszen benne lenne y-ban, akkor annak rendezettsége folytán ez állna az y[j] helyén, nem pedg egy ennél nagyobb érték. A feldolgozás tehát x[]-vel nem csnál semmt, a Next() művelet pedg úgy lép a következő elemre, hogy az :=+1 értékadással átlép az x[]-t. Hasonló megfontolásokból x[]>y[j] esetén csak a j:=j+1 értékadásra (lyenkor ez a Next() művelet) van szükség. Ha azonban x[]=y[j], akkor olyan értékkel találkoztunk, amely mndkét vektorban szerepel, ez egy közös érték, amt kírunk a z vektorba, majd a Next() művelet átlép ezt az értéket mndkét vektorban. A Current() művelet a fent három esettől függően vagy az x[]-t, vagy az y[j]-t, vagy az x[]-t adja vssza. Most csak a rmadk esetben kell a felsorolt értéket (x[]-t) feldolgozn. Mvel mnd a Current() művelet, mnd a feldolgozás, mnd a Next() művelet ugyanazon háromágú elágazással írtó le, ezt egyetlen háromágú elágazásba vonjuk össze, amely az alább algortmus cklusmagjában láttó. A feldolgozás eredményét egy z vektorba helyezzük el, amelynek aktuáls méretét a k mutatja. Ez a vektor s egyértelmű és rendezett lesz., j, k := 1, 1, 0 n j m x[]< y[j] x[]>y[j] x[]=y[j] SKIP SKIP k := k+1 z[k] := f(x[]) := +1 j := j+1, j := +1, j+1 Ha nemcsak a közös elemeket kell feldolgozn, nem az összes elem felsorolására szükség van, akkor a End() művelet az x j y -ra módosul. Ematt a hármas elágazás feltételrendszere s bonyolultabbá válk. Ugyans nemcsak az utal arra, hogy az x[] elemet kell feldolgozn, x j y x[]<y[j], nem az s, x j> y, azaz amkor már az y vektor elemet már mnd feldolgoztuk. Analóg módon, y[j] a feldolgozandó elem akkor, 146

9.4. Összefuttatás ( x j y x[]>y[j]) (> x j y ). A rmadk eset feltétele: x j y x[]=y[j]. Fgyelembe véve, hogy ezek a feltételek egy olyan cklus magjában kerülnek kértékelésre, amelynek cklusfeltétele: x j y, az elágazás feltétele egyszerűsödnek. Általánosítsuk a fent problémát felsorolókra! Dolgozzuk fel egyenként az x és y felsorolók által szgorúan növekedően rendezett sorrendben előállított elemeket, és a feldolgozásuk eredményét fűzzük egy z sorozatba. A = (x: enor(e), y: enor(e), z:seq(e)) f1( e) Ef = ( x = x y = y x y) f ( e) f 2 ( e) Uf = ( z f ( e) f ( e) e{ x'} { y'} 3 e { x'} e { y'} e { x'} e { y'} e { x'} e { y'} A specfkácóban a t jelöl azt, hogy t szgorúan növekvően rendezett, és természetesen feltételezzük, hogy E-n értelmezett egy teljes rendezés. A {t}-vel egy t felsorló elemeből képzett lmazt jelöltük. Mvel feltettük, hogy a felsorolt értékek nem smétlődnek, így azok gondolatban történő lmazzá alakítása nem okoz adatvesztést. A feladatot a felsorolt elemek összefuttatása mellett összegzés oldja meg, amelyk addg tart, amíg a felsorolások végére nem érünk. Ennek alapját egy olyan egyed felsoroló adja, amelynek Current() művelete az x.current() és y.current() elemek közül a ksebbet, csak az egyk adott, akkor azt, egyezés esetén az egyező elemet adja meg. A Frst() művelet az x.frst() és y.frst() egydejű végrejtásából áll, hszen ez teremt meg a lehetőséget arra, hogy az x.current() és y.current() értelmezhető legyen. A Next() művelet az aktuálsan feldolgozott elemet eldobja azért, hogy a Current() a soron következőt tudja majd megadn. Ehhez egy háromágú elágazás kell. Ha x.current()<y.current() (vagy y.end() és x.end()), akkor az x.current() a feldolgozott elem, azt kell lecseréln az x.next()-tel. Ha x.current()>y.current() (vagy x.end() és y.end()), akkor az y.next()-re van szükség. Ha x.current()=y.current(), akkor mndkét felsorolóval tovább kell lépn. Mvel az aktuálsan kválasztott érték feldolgozásánál s ugyanezt a három feltételt kell vzsgáln, a Next() művelet elágazása a feldolgozás elágazásával összevontó. Az End() művelet akkor lesz gaz, mnd az x, mnd az y felsoroló véget ért, azaz x.end() y.end(). Fontos észrevenn, hogy az eredmény sorozat s egyértelmű és rendezett lesz. y.end() (x.end() x.current()<y.current()) x.frst(); y.frst(); z := <> x.end() y.end() x.end() (y.end() x.current()>y.current()) x.end() y.end() x.current()=y.current() z:wrte(f 1 (x.current())) z:wrte(f 2 (x.current())) z:wrte(f 3 (x.current())) x.next(); y.next() x.next(); y.next() Ezek alapján az összefuttatásos feldolgozás könnyen adaptáltó sorozatok vagy szekvencáls nputfájlok összefuttatására s. Az összefuttatás alkalmazásának egyk klasszkus példája az alább szekvencáls karbantartás. 147

9. Vsszavezetés egyed felsorolókkal 9.8. Példa. Adott egy árukészletet az áruk azonosítója szernt egyértelmű és növekvően rendezett szekvencáls nputfájl, továbbakban törzsfájl, és az egyes árukra vonatkozó változtatásokat tartalmazó áruk azonosítója szernt egyértelmű és növekvően rendezett másk szekvencáls nputfájl, továbbakban módosító fájl. A változtatások három félék lehetnek: új áru felvétele (beszúrás), meglevő áru leselejtezése (törlés) és meglevő áru mennységének módosítása (módosítás). Készítsük el a változtatásokkal megújított, úgynevezett dőszerűsített árukészletet. A törzsfájl Áru=rec(azon:N, menny:n) típusú elemek; a módosító fájl pedg Változás=rec(azon:N, müv:{i,d,u}, menny:z) típusú elemek sorozata. Az I (beszúrás), D (törlés), U (módosítás) a megfelelő változtatás típusára utal, a mennység a törlés esetén érdektelen, módosítás esetén ennyvel kell az eddg mennységet módosítan. Az új törzsfájl a rég törzsfájllal megegyező szerkezetű. A feladat állapottere: A= (t:nfle(áru), m:nfle(változás), u:outfle(áru)) Ef = ( t = t' m = m' t és m szekvencáls nputfájlok t és m az azon mező szernt szgorúan növekedően rendezett) Szükségünk van egy olyan felsorolóra, amelyk fel tudja soroln a két szekvencáls nputfájlban előforduló összes áruazonosítót, meg tudja mondan, hogy az melyk nputfájlban találtó (törzsfájl, módosító fájl vagy mndkettő), és képes megadn az aktuáls áruazonosítóhoz tartozó törzsfájlbel lletve módosító fájlbel rekordot. Az azon(t ) az összes t -bel azonosítót tartalmazó lmazt, az azon(m ) az összes m -bel azonosítót tartalmazó lmazt jelöl. Ha aazon(t ), akkor a(t ) a t -bel a azonosítójú rekordot jelöl. Hasonlóan, aazon(m ), akkor az a(m ) az m -bel a azonosítójú rekord. A= (x:enor(n), u: outfle(áru)) Ef = ( x = x' ) x' S = ( u f ( x' ) ) 1 f ( a) a( t') f ( a) 2 f ( a) 3 a azon( x') a azon( y') a azon( x') a azon( y') a azon( x') a azon( y') ( a, a( m' ). menny) f 2 ( a) hba kül e. müv I hba f 3 ( a) ( a, a( t' ). menny a( m' ). újmenny) e. müv I e. müv D e. müv U A feladat megoldását a fent körvonalazott felsoroló felett összegzésre (am tt egy elemenként feldolgozás) vezetjük vssza. A felsorolót a két előreolvasott nputfájl (st, dt, t, sm, dm, m) reprezentálja. A Frst() művelet végz el a kezdet előreolvasásokat. Az End() akkor lesz gaz, mndkét fájl kürült, azaz st=anorm és sm=abnorm. A Current() művelet a soron következő azonosítót és az ahhoz kapcsolódó adatokat adja vssza, amely a dt és dm-ből 148

9.4. Összefuttatás olvastó k. Ha valamelyk fájlra az utolsó olvasás abnorm státuszt adott vssza, akkor értelemszerűen a másk fájlból olvasott aktuáls elem a soron következő, mndkét fájl olvasás státusza norm, akkor a két aktuáls elem közül a ksebb azonosítójú, egyenlőség esetén mndkettő aktuáls elem együtt. Ezek három esetben foglaltók össze: t -bel aktuáls elemet (dt) dolgozunk fel, m -bel aktuáls elemet (dm) vagy t és m aktuáls elemet. A Next() művelet a feldolgozott aktuáls elem helyére próbál újabbat olvasn a fent három esetnek megfelelően: egyk nputfájlból, másk nputfájlból vagy mndkettőből. sm=abnorm (st=norm dt.azon<dm.azon) u:wrte(dt) st, dt, t: read; sm, dm, m: read; u := <> st=norm sm=norm st=abnorm (sm=norm dt.azon>dm.azon) dm.müv=i u:wrte(dm.a, dm.menny) st=norm sm=norm dt.azon=dm.azon dm.müv= I D U HIBA HIBA SKIP u:wrte(dt.a, dt.menny+ dm.menny) st, dt, t: read sm, dm, m: read st, dt, t: read; sm, dm, m: read Az tt megoldott feladatot úgy s átfogalmaztjuk, hogy nem követeljük meg azt, hogy a módosító fájl egyértelmű legyen, azaz egy azonosítóhoz több változtatást s rendelhetünk. Ennek egyk megoldása az lehet, hogy a fent algortmusban a módosító fájlnak nem az egyes elemet, nem a megegyező azonosítójú csoportjat olvassuk be és futtatjuk össze a törzsfájl elemevel. A csoportok kolvasásához pedg a korábban (9.3. alfejezet) mutatott technkával tudunk felsorolót készíten. Egy másk lehetőséget kínál a megoldásra egy olyan felsoroló készítése, amelyk azonosító szernt növekedve úgy sorolja fel az elemeket, hogy egy adott azonosítóhoz először a törzsfájlbel elemet, lyen nncs, akkor egy specáls üres elemet adja meg, majd az lyen azonosítójú módosító fájlbel elemeket sorolja fel. A feladatot ekkor egy rekurzív függvény kszámításával oldtjuk meg. (lásd feladatok között) Hasonló problémát vet fel az, amkor a módosítások több különböző módosító fájlban találtók. Ilyenkor előbb össze kell futtatn ezeket egyetlen módosító fájlba, vagy legalábbs egy olyan felsorolót kell bevezetn, amely egyetlen, azonosító szernt növekvő sorozatként bánk a módosító fájlokkal. Ennek lényegét emel k a következő feladat. 9.9. Példa. Adott n darab egész számokat tartalmazó szekvencáls nputfájl, mndegyk egyértelmű és növekvően rendezett. Készítsünk olyan felsorolót, amely a fájlokban előforduló összes egész számot felsorolja úgy, hogy egy számot csak egyszer ad meg. A felsorolót az összes előreolvasott szekvencáls nputfájllal reprezentáljuk. Ez három 1-től n-g ndexelhető tömbbel ábrázoltó: f:nfle(z) n, df:z n, sf:státusz n. A kezdet beolvasásokat a Frst() művelet végz. Az End() művelet akkor ad gazat, mndegyk fájl olvasás státusza abnorm lesz. Ennek eldöntésére az 1..n ntervallum felett egy optmsta 149

9. Vsszavezetés egyed felsorolókkal lneárs keresésre van szükség: vzsgáljuk, hogy [1..n]:sf[]=abnorm teljesül-e. A Current() művelet a soron következő egész számot az aktuálsan beolvasott egész számok között mnmum-kereséssel tározza meg, de k kell gyna a vzsgálatból azon fájlokat, amelyek olvasás státusza már abnorm. Vegyük észre, hogy ez a feltételes mnmum-keresés egyben az End() műveletet s mplementálja, hszen mellékesen eldönt, hogy van-e még nem üres fájl. Ezért tegyük bele ezt a Frst() (és később a Next()) művelet mplementácójába, a felsoroló reprezentácójához pedg vegyük hozzá a mnmum keresés eredményét tároló l logka értéket, és mn egész számot. Ekkor az End() értéke egyszerűen a l lesz, a Current() értéke pedg a mn. A Next() műveletnek mndazon fájlokból kell új elemet olvasna, amelyek aktuálsan kolvasott értéke megegyezk a mn értékkel, majd végre kell jtana az előbb említett feltételes mnmum-keresést. Mnd a Frst(), mnd a Next()-bel cklusok összevontók egy cklusba. Frst() =1..n sf[],df[],f[]:read l, mn := mn df [ ] n 1 sf [ ] norm Next() =1..n sf[]=norm df[]=mn sf[],df[],f[]:read SKIP l, mn := mn df [ ] n 1 sf [ ] norm 150

9.5. Feladatok 9.5. Feladatok 9.1. Egy kémrepülőgép végg repült az ellenség dállása felett, és rendszeres dőközönként megmérte a felszín tengersznt felett magasságát. A mért adatokat egy szekvencáls nputfájlban tároljuk. Tudjuk, hogy az ellenség a dászat rakétát a lehető legmagasabb horpadásban szokta elhelyezn, azaz olyan helyen, amely előtt és mögött magasabb a tengersznt felett magasság (lokáls mnmum). Mlyen magasan találtók az ellenség rakétá? 9.2. Számoljuk meg egy karakterekből álló szekvencáls nputfájlban a szavakat úgy, hogy a 12 betűnél hosszabb szavakat duplán vegyük fgyelembe! (Egy szót szóközök vagy a fájl vége tárol.) 9.3. Alakítsunk át egy btsorozatot úgy, hogy az első btjét megtartjuk, utána pedg csak számokat írunk annak megfelelően, hogy hány azonos bt követ közvetlenül egymást! Például a 00011111100100011111 sorozat tömörítve a 0362135 számsorozat lesz. 9.4. Egy szöveges fájlban a bekezdéseket üres sorok választják el egymástól. A sorokat sorvége jel zárja le. Az utolsó sort zártja a fájl vége s. A sorokban a szavakat a sorvége vagy elválasztójelek tárolják. Adjuk meg azon bekezdések sorszámat, amelyek tartalmazzák az előre megadott n darab szó mndegykét! (A nem-üres sorokban mndg van szó. Bekezdésen a szövegnek azt a szakaszát értjük, amely tartalmaz legalább egy szót, és vagy a fájl eleje lletve vége, vagy legalább két sorvége jel tárolja.) 9.5. Egy szöveges állomány legfeljebb 80 karakterből álló sorokat tartalmaz. Egy sor utolsó karaktere mndg a specáls \eol karakter. Másoljuk át a szöveget egy olyan szöveges állományba, ahol legfeljebb 60 karakterből álló sorok vannak; a sor végén a \eol karakter áll; és ügyelünk arra, hogy az eredetleg egy szót alkotó karakterek továbbra s azonos sorban maradjanak, azaz sorvége jel ne törjön ketté egy szót. Az eredet állományban a szavakat egy vagy több szótároló jel választja el (Az \eol s ezek közé tartozk), amelyek közül elég egyet megtartan. A szótároló jelek egy karaktereket tartalmazó szótár nevű lmazban találtók. Feltehetjük, hogy a szavak 60 karakternél rövdebbek. 9.6. Adott egy keresztneveket és egy vrágneveket tartalmazó szekvencáls fájl, mndkettő abc szernt szgorúan növekedően rendezett. Határozzuk meg azokat a keresztneveket, amelyek nem vrágnevek, lletve azokat a neveket, amelyek keresztnevek s, és vrágnevek s! 9.7. Egy x szekvencáls nputfájl egy könyvtár nylvántartását tartalmazza. Egy könyvről smerjük az azonosítóját, a szerzőjét, a címét, a kadóját, a kadás évét, az aktuáls példányszámát, az ISBN számát. A könyvek azonosító szernt szgorúan növekvően rendezettek. Egy y szekvencáls nputfájl az aznap könyvtár forgalmat mutatja: melyk könyvből hányat vttek el, lletve hoztak vssza. Mnden bejegyzés egy azonosítót és egy előjeles egészszámot - elvtték: negatív, vsszahozták: poztív - tartalmaz. A bejegyzések azonosító szernt szgorúan növekvően rendezettek. Aktualzáljuk a könyvtár nylvántartást! A feldolgozás során keletkező hbaeseteket egy h sorozatba írjuk bele! 9.8. Egy vállalat dolgozónak a fzetésemelését kell végrejtan úgy, hogy az azonos beosztású dolgozók fzetését ugyanakkora százalékkal emeljük. A törzsfájl dolgozók 151

9. Vsszavezetés egyed felsorolókkal sorozata, ahol egy dolgozót három adat helyettesít: a beosztáskód, az egyén azonosító, és a bér. A törzsfájl beosztáskód szernt növekvően, azon belül azonosító szernt szgorúan monoton növekvően rendezett. A módosító fájl beosztáskód-százalék párok sorozata, és beosztáskód szernt szgorúan monoton növekvően rendezett. (Az egyszerűség kedvéért feltehetjük, hogy csak a törzsfájlban előforduló beosztásokra vonatkozk emelés a módosító fájlban, de nem feltétlenül mndegykre.) Adjuk meg egy új törzsfájlban a dolgozók emelt béret. 9.9. Egy egyetem kurzusra járó llgatóknak három gépterm zárthelyt kell írna a félév során. Két félévközt, amelykből az egyket.net/c#, a máskat Qt/C++ platformon. Azt, hogy a rmadk zárthelyn k mlyen platformon dolgozk, az dönt el, hogy a félévköz zárthelyken hogyan szerepelt. Ak mndkét félévköz zárthelyt teljesítette, az szabadon választt platformot. Ak egyket sem, az nem vehet részt a félévvég zárthelyn, számára a félév érvénytelen. Ak csak az egyk platformon írta meg a félévközt, annak a félévvégt a más platformon kell teljesítene. Mnden gyakorlatvezető elkészít azt a kmutatást (szekvencáls fájl), amely tartalmazza a saját csoportjába járó llgatók félévköz teljesítményét. Ezek a fájlok llgató azonosító szernt rendezettek. A fájlok egy eleme egy llgató azonosítóból és a teljesítmény jeléből (X mndkét platformon teljesített, Q csak Qt platformon, N csak.net platformon, 0 egyk platformon sem) áll. Rendelkezésünkre állnak továbbá a félévvég zárthelyre bejelentkezett llgatók azonosító rendezett formában egy szekvencáls fájlban. Állítsuk elő azt a szekvencáls outputfájlt, amelyk a zárthelyre bejelentkezett llgatók közül csak azokat tartalmazza, akk legalább az egyk félévköz zárthelyt teljesítették. Az eredmény fájlban mnden lyen llgató azonosítója mellett tüntessük fel, hogy mlyen platformon kell a llgatónak dolgozna:.net-en, Qt-vel vagy szabadon választt. 9.10. Egy vállalat raktárába több különböző cég szállít árut. A raktárkészletet egy szekvencáls nputfájlban (törzs fájl) tartják nylván úgy, hogy mnden áruazonosító mellett feltűntetk a készlet mennységét. A beszállító cégek mnden nap elküldenek egy-egy ezzel megegyező formájú szekvencáls nputfájlt (módosító fájl), amelyek az adott napon szállított áruk mennységét tartalmazzák. Mnden szekvencáls fájl áruazonosító szernt szgorúan növekvően rendezett. Aktualzáljuk a raktárnylvántartást. 152