Nagy rendrakás a ciklusok között

Szóval alapvetően négy ciklusfélét ismerünk. Ezek közül eddig háromról beszéltünk. De majd most!

NYILATKOZAT: Ez a cikk hosszabb, mint eddig bármelyik, de legalább egyszerűbb elolvasni, és ha végzel vele, mindent tudni fogsz a ciklusokról. Ja, nem…

Feltételes ciklusok

Az ilyen ciklusoknál az ismétlődés feltételhez kötött. Ha a feltétel teljesül, van ismétlődés, ha nincs, akkor bizony nincs. Kettő ilyen ciklus létezik, az elöltesztelő és a hátultesztelő.

1. Elöltesztelő feltételes ciklus, röviden: elöltesztelő ciklus.

Azért elöltesztelő, mert a ciklus elején vizsgáljuk meg, hogy belépünk-e a ciklusba. Ilyen a Python while-ciklusa, meg általában a nyelvek while-ciklusai. Minthogy már volt róla külön lecke, csak röviden emlékszünk meg róla.

Hókuszpók, Hami és Sziamiaú

Hidd el, nincs jobb az elöltesztelő ciklusnál
– nyilatkozza a fekete ruhás szoftverfejlesztő

Mondatszerű leírásban (pszeudokódban) ilyen:

ciklus amíg feltétel  #más estben: "ciklus, ha feltétel", esetleg "mialatt feltétel", de akár "ismételd, amíg feltétel" is lehet
    egyik utasítás
    másik utasítás
ciklus vége

Konkrét feladattal: adjunk a felhasználónak egy muffint, amíg azt nem mondja, hogy elég.

elég := "n"  #"Legyen egyenlő"-nek olvassuk. Lehet sima egyenlőségjel is.
ciklus amíg elég != "i"   #lehet áthúzott egyenlőségjel is, vagy akár szöveggel írva
    ki: "tessék, egy muffin"
    ki: "elég volt? (i/n)"
    be elég
ciklus vége

Egy lehetséges Python nyelvű megvalósítás:

elég = 'n'

while elég != 'i':
    print('tessék, egy muffin')
    elég = input('elég volt? (i/n)')

2. Hátultesztelő feltételes ciklus, röviden: hátultesztelő ciklus

Attól hátultesztelő, hogy a ciklus végén megnézzük, hogy meg kell-e csinálni a ciklust még egyszer. Egy alkalommal biztosan lefut, mert az elején ész nélkül belelépünk. A végén egyes nyelvekben azt kell megadni, hogy milyen feltétel teljesülése mellett maradunk a ciklusban, másoknál meg azt, hogy milyen feltétel teljesülése mellett lépünk ki.

Mondatszerű leírásban (pszeudokódban) ilyen:

ciklus
    egyik utasítás
    másik utasítás
ciklus amíg feltétel # vagy "ismételd amíg feltétel"

Konkrét feladatban: kérdezzük meg a felhasználót, hogy 5+5 mennyi. Addig kérdezgessük, amíg el nem találja.

ciklus
    ki: "mennyi 5+5?"
    be eredmény
ciklus amíg eredmény != 10 #itt a bennmaradás feltételét adtuk meg.

Egy lehetséges Python-nyelvű megvalósítás: na ilyen nincs. A Pythonnak nincs hátultesztelő ciklusa. Egyszerűen nincs. Nem kell azonnal torkon szúrni magunkat: Minden hátultesztelő ciklus átírható elöltesztelővé. Lássuk a mostanit:

eredmény := üres változó
ciklus amíg eredmény != 10
    ki: "mennyi 5+5?"
    be eredmény
ciklus vége

Ezt meg már simán megírod Pythonban, ugye?

Két Hókuszpók

A bal oldali fekete ruhás szoftverfejlesztő szerint a hátultesztelő ciklus jobb, mint az elöltesztelő. A jobb oldali fekete ruhás szoftverfejlesztő szerint a bal oldali fekete ruhás szoftverfejlesztő hülye.

Na, ennyit a feltételes ciklusokról.

3. Bejárós ciklus

Erről is volt már szó külön leckében. Egy gyűjteményes adattípusú objektum – más szóval: tároló – elemeit lehet vele bejárni, végigjárni. Bizonyos helyeken ezt a ciklust is elöltesztelő ciklusnak tekintik, hiszen elöl dől el, hogy végigjártuk-e már az objektum összes elemét. Ebben a ciklusban van ciklusváltozó, amely mindig a tároló épp aktuális elemét tartalmazza.

Három Hókuszpók, az egyik fejre esett

“Sok ciklust bejártam már” – mondja a bal oldali fekete ruhás szoftverfejlesztő. A vele szemben lévő fekete ruhás szoftverfejlesztő érdeklődve hallgatja. A harmadik fekete ruhás szoftverfejlesztő közben békésen szunyókál.

Mondatszerű leírásban (pszeudokódban) ilyen:

ciklus Tömb minden Elem-ére: #a Tömb egy gyűjteményes adattípus. A legtöbb nyelvben ilyen van. Nekünk főleg listánk van, ami bizony nagyon jó.
    egyik parancs
    másik parancs
ciklus vége

Konkrét feladatban: Írjuk ki az éttermi menü minden elemét!

ciklus menü minden fogás-ára: #másutt: ciklus minden fogás-ra a menü-ben
    ki: fogás #nem kifogás:))
ciklus vége

Egy lehetséges Python-nyelvű megvalósítás:

for fogás in menü: #ahol a menü egy már létező lista, vagy hasonló
    print(fogás)

Vannak olyan nyelvek, amikben nincs bejárós ciklus. A bejárós ciklusok átírhatók akár számlálós, akár feltételes ciklusokká, de ezt majd máskor beszéljük meg, mert a listákról még nem tudunk ehhez eleget.

4. Számlálós ciklus

Ilyen sincs a Pythonban, de a múltkor megtanultuk szimulálni. Ez azt is jelenti, hogy a számlálós ciklusok átírhatók bejárós ciklusokká. De átírhatók feltételes ciklusokká is, ez sokkal gyakoribb. Ez is felfogható elöltesztelő ciklusnak, amennyiben az elején nézi meg a program, hogy elértük-e már a program felső határát.

Három Hókuszpók és Sziamiaú

A piros emlősállat megszakítja a fekete ruhás szoftverfejlesztők szekvenciáját

Mondatszerű leírásban (pszeudokódban) ilyen:

ciklus i := a-tól b-ig c lépésközzel
    egyik parancs
    másik parancs
ciklus vége

(Ja: azért látunk majdnem mindig i-t az ilyen ciklusok ciklusváltozójakért, mert egy régi programozási nyelvben, a FORTRAN-ban az egész számokat csak az I, J, K, L, M és N nevű változók tartalmazhatták, márpedig a számlálós ciklus ciklusváltozója mindig egész szám. Az i használata ma már csak szokás, nem kötelező.)

Konkrét feladatban: Írjuk ki az első 10 negatív szám köbét!

ciklus i := -1-től -10-ig -1 lépésközzel
    ki: i köbe
ciklus vége

Egy lehetséges Python-nyelvű megvalósítás: bejárós ciklussá alakítjuk.

for i in range(-1, -11, -1): #ugye figyelsz a -11-re a -10 helyett?!
    print(i**3)

Említettem, hogy átalakíthatjuk feltételes ciklussá, ami, ahogy már mondtam, a Pythonban csak elöltesztelő ciklus lehet. Lássuk:

i = -1
ciklus amíg i >= -10
    ki: i köbe
    i := i - 1
ciklus vége

És ezt is megírod simán, igaz?

Lássunk egy rövid videót, mert ebben a hosszúra nyúlt posztban az még nem volt:

És akkor némi angolozás, meg nevezéktan:

  • A feltételes ciklus neve angolul condition-controlled loop.
  • Az elöltesztelő ciklus angolul while loop, azaz egyszerűen csak a kulcsszóról van elnevezve, de lesz még ilyen:
  • A hátultesztelő ciklus angolul do-while loop, esetleg repeat-until loop.
  • A bejárós ciklust magyarul iteráló ciklusnak is szokás nevezni. De ez nem is magyarul van. Naés! Annál szakszerűbb(nek hangzik)!! 😉
  • A bejárós ciklus angolul collection-controlled loop. De ritkán hívják így, lásd a következő pontot.
  • A bejárós ciklus tudtommal csak a Pythonban for-ciklus, angolul a más programozási nyelvekben szokásos kulcsszaváról elnevezve foreach loop a közkeletű neve.
  • A számlálós ciklus angolul count-controlled loop, de leginkább a más programozási nyelvekben szokásos kulcsszaváról elnevezve emlegetik: for loop.
  • Csak a számlálós és a bejárós ciklusban van ciklusváltozó.

Feladatok

F0016a: Rajzold ki az alábbi ábrát ciklus használatával a konzolodra! Melyik ciklust érdemes használni? Az “o”-betűk számát tárold változóban! (Megoldás az expand source-ra kattintva.) (Ez, és a g. feladatig minden innen származik. Köszönet érte!)

F0016a ábra


hányszor = 5

for _ in range(hányszor):
    print('o ', end='')
print('')

A kódban látsz egy érdekes dolgot: a ciklusváltozó neve alávonás (“_”). Ugye a változónevekben a betűkön és a számokon kívül olyankor szokás (érted, nem kötelező, csak szokás) az alávonást használni, ha igazából nem használjuk fel a ciklusváltozó értékét. Azaz az előző programban jól nem használtuk, de például a következő program így nem oké (legalábbis a szokásoknak nem felel meg, futni hibátlanul fog), mert itt használjuk a ciklusváltozó értékét: kiírjuk, sőt a négyzetét is kiírjuk.


meddig = 5
for _ in range(meddig):
    print(_, _**2)

F0016b: Rajzold ki az alábbi ábrát ciklus használatával a konzolodra! A sorok és az oszlopok számát tárold változóban! Elsőként írj pszeudokódot, majd valósítsd meg! (Megoldás itt.)

F0016b feladat ábra

F0016c: Rajzolj ciklus használatával az alábbi ábrán is látható szakaszt a konzolra! A szakasz hosszát kérd a felhasználótól! Először írd meg mondatszerű leírással a programot, aztán valósítsd is meg! (Megoldás itt.)

F0016c feladat ábrája

F0016d: Rajzolj több ciklus használatával az alábbi ábrán is látható téglalapot a konzolra! A téglalap szélességét és magasságát tárold változóban! Először írd meg mondatszerű leírással a programot, aztán valósítsd is meg! (Megoldás itt.)

F0016d feladat ábrája

F0016e: Rajzolj több ciklus használatával az alábbi ábrán is látható háromszöget a konzolra! A háromszög emeleteinek számát kérd a felhasználótól! Először írd meg mondatszerű leírással a programot, aztán valósítsd is meg! (Megoldás itt.)

F0016e feladat ábrája

F0016f: Rajzolj több ciklus használatával az alábbi ábrán is látható háromszöget a konzolra! Először írd meg mondatszerű leírással a programot, aztán valósítsd is meg! (Megoldás itt.)

F0016f feladat ábrája

F0016g: Rajzolj több ciklus használatával az alábbi ábrán is látható foltokat a konzolra! A foltok szélessége az ábrán a=8, magassága b=4. Egymás mellett m=3 folt van és egymás alatt n=2 sor található. A négy paramétert tárold változóban! (Megoldás itt.)

F0016g feladat ábrája

 

Előzőleg megismerkedtünk a range() függvénnyel és a számlálós ciklussal. Legközelebb a lista adattípussal mélyítjük el ismeretségünket.

Nagy rendrakás a ciklusok között” bejegyzéshez 30ozzászólás

  1. Ennél a résznél, direkt van úgy, hogy az igen (kérek még) esetében azonnal leálljon a ciklus?

    “Egy lehetséges Python nyelvű megvalósítás:
    elég = ‘n’

    while elég != ‘i’:
    print(‘tessék, egy muffin’)
    elég = input(‘kérsz még? (i/n)’)”

    Kedvelés

  2. Szia Raerek!

    Sokat keresgeltem, de nem talaltam igazan jo forrast a pszeudokod modszertanara, szabalyaira.
    Tudsz esetleg valami jo forrast erre vonatkozoan?

    Kedvelés

    • Nezd, a F0016D – hez irtam egy pszeudot:

      #ki : “+” \nincs sortores
      #ciklus szakasz_hossza
      #ki : “-” \nincs sortores
      #ciklus vege
      #ki : “+”

      #ciklus_1 belso_magassag
      #ki:”|” \nincs sortores
      #ciklus_2 szakasz_hossza
      #ki:”:” \nincs sortores
      #ciklus_2 vege
      #ki:”|”
      #ciklus_1 vege

      #ki: “+” \nincs sortores
      #ciklus szakasz_hossza
      #ki: “-” \nincs sortores
      #ciklus vege
      #ki: “+”

      es ez alapjan sikerult ELSORE ( 😀 ) ez:

      https://pastebin.com/d9Q8iYkF

      meg nem neztem meg a megoldasvideot, majd mindjart kiderul, te hogy irtad 😉

      De a kerdesem igazabol az lenne, hogy mit kene fejlesztenem a pszeudokod irason? (Vagy azert fogalmazol ugy, hogy “mondatszeru”, mert a leirasmodja mindegy, csak tervezzunk?)

      Kedvelés

      • Gratula! Ez a pszeudokód oké, majd ha több nyelvi eszközt ismersz, akkor térj vissza a fejlesztéséhez. Azért “mondatszerű leírás”, mert ez a név jobban leírja, hogy mi ez, mint a pszeudokód. És igen, végülis mindegy, arról szól a dolog, hogy ne azzal menjen el az időd, hogy ebből miként lesz kód, hanem először mondd meg, hogy mit akarsz csinálni.

        Kedvelés

  3. ezt ertem, viszont, nagyon sokat torom a fejem (F0016e) igy is mivel leirast nem tudok irni amig nem tudom hogy lessz belole kod.nagy a katyvasz az agyamban most, csak probalkozni tudok a koddal, irom, torlom, irom aztan egyszercsak osszeall a kep meg a haromszog persze. 😀

    Kedvelés

  4. Szia! Először is [meghajlás], fantasztikus az a munka, amit ebbe a Python-oktatásba beleraktál! Több mindennel próbálkoztam már ez ügyben, és messze ezzel jutottam el legtovább (még nem mondhatom azt, hogy végig, de azért most már bizakodom 🙂 ). Köszönöm szépen!

    Ami a hozzászólásom konkrét tárgyát illeti, egyszerűen nem megy nekem a pszeudokódon való fogalmazás. Eleve “Python-nyelven” fogalmazom meg, hogy mit akarok. Persze, le tudom írni mondatokban, hogy mit kell csinálnom (úgy, ahogy a feladat van fentebb), de hogy lefordítsam (illetve részben visszafordítsam) egy “közbenső nyelvre”, és utána tovább, az nem megy. Az f016d-nél tartok, és több energiát öltem a pszeudokódba, mint amit végül (lényegében ennek feladása után) a tényleges programozás elvitt.
    Itt a megoldásom egyébként:
    https://pastebin.com/EnLXJdiN

    Lehet, hogy nem a legszebb, de működik… Mindjárt megnézem a tiédet. 🙂

    Szóval ez a világért sem kritika, inkább egy kérdés, hogy bajba fogok-e kerülni, ha nem tanulom meg a pszeudokódot…

    Még egyszer köszönöm a munkádat!

    Kedvelés

    • Köszönöm, és szívesen:) Ami pedig a hozzászólásod konkrét tárgyát illeti, nem kell nagyon korrekt pszeudokódot írni tudni, jó az, ha addig jutsz, hogy “pörgetem az oszlopokat eddig-és-eddig, aztán kinullázom és léptetem a sort”, aztán megint pörgetem az oszlopokat”. Szóval ne izgulj:)

      Kedvelés

  5. Szia Pythonidomár!
    Nagyon jók a videók, jól is magyarázod a dolgokat, csillagos 5-ös! Köszönöm!
    Nagy rendrakás a ciklusok kozott leckénél az f16e feladat jól begyakoroltatja a for-in-range dolgot, az én megoldásom:
    ————————————
    print(‘f16e’)
    sorok = int(input(‘Hány soros legyen ez az ábrácska? ‘))
    valtozo = None
    sor = 0

    while sorok != 0:
    valtozo = sorok*2-1
    print(sor*’ ‘,valtozo*’O’,sep=”)
    sor += 1
    sorok -= 1
    ————————————
    Ezután fura volt végignézi a megoldás videót, ez kevésbé komplikált szerintem.
    Köszi a sok videót!
    Tom

    Kedvelés

    • Én köszönöm:) Mert ugye én alapvetően nem tanítottam a “betűk szorzása” műveletet, mert elég Python-specifikus, de igazán remekül kihasználtad.

      Kedvelés

  6. Szia!
    Egy picit félreértettem az F0016f feladatot és – kiindulva az előzőből – belevettem, hogy kérje be az emeletek számát 🙂
    Az eredmény ez lett:
    https://pastebin.com/irAMQxqT
    Kár, hogy csak páratlan számú emeletnél ad szép eredményt.
    Az lenne a kérdésem, hogy ilyenkor, amikor már van egy kis matekozás benne, mi a gyakorlat (melyik a Pythonosabb 🙂 )? Kiemelni néhány műveletet és az eredményét változókban tárolni és úgy használni, vagy menjen inkább az összes művelet egy kupacba? Itt az emeletek_fele változóra gondolok.

    emeletek_fele = int (emeletek / 2)
    for _ in range((emeletek_fele – abs(emeletek_fele – emelet)) + 1):

    vagy

    for _ in range((int (emeletek / 2)- abs(int(emeletek / 2) – emelet)) + 1):

    Nekem az első változat a tszbé 🙂

    Előre is köszönöm!

    Kedvelés

    • Ebben az esetben szerintem nem a pythonosság számít, hanem az, hogy _te_ hogyan tudod jobban olvasni a kódodat. Sőt, biztos, hogy több változóval tudod egy év múlva jobban olvasni, inkább úgy teszem fel, hogy nehéz-e akkor olvasnod, ha minden egybe megy. Ha nehéz, akkor használj változó-hegyeket. Ha nem gond, akkor mehet egybe.

      Kedvelik 1 személy

  7. Először is, köszi a munkádat!

    Ez volt az első lecke amiben keményen megszenvedtem a feladatokkal, pontosabban az e, és az f-el, kis csalás nélkül nem is ment. Az utolsót viszont 1 perc alatt megírtam elsőre, ki érti ezt? 😀

    Kedvelés

  8. Sziasztok
    Én a feladatokat while ciklussal oldottam meg, a for- ral valahogy nem látom át. Pl az f feladat:
    oszlopok_szama = 10 #ez módosítható,a nyíl hossza
    sorok_szama = (oszlopok_szama*2)-1
    szamlalo = oszlopok_szama – 1
    while szamlalo != 0:
    print(szamlalo*’ ‘+(oszlopok_szama-szamlalo)*’O’)
    szamlalo -=1
    print(oszlopok_szama*’O’)
    while szamlalo != oszlopok_szama-1:
    szamlalo += 1
    print(szamlalo*’ ‘+(oszlopok_szama-szamlalo)*’O’)

    Ezek az egymásba ágyazott for ciklusok még nem tiszták. hogy lépkednek ezek és hová? 🙂

    Kedvelés

    • utolsó feladat,közel két óra után összeállt, de úgy látom még mindig nem az igazi:
      magassag = 4
      szelesseg = 8
      sorok = 2
      oszlopok = 3

      for i in range(sorok):
      for i in range(magassag):
      print(oszlopok*(szelesseg*’O’+’ ‘))
      print(‘ ‘)

      Kedvelés

  9. F0016e:
    csaltam, mert a videót is megnéztem, és az egyik hozzászóló megoldását használtam, kicsit módosítva…
    de ez elég egyszerű, és működik, kivéve pl ha az input = 89, akkor a háromszög közepe körül van egy törés… ??

    emeletek = int(input(‘Hány emelet magas legyen? ‘))

    for emelet in range(emeletek):
    oszlop = 2 * (emeletek – emelet) – 1
    print(emelet * ‘ ‘, oszlop * ‘O’, sep=”)

    Kedvelés

  10. Szervusztok!

    16. e-hez egy javaslat – igaz egy ciklussal:

    emelet = int(input(‘Add meg a háromszög szintjeinek számát!\n.: ‘))
    szóköz=emelet
    for _ in range(emelet,0,-1):
    print(‘o’*(emelet*2-1))
    emelet-=1
    print(‘ ‘*(szóköz-emelet),end=”)

    Kedvelés

  11. Sziasztok,
    Én a F0016d-re a következő megoldást szültem:

    print(‘Ez a program egy karakteres téglalap / négyzet rajzoló’)
    szélesség = int(input(‘Kérlek add meg a szélességet: ‘))
    magasság = int(input(‘Kérlek add meg a magasságot: ‘))

    kezdo_karakter = ”
    belso_karakter = ”

    for sor in range(magasság):
    if sor == 0 or sor == magasság-1:
    kezdo_karakter = ‘+’
    belso_karakter = ‘-‘
    else:
    kezdo_karakter = ‘|’
    belso_karakter = ‘:’
    for oszlop in range(szélesség):
    if oszlop == 0 or oszlop == szélesség-1:
    print(kezdo_karakter, end=”)
    else:
    print(belso_karakter, end=”)
    print(”)

    Kedves raerek,
    Fantasztikus munkát végzel itt a Pythonidomár-on!
    Igényes, lényegretörő és jól felépített az egész, továbbá nagyon jól is magyarázol a videókban. Tetszik, hogy nem csak kizárólag a Pythonra koncentrálsz, hanem úgy általánosságban programozni tanítasz.
    Remélem, újra erőt gyűjtesz és lesz még folytatása az oldalnak.
    Egy egyenlőre nagyon lelkes 46 éves, 4 gyermekes apuka, aki újra kedvet kapott a programozáshoz. Részben a kicsi fia miatt. 🙂
    Üdv: MS

    Kedvelés

    • Hát, nagyon köszönöm a méltatást, igen jóleső. A kor egyébként nálam is ugyanaz, a gyerekek száma csak a fele. És igen, én is remélem. Mindig úton van, de mindig közbeszól valami. A témákat kitartóan gyűjtögetem azért:)

      Kedvelés

Hozzászólás