# 14. hét: gyakorló feladatok vizsgára

Czirkos Zoltán, Ress Sándor · 2024.12.07.

Gyakorlófeladatok az előadás anyagához kapcsolódóan.

## 1. Huszonegy

Írj programot, ami magyar kártyával játszott huszonegy játékot szimulál. A kártyák színeit (tök, makk, zöld, piros) a T,M,Z,P betűkkel, a lapokat (alsó, felső, király, hetes, nyolcas, kilences, tízes, ász) pedig a A,F,K,7,8,9,X,Á betűkkel jelöld. Pl. a makk hetes -> M7, a zöld ász -> ZÁ.

- Írj függvényt `eloallit` néven, ami előállít egy listát ami a 32 kártyát tartalmazza. `TA, TF, TK, T7, ... P9, PX, PÁ`
- Írj függvényt `huz` néven, ami adott darabszámú kártyát véletlenszerűen kivesz a pakliból és visszatér a kivett lapok listájával. Tipp: random.randrange
- Írj függvényt `ertek` néven, ami egy adott lapról megmondja annak értékét. (alsó = 2, felső = 3, király = 4, a számozott lapok a számnak megfelelő érték, ász = 11)
- Írj függvényt `befuccsol` néven, ami meghatározza azt, hogy a pakliban maradt lapok között hány olyan van, amivel a játékos "befuccsol", azaz, ha azt a lapot kapja, 21 fölé nő a kézben tartott lapok értéke. Lásd a példát! (haladó kártyásoknak: az egyszerűség kedvéért nincs ohne ász szabály...)
- Írj `main` függvényt, amelyben előállítasz egy paklit, kihúzol belőle egy játékosnak 2 lapot, kíírod a lapok értékét, és ha az 21 alatt van, kiírod annak valószínűségét százalékban, hogy a következő lapra befuccsol.

Pl.

    A kiosztott lapok:  TF Z9
    A lapok értéke 12.
    A következő lapra 27% valószínűséggel befuccsol.

Azaz a játékos lapjai tök felső és zöld kilences, ami összesen 12-t ér. Ha legközelebb tízest vagy ászt húz, befuccsol. 4 tízes és 4 ász maradt a pakliban, összesen 8 "rossz lap" a maradék 30-ból, így a valószínűség 8/30, kb. 27%

## 2. Huszonkettő

Magyar kártyával játszott huszonegy játék online kaszinós változatát kell módosítanod. A szoftver a paklit egyszerűen a lapok egész értékeivel reprezentálja. (alsó = 2, felső = 3, király = 4, a számozott lapok a számnak megfelelő érték 7,8,9,10, az ász = 11), így a keveretlen pakli forráskódja:

    PAKLI= [2,3,4,7,8,9,10,11] * 4

- A szerencsejáték-felügyelet nem tartja biztonságosnak a `random.shuffle` használatát, és csak a `random.randrange` függvény hívását engedélyezi. Írd újra a `kever` függvényt, hogy a `random.shuffle` függvény helyett az előadáson és gyakorlaton megismert Fisher-Yates keverést alkalmazza a `random.randrange` használatával. Az algoritmus pszeudókódja:

      CIKLUS i = 0-tól n-2-ig:
        j = véletlenszám i ≤ j < n között
        csere: lista[i] ↔ lista[j]

- Írj függvényt `sorozat` néven, ami kap egy egész szám indexet, ahonnan kezdve vesszük a lapokat egymás után addig, amíg a lapok összege legalább 21 nem lesz. A függvény térjen vissza a lapok összegével! Túlcímzésre ügyelj!

- Írj `db21` néven függvényt meghatározod az előző függvény segítségével, hogy hány olyan egymás után következő sorozat van a pakliban, amelynek értéke 21.

  Pl. `2 7 4 10 11` pakliban van 21 értékű sorozat a 2. laptól és a 4. laptól indulva egyaránt.

- Írj `jolkever` néven függvényt, ami addig keveri a paklit, amíg nincs 21-es sorozat egy sem. A függvény térjen vissza a keverések számával.

- Demonstráld a működést a `main` függvényben, a mintához hasonlóan!

Példa kimenet:

    Alaposan megkevertem: 140 alkalommal.
    9 4 3 9 3 11 9 4 10 10 3 2 8 10 7 10 8 8 3 9 7 11 8 7 4 11 11 7 2 2 4 2

## 3. IBAN

Készíts programot, amely az első parancssori paraméterben megadott fájlból magyar bankszámlaszámokat olvas, nemzetközi (IBAN) formátumra alakítja át és a második paraméterként megadott fájlba írja. A fájlban érvényes magyar számlaszámok találhatók, esetlegesen kötőjellel vagy szóközzel elválasztva. A számlaszámok 16 vagy 24 karakteresek lehetnek. A kimenet érvényes nemzetközi bankszámlaszám legyen, négy karakterenként szóközzel elválasztva.

A program tartalmazzon hibakezelést, rossz paraméterek vagy nem létező fájl esetén adjon hibajelzést!

Az IBAN képzésének algoritmusa:

1. Az első két karakter Magyarország országkódja, azaz HU
2. A 3-4 karakter az ellenőrző szám, melynek kiszámítását lásd alább
3. Az 5-28. karakter a belföldi számlaszám. Ha a számlaszám csak 16 karakter hosszú, akkor nyolc nullás számjeggyel kell kiegészíteni.

Az ellenőrző számjegy kiszámításának algoritmusa, a 10032000-06056353 számlaszámon bemutatva:

Eltávolítjuk a tagolókat és mivel a számlaszám 16 karakteres, még 8 nullát hozzáírunk. `100320000605635300000000` Ezután a végéhez a 1730-at (ez a HU-nak felel meg, A=10, B=11 stb.) és még két nullát hozzáírunk. `100320000605635300000000173000`

Az így kapott számra kiszámoljuk a 97-el történő osztás maradékát. Ebben az esetben ez 82 lesz. Az ellenőrző szám pedig a 98 - a maradék, azaz 98-82=16 lesz. Így az átalakított számlaszám, tagolás után: `HU16 1003 2000 0605 6353 0000 0000`

Ezt a példát másold ki egy fájlba a teszteléshez (NAV SZJA, illetve a BME Neptun gyűjtőszámla).

hazai.txt:

    10032000-06056353
    10032000 01425279 01120008

nemzetkozi.txt:

    HU16 1003 2000 0605 6353 0000 0000
    HU97 1003 2000 0142 5279 0112 0008

Használj top-down tervezést, függvényeket! Legalább 2-3 függvényre bontsd szét a feladatot!

## 4. Kaminói klónozók 🔩

A kaminói klónozók többféle klónt is gyártanak. Van egy raktáruk, rengeteg alkatrésszel, és többféle típusú klón tervrajza.

A raktárkészletet egy Python szótár tartja nyilván (dict). Ebben a kulcs az alkatrész típusa, az érték pedig a darabszám, például: sisak: 6 db, csavar: 3 db, kesztyű: 7 db, csizma: 3 db. Egy adott klónhoz az alkatrészigény szintén egy szótárban tárolható, pl. kesztyű: 2 db, sisak: 1 db, csavar: 5 db.

Írj függvényt, amelyik egy alkatrészigényt kezel! Vegye át ez paraméterként a raktárkészletet és az alkatrészigényt. Ha van minden alkatrészből elég, akkor vonja le a raktárkészletből a felhasznált alkatrészeket, és adjon igazat. Ha bármelyik alkatrészből hiány van, vagy egyáltalán nincs olyan alkatrész, akkor ne csináljon semmit, hanem adjon hamisat.

Írj függvényt, amelyik fájlba írja a paraméterként adott raktárkészletet! Minden tételhez a fájl egy sora tartozzon. A sorok elején legyen a darabszám, utána pedig az alkatrész neve, vesszővel elválasztva.

Írj függvényt, amelyik a paraméterként megadott nevű fájlból beolvas egy teljes raktárkészletet, és visszaadja azt!

Mutass példát az összes megírt függvény használatára a fenti adatokkal! Az alkatrészigénylésnél írd ki, hogy sikeres vagy sikertelen-e az igénylés!

## 5. Névnapok

Egy fájl a névnapokat tartalmazza:

    1 1 Fruzsina
    1 2 Ábel
    1 3 Genovéva Benjámin
    ...
    6 2 Kármen Anita Péter Marcellinusz
    ...
    6 29 Péter Pál Emőke Judit Petra Szulamit Ivett
    12 31 Szilveszter

Olvassa be ezt a fájlt a beolvas() függvényed! A paramétere legyen a fájlnév, visszatérési értéke pedig egy általa létrehozott `dict` objektum. Az utóbbi kulcsai a napok (hónapot és napot, két egész számot tartalmazó `tuple`), értékei pedig listák, hiszen egy napon több névnap is lehet. Pl. `nevnapok[(1,3)]` értéke `["Genovéva","Benjámin"]`.

Írj ezután egy másik, megfordit() nevű függvényt, amelyik megfordítja ezt a `dict`-et! Vagyis hozzon létre egy másikat, amelyet névvel lehet indexelni, és úgy dátumokat kapunk, hogy mikor vannak az ahhoz tartozó névnapok. Például `datumok["Péter"]` értéke `[(6,2),(6,29)]` lesz a fenti adatokkal. A függvény paramétere az eredeti `dict`, értéke pedig az új `dict` legyen.

Írj főprogramot, amelyik beolvassa a nevnapok.txt fájlt az első függvénnyel, megfordítja a másikkal; végül pedig kér egy nevet a felhasználótól, és kiírja, hogy mikor tarthatja a névnapjait! (Vagy hogy nincs olyan név.)

A fenti adatokat használhatod minta fájlnak, csak a két `...`-os sort töröld ki.

## 6. Órarend

- Definiálj osztályt, amely alkalmas egy órarendi adat tárolására, amely tartalmazza, hogy az óra a hét mely napján van (hétfő = 1, kedd = 2...), mikor kezdődik (egész óra) és mi a tárgy neve!

- Írj függvényt, amely átvesz egy ilyenekből álló listát, és megkeres belőle egy órát az adott időpontban! Pl. ha a keresés 1, 8, akkor a hétfő reggel 8-as órát adja meg; ha a 3 és 9, akkor a szerda 9 órásat. Ha lyukas óra van, akkor adjon vissza None-t.

- Írj függvényt, amely az órarendet táblázatszerűen kiírja a kimenetre! A táblázatnak 5 oszlopa (hétfő-péntek) és 9 sora (07-15 óra) van. Ha egy időpontban nincs óra, azt – jellel kell jelezni a táblázatban. Használhatod az előbbi függvényt is, de más megoldást is kitalálhatsz.

Mutass példát egy főprogramban a fentiek használatára!

## 7. Sudoku

Adott a következő Sudoku rejtvény a következő formában: a rács elemek egész számok, ahol a '0' a ki nem töltött üres négyzetet jelképezi. Ezt a kódot másold a saját programod elejére és ezzel dolgozz!

    sudoku= [
        [0, 3, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 1, 9, 5, 0, 0, 0],
        [0, 0, 8, 0, 0, 0, 0, 6, 0],
        [8, 0, 0, 0, 6, 0, 0, 0, 0],
        [4, 0, 0, 8, 0, 0, 0, 0, 1],
        [0, 0, 0, 0, 2, 0, 0, 0, 0],
        [0, 6, 0, 0, 0, 0, 2, 8, 0],
        [0, 0, 0, 4, 1, 9, 0, 0, 5],
        [0, 0, 0, 0, 0, 0, 0, 7, 0]
    ]

A Sudoku rejtvény kitöltése során egy számjegy csak egyszer szerepelhet egy sorban, egy oszlopban illetve egy 3x3 résztáblában.

Pl. a 8. sor 8. oszlopába csak a 3 számjegy kerülhet, mert az 1,4,5,9 a 8. sorban, a 6,7,8 a 8. oszlopban, a 2 pedig a 3x3-as résztáblázatban szerepel.

- Írj függvényt `sorban` néven, ami megkapja a táblát, egy sor indexet és egy számot, majd visszaadja logikai értékként, hogy ez a szám szerepel-e a megadott sorban.
- Írj függvényt `oszlopban` néven, ami az első függvényhez hasonlóan megkapja a táblát, egy oszlop indexet, és egy számot, majd visszaadja, hogy a szám szerepel-e a megadott oszlopban.
- Írj függvényt `resztablaban` néven, ami megkapja a táblát, egy sor ill. oszlop indexet és egy számot és visszaadja logikai értékként, hogy a beírandó szám szerepel-e az adott pozícióhoz tartozó 3x3-as résztáblában vagy sem.
- A fenti függvények használatával írj egy `beirhato` függvényt, ami kap egy táblát, egy sor ill. oszlop indexet és egy számot és visszaadja logikai értékként, ha az adott szám beírható-e.
- Írj main függvényt, amelyben bekérsz a felhasználótól egy sor és oszlop számot, "hagyományosan" egytől kilencig sorszámozva és ha az üres, a `beirhato` függvény használatával kiírod, milyen számokat lehetséges oda beírni! Ha nem helyesek a koordináták adjon hibaüzenetet! Ha az előző függvényeket valamelyikét esetleg nem tudtad megírni, írj oda egy `return True` törzset és akkor az ehhez a részfeladathoz tartozó pontszámot megszerezheted.

Példa:

    Sor? 5
    Oszlop? 5
    Beírható: 3 5 7

## 8. Faktoriálisprím

A faktoriálisprímek olyan prímszámok, melyek eggyel kisebbek vagy nagyobbak egy faktoriálisnál (p = n!±1 prímszám). Az első néhány faktoriálisprím: 2 (0! + 1 vagy 1! + 1), 3 (2! + 1), 5 (3! − 1), 7 (3! + 1), 23 (4! − 1), 719 (6! − 1)

Írj programot, ami kiírja az első n faktoriális prímet!

Vigyázz, a számítási igény nagy lehet, óvatosan közelíts!

Példa:

    1. faktoriálisprím: 2
    2. faktoriálisprím: 3
    3. faktoriálisprím: 5
    4. faktoriálisprím: 7
    5. faktoriálisprím: 23
    6. faktoriálisprím: 719
    7. faktoriálisprím: 5039

## 9. Fapados

A repülőgépen hat oszlopban (ABCDEF) és 30 sorban vannak az ülések. Egy ülést a sor száma és az oszlop betűjele azonosítja, pl. a 12F a 12. sorban lévő, jobboldali ablak melletti ülést jelenti.

A foglalásokat egy fájlban tároljuk, a következő formátumban: hat karakteres foglalás azonosító, kettőspont, majd a kiosztott ülések vesszővel elválasztva.

    QWERTY:9A,9B,9C,10A,10B
    BILLIG:8A,8B,8C
    ...

A foglalásokat a programban tárold egy szótárban, amelynek kulcsa a foglalás azonosító, értéke pedig a lefoglalt ülőhelyek listája!

A programod feladata az, hogy azon kedves utasok számára, akik nem hajlandók fizetni külön az ülés kiválasztásáért, foglalásonként véletlenszerűen rendelj hozzá a szabad ülések közül, amíg lehetséges.

A program induláskor olvassa be a foglalásokat egy fájlból, majd olvasson a bemenetéről foglalási azonosítót és darabszámot egészen az üres sorig. Ha lehetséges, rendeljen hozzá véletlenszerűen üléseket a foglaláshoz, majd mentse el. Ha már nincs elegendő ülőhely, adjon hibaüzenetet!

### Példa

    ELSOFO 1
    15A
    MASODI 3
    6A 12D 16E
    TULSOK 200
    Túlfoglalás: kért 200, szabad helyek 176

## 10. Fapados 2

A feladat ugyanaz, mint az előző, de egyrészt jól ültesd szét a kedves utasokat, nehogy egy sorba kerüljenek, másrészt, amíg van középső ülés (B vagy E) addig olyat kapjanak! Hátha kinyitják a pénztárcát :-)

## 11. Statisztika bináris fával

Egy szövegfájlban egész számok találhatók, soronként egy darab. Készíts programot, amely bináris fa használatával statisztikát készít, azaz megszámolja, hogy a parancssori argumentumként megadott fájlban melyik egész szám hányszor fordult elő. Ha nincs parancsorban fájl megadva, adjon hibajelzést! A beolvasás legyen hibabiztos, az egész számként nem értelmezhető bemenetet a program hagyja figyelmen kívül!

Az eredményt a példaként megadott formátumhoz hasonlóan írd ki, a számok szerint növekvő sorrendben! Teszt adatokat pl. a 11. heti feladatok között találsz.

Példa:

    statisztika.py adatok.txt

    3816:       1 db
    3817:       4 db
    3818:      11 db
    3819:      62 db
    3820:     136 db
    3821:     344 db
    3822:     699 db
    3823:    1230 db
    3824:    2037 db
    3825:    2922 db
    3826:    3265 db
    3827:    3786 db
    3828:    2951 db
    3829:    2770 db
    3830:    1888 db
    3831:    1239 db
    3832:     665 db
    3833:     367 db
    3834:     149 db
    3835:      65 db
    3836:      22 db
    3837:       8 db
    3838:       2 db