Poznámky k téme

Cykly

~20 min čítania24 príkladov na spustenie

Každý príklad si môžeš spustiť priamo tu – a potom upraviť kód a skúsiť, čo sa zmení. Tvoj kód beží iba v tomto prehliadači, v izolovanom prostredí bez prístupu k internetu či k tvojmu účtu.

Počítače sú silné v tom, že vedia tú istú činnosť zopakovať tisíckrát bez chyby. Opakovanie sa v programe zapisuje cyklom. Python má dva druhy cyklov: for – keď vieme, koľkokrát (alebo pre ktoré hodnoty) sa má niečo zopakovať, a while – keď sa má opakovať, kým platí podmienka.

Čo sa naučíš

  • opakovať príkazy cyklom for s funkciou range,
  • použiť cyklus while a vyhnúť sa nekonečnému cyklu,
  • počítať pomocou počítadla a akumulátora (súčet, súčin, priemer),
  • predčasne ukončiť cyklus (break) alebo preskočiť krok (continue),
  • písať vnorené cykly a trasovať, čo cyklus robí.

1Cyklus for a funkcia range

Python
for i in range(5):
print("Opakovanie číslo", i)
print("Hotovo")

Výstup:

Opakovanie číslo 0
Opakovanie číslo 1
Opakovanie číslo 2
Opakovanie číslo 3
Opakovanie číslo 4
Hotovo

Ako to funguje:

  • range(5) vytvorí čísla 0, 1, 2, 3, 4 – päť čísel, začína sa nulou a 5 už nepatrí do výsledku.
  • Premenná i (riadiaca premenná cyklu) postupne nadobudne každú z týchto hodnôt.
  • Pre každú hodnotu sa vykoná telo cyklu – odsadený blok pod riadkom s dvojbodkou.
  • Neodsadený riadok print("Hotovo") sa vykoná až po skončení cyklu, raz.

1.1Tri podoby range

ZápisČíslaVýznam
range(n)0, 1, …, n−1n čísel od nuly
range(od, do)od, od+1, …, do−1do už nepatrí
range(od, do, krok)od, od+krok, …kým sme pred do
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> list(range(2, 8))
[2, 3, 4, 5, 6, 7]
>>> list(range(1, 11, 3))
[1, 4, 7, 10]
>>> list(range(10, 0, -2))
[10, 8, 6, 4, 2]
>>> list(range(5, 1))
[]

(list(...) tu iba ukazuje, ktoré čísla range vytvorí.) So záporným krokom sa počíta smerom dole; ak je od už „za“ hranicou, range je prázdny a telo cyklu sa nevykoná ani raz.

1.2Riadiaca premenná v tele cyklu

Python
for i in range(1, 6):
print(i, "na druhú je", i ** 2)

Výstup:

1 na druhú je 1
2 na druhú je 4
3 na druhú je 9
4 na druhú je 16
5 na druhú je 25

Ak hodnotu riadiacej premennej nepotrebuješ, zvykne sa pomenovať _:

Python
for _ in range(3):
print("Hip hip hurá!")

Výstup:

Hip hip hurá!
Hip hip hurá!
Hip hip hurá!

1.3Výpis do riadku

Vďaka end=" " vypíšeš hodnoty z cyklu vedľa seba. Prázdny print() po cykle ukončí riadok:

Python
for i in range(10, 0, -1):
print(i, end=" ")
print()
print("Štart!")

Výstup:

10 9 8 7 6 5 4 3 2 1 
Štart!

1.4for cez text a zoznam

Cyklus for vie prechádzať aj znaky reťazca alebo prvky zoznamu – nielen čísla z range:

Python
for znak in "Python":
print(znak, end="-")
print()
for ovocie in ["jablko", "hruška", "slivka"]:
print("Ovocie:", ovocie)

Výstup:

P-y-t-h-o-n-
Ovocie: jablko
Ovocie: hruška
Ovocie: slivka

Viac v témach Reťazce a Zoznamy.

2Cyklus while

Cyklus while opakuje svoje telo, kým platí podmienka. Podmienka sa testuje pred každým opakovaním; ak neplatí hneď na začiatku, telo sa nevykoná ani raz.

Python
n = 1
while n < 100:
print(n, end=" ")
n = n * 2
print()
print("Prvá mocnina dvoch nad 100:", n)

Výstup:

1 2 4 8 16 32 64 
Prvá mocnina dvoch nad 100: 128

Telo cyklu musí niečo meniť tak, aby podmienka raz prestala platiť – tu sa n zdvojnásobuje. Ak by sme riadok n = n * 2 vynechali, podmienka by platila stále a program by sa nikdy neskončil (nekonečný cyklus). Spustený program vtedy zastavíš klávesmi Ctrl + C alebo tlačidlom Stop.

2.1while so vstupom

while je ideálny, keď dopredu nevieme, koľko opakovaní bude – napríklad pri čítaní čísel, kým niekto nezadá nulu:

Python
sucet = 0
cislo = int(input("Číslo (0 = koniec): "))
while cislo != 0:
sucet += cislo
cislo = int(input("Číslo (0 = koniec): "))
print("Súčet:", sucet)

Výstup:

Číslo (0 = koniec): 12
Číslo (0 = koniec): 7
Číslo (0 = koniec): 30
Číslo (0 = koniec): 0
Súčet: 49

Prvé číslo načítame pred cyklom, aby mala podmienka čo testovať; ďalšie čísla čítame na konci tela cyklu.

2.2for alebo while?

  • for – keď vieš, koľkokrát sa má cyklus vykonať, alebo prechádzaš prvky (čísla z range, znaky textu, prvky zoznamu).
  • while – keď počet opakovaní závisí od niečoho, čo sa ukáže až počas behu (kým sa nezadá 0, kým číslo nie je 1, kým nenájdeme hľadanú hodnotu).

Každý for cyklus s range sa dá prepísať na while:

Python
i = 0 # začiatok
while i < 5: # podmienka
print(i, end=" ")
i += 1 # krok
print()

Výstup:

0 1 2 3 4 

3Počítadlo a súčet

Veľmi časté úlohy v cykloch sú spočítať prvky s nejakou vlastnosťou a sčítať hodnoty. Postup je vždy rovnaký:

  1. pred cyklom premennú vynuluj (pocet = 0, sucet = 0),
  2. v cykle ju zväčšuj (pocet += 1, sucet += x),
  3. po cykle výsledok použi.
Python
sucet = 0
pocet_parnych = 0
for x in range(1, 21):
sucet += x
if x % 2 == 0:
pocet_parnych += 1
print("Súčet 1 až 20:", sucet)
print("Párnych čísel:", pocet_parnych)

Výstup:

Súčet 1 až 20: 210
Párnych čísel: 10

Pri súčine sa začína jednotkou, nie nulou (nula by všetko vynulovala). Príklad: faktoriál 6! = 1 · 2 · 3 · 4 · 5 · 6.

Python
faktorial = 1
for i in range(1, 7):
faktorial *= i
print("6! =", faktorial)

Výstup:

6! = 720

3.1Priemer z načítaných čísel

Python
n = int(input("Koľko čísel? "))
sucet = 0
for _ in range(n):
sucet += int(input())
print(f"Priemer: {sucet / n:.2f}")

Výstup:

Koľko čísel? 5
8
10
7
9
6
Priemer: 8.00

3.2Trasovanie cyklu

Pri trasovaní zapisuj hodnoty premenných po každom opakovaní. Program sucet = 0, for i in range(1, 5): sucet += i:

opakovanieisucet po kroku
pred cyklom–0
1.11
2.23
3.36
4.410

4break a continue

  • break cyklus okamžite ukončí – pokračuje sa prvým príkazom za cyklom.
  • continue preskočí zvyšok aktuálneho opakovania a pokračuje ďalším.
Python
for i in range(1, 10):
if i == 6:
break
if i % 2 == 0:
continue
print(i)

Výstup:

1
3
5

Čísla 2 a 4 sa preskočili (continue), pri 6 cyklus skončil (break).

4.1while True a break

Častý vzor: cyklus „navždy“, ktorý sa ukončí break, keď nastane podmienka. Hodí sa, keď sa podmienka ukončenia dá otestovať až uprostred tela:

Python
while True:
heslo = input("Heslo: ")
if heslo == "Tajne123":
break
print("Nesprávne, skús znova.")
print("Prístup povolený.")

Výstup:

Heslo: ahoj
Nesprávne, skús znova.
Heslo: heslo
Nesprávne, skús znova.
Heslo: Tajne123
Prístup povolený.

4.2Hľadanie s break

Python
# prvé číslo väčšie ako 100, ktoré je deliteľné 7 aj 9
n = 101
while True:
if n % 7 == 0 and n % 9 == 0:
break
n += 1
print(n)

Výstup:

126

5Vnorené cykly

V tele cyklu môže byť ďalší cyklus. Vnútorný cyklus prebehne celý pri každom opakovaní vonkajšieho. Ak vonkajší beží 3-krát a vnútorný 4-krát, telo vnútorného sa vykoná 3 · 4 = 12-krát.

Python
for riadok in range(1, 4):
for stlpec in range(1, 5):
print(riadok * stlpec, end="\t")
print()

Výstup:

1	2	3	4	
2	4	6	8	
3	6	9	12	

Takto vznikla malá tabuľka násobenia: vonkajší cyklus určuje riadok, vnútorný vypíše stĺpce jedného riadku a print() riadok ukončí.

5.1Obrazce zo znakov

Python
n = 5
for i in range(1, n + 1):
print("*" * i)

Výstup:

*
**
***
****
*****

Počet hviezdičiek v riadku závisí od čísla riadku. Pyramída potrebuje aj medzery pred hviezdičkami:

Python
n = 4
for i in range(1, n + 1):
print(" " * (n - i) + "*" * (2 * i - 1))

Výstup:

   *
  ***
 *****
*******

Pri obrazcoch si najprv napíš do tabuľky, koľko medzier a znakov má mať každý riadok, a hľadaj vzťah s číslom riadku i.

6Riešené úlohy

6.1Ciferný súčet

Zadanie: Načítaj prirodzené číslo a vypíš súčet jeho cifier.

Riešenie: Poslednú cifru získame ako n % 10, potom ju „odtrhneme“ celočíselným delením n // 10. Opakujeme, kým číslo nie je 0 – počet cifier dopredu nepoznáme, preto while.

Python
n = int(input("Číslo: "))
sucet = 0
while n > 0:
sucet += n % 10
n = n // 10
print("Ciferný súčet:", sucet)

Výstup:

Číslo: 90417
Ciferný súčet: 21
nn % 10sucet
9041777
904118
904412
90012
9921
0–koniec

6.2Collatzova postupnosť

Zadanie: Začni od zadaného čísla. Ak je párne, vydeľ ho dvoma; ak je nepárne, vynásob ho tromi a pripočítaj 1. Opakuj, kým nedostaneš 1. Vypíš postupnosť a počet krokov.

Riešenie: Počet krokov nepoznáme, preto while n != 1. Matematici predpokladajú, že postupnosť sa vždy dostane k 1 (Collatzova hypotéza), dokázané to však zatiaľ nie je.

Python
n = int(input("Začiatok: "))
kroky = 0
print(n, end=" ")
while n != 1:
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
kroky += 1
print(n, end=" ")
print()
print("Počet krokov:", kroky)

Výstup:

Začiatok: 6
6 3 10 5 16 8 4 2 1 
Počet krokov: 8

6.3Prevod do dvojkovej sústavy

Zadanie: Načítaj prirodzené číslo a vypíš ho v dvojkovej sústave.

Riešenie: Číslo opakovane delíme dvoma a zapisujeme zvyšky. Zvyšky čítané odzadu tvoria zápis v dvojkovej sústave, preto každú novú cifru pridáme na začiatok textu.

Python
n = int(input("Číslo: "))
dvojkovo = ""
while n > 0:
dvojkovo = str(n % 2) + dvojkovo
n = n // 2
print(dvojkovo)

Výstup:

Číslo: 13
1101

Kontrola: 1101₂ = 8 + 4 + 0 + 1 = 13. Python to vie aj sám: bin(13) je '0b1101'.

6.4Fibonacciho postupnosť

Zadanie: Vypíš prvých 12 členov Fibonacciho postupnosti: 1, 1, 2, 3, 5, 8, … (každý ďalší člen je súčtom dvoch predchádzajúcich).

Riešenie: Pamätáme si posledné dva členy a a b. V každom kroku vypíšeme a a posunieme sa: nové a je staré b, nové b je súčet. Zápis a, b = b, a + b vypočíta pravú stranu celú naraz, takže sa stará hodnota a nestratí.

Python
a, b = 1, 1
for _ in range(12):
print(a, end=" ")
a, b = b, a + b
print()

Výstup:

1 1 2 3 5 8 13 21 34 55 89 144 

6.5Hádanie čísla

Zadanie: Počítač si myslí číslo od 1 do 100. Ty hádaš a program odpovedá „viac“ alebo „menej“, kým neuhádneš. Na konci vypíše počet pokusov.

Riešenie: Náhodné číslo vyberie funkcia random.randint (téma Modulárny program). Pre ukážku je nastavené random.seed, aby bol príklad zakaždým rovnaký – v hre to nerob. Počet pokusov nepoznáme, preto while.

Python
import random
​
tajne = random.randint(1, 100)
pokusy = 0
tip = 0
while tip != tajne:
tip = int(input("Tvoj tip: "))
pokusy += 1
if tip < tajne:
print("Viac.")
elif tip > tajne:
print("Menej.")
print("Uhádnuté na", pokusy, "pokusov!")

Výstup:

Tvoj tip: 50
Menej.
Tvoj tip: 25
Viac.
Tvoj tip: 37
Viac.
Tvoj tip: 43
Menej.
Tvoj tip: 40
Viac.
Tvoj tip: 42
Uhádnuté na 6 pokusov!

6.6Prvočísla do n

Zadanie: Vypíš všetky prvočísla menšie ako 50.

Riešenie: Prvočíslo je číslo väčšie ako 1, ktoré je deliteľné iba 1 a sebou samým. Pre každé číslo spočítame jeho delitele od 2 po n − 1; vnútorný cyklus ukončíme break, len čo nájdeme prvého delitela.

Python
for n in range(2, 50):
prvocislo = True
for d in range(2, n):
if n % d == 0:
prvocislo = False
break
if prvocislo:
print(n, end=" ")
print()

Výstup:

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 

Premenná prvocislo je príznak (flag): na začiatku predpokladáme, že číslo je prvočíslo, a ak nájdeme delitela, príznak zmeníme. Rýchlejší test (stačí skúšať delitele po odmocninu) je v téme Algoritmy.

7Časté chyby

  • Chyba „o jednu“: range(1, n) končí pri n − 1. Pre čísla od 1 do n vrátane použi range(1, n + 1).
  • Nekonečný while: v tele cyklu sa nemení premenná z podmienky (alebo sa mení zlým smerom).
  • Zlé odsadenie: príkaz, ktorý patrí za cyklus, je odsadený – vykoná sa pri každom opakovaní. Alebo naopak: príkaz, ktorý má byť v cykle, odsadený nie je.
  • Vynulovanie v cykle: sucet = 0 napísané vo vnútri cyklu vynuluje súčet pri každom opakovaní. Patrí pred cyklus.
  • Zmena riadiacej premennej vo for: priradenie do i v tele cyklu nezmení, ktorá hodnota príde v ďalšom kroku – for si ju vezme z range.
Python
for i in range(3):
print("i =", i)
i = 100 # nemá vplyv na ďalší krok

Výstup:

i = 0
i = 1
i = 2

Zhrnutie

  • for i in range(...): range(n) je 0 až n−1, range(od, do) končí pred do, tretí argument je krok (aj záporný).
  • while podmienka: – opakuje, kým podmienka platí; telo musí podmienku raz „pokaziť“.
  • for pre známy počet alebo prechádzanie prvkov; while pre neznámy počet opakovaní.
  • Počítadlo a súčet: vynulovať pred cyklom, zväčšovať v cykle; súčin začína od 1.
  • break ukončí cyklus, continue preskočí zvyšok kroku; while True + break je bežný vzor.
  • Vnorený cyklus prebehne celý pri každom kroku vonkajšieho.

Úlohy na precvičenie

  1. Vypíš násobky čísla 7 menšie ako 100 do jedného riadku.
  2. Načítaj n a vypíš súčet 1² + 2² + … + n².
  3. Načítavaj čísla, kým nepríde záporné; potom vypíš najväčšie z nich a ich počet.
  4. Vypíš celú malú násobilku (10 × 10) zarovnanú do stĺpcov.
  5. Načítaj číslo a vypíš počet jeho cifier (bez prevodu na text).
  6. Vypíš „obrátenú“ pyramídu z hviezdičiek s n riadkami.

Prečítané?

Over si, čo si z poznámok pamätáš, na krátkych úlohách k téme.