5. Угнежђене петље¶
У овој лекцији показујемо:
- како раде угнежђене петље,
- како се користе угнежђене петље за исписивање табела са подацима, и
- како се обрађују подаци представљени табелама.
5.1. Петља у петљи¶
Када се у телу петље нађе друга петља, као у овом примеру:
print("Tablica mnozenja 5 x 5")
for i in range(5):
print("Tablica mnozenja sa", i+1)
######### ovo je petlja u petlji
for j in range(5):
print(i+1, "*", j+1, "=", (i+1) * (j+1))
онда кажемо да је друга петља угнежђена, јер је обухваћена оном првом као у гнезду. За прву кажемо још и да је спољашња петља, док је ова друга унутрашња. Погледајмо како овај прогам ради:
print("Tablica mnozenja 5 x 5")
for i in range(5):
print("Tablica mnozenja sa", i+1)
######### ovo je petlja u petlji
for j in range(5):
print(i + 1, "*", j + 1, "=", (i + 1)*(j + 1))
Угнежђене петље се природно јављају када радимо са табелама података, или са подацима који треба да буду организовани у две димензије (и хоризонтално и вертикално).
Пример. Написати програм који приказује таблицу множења 10 x 10:
* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
2 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 |
3 | 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 |
4 | 4 | 8 | 13 | 16 | 20 | 24 | 28 | 32 | 36 | 40 |
5 | 5 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 |
6 | 6 | 12 | 18 | 24 | 30 | 36 | 42 | 48 | 54 | 60 |
7 | 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 |
8 | 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 | 80 |
9 | 9 | 18 | 27 | 36 | 45 | 54 | 63 | 72 | 81 | 90 |
10 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 |
Решење. Први покушај да се овај проблем реши би могао да изгледа овако:
print("Tablica mnozenja 10 x 10")
for i in range(10):
for j in range(10):
print((i + 1)*(j + 1))
али видимо да то није оно што смо желели. Желимо таблицу множења да испишемо као таблицу. Проблем је у томе што наредба print
пређе у нови ред чим нешто испише, а ми желимо да испишемо низ бројева у једном реду пре него што пређемо у нови ред.
Наредби print
можемо рећи да не прелази у нови ред тако што као опцију додамо
end = ""
Тада ће све што наредба испише бити смештено у исти ред. Када завршимо исписивање бројева који треба да буду у истом реду прелазимо у нови ред наредбом
print()
Ова наредба, заправо, ништа не испише, већ само пређе у нови ред.
print("Tablica mnozenja 10 x 10")
for i in range(10):
for j in range(10):
print((i + 1)*(j + 1), end="")
print()
Сада је мало боље, али и даље далео од онога што желимо. Треба нам мали размак између бројева. То је лако додати:
print("Tablica mnozenja 10 x 10")
for i in range(10):
for j in range(10):
print((i + 1)*(j + 1), " ", end="")
print()
Добили смо таблицу множења у принципу. Једини је проблем у томе што су редови и даље неуредни.
Да бисмо у таблици поравнали редове није, дакле, довољно само додати мали размак, већ треба обезбедити да сваки број буде исписан на исти број места независно од тога да ли број има једну, две или три цифре. За то ћемо користити уграђену функцију format
која форматира, односно, приказује податке на посебан начин. На пример,
format("Python", "15")
ће од стринга "Python"
направити нови стринг "Python "
који има дужину 15, а садржај је поравнат по левој ивици. С друге стране,
format(56, "4")
број 56 форматирати као стринг дужине 4 у коме је садржај поравнат по десној ивици.
Видимо да податак који форматирамо може dа буде и стринг и број, али други аргумент функције format
који објашњава функцији како да форматира садржај увек мора бити стринг. Разлог је у томе што стринг који описује захтеве може бити веома компликован и може да садржи и симболе који нису цифре. На пример,
format("Python", "^15")
ће од стринга "Python"
направити нови стринг " Python "
који има дужину 15, а садржај је центриран.
Коначно, ево програма који исписује таблицу множења као табелу:
print("Tablica mnozenja 10 x 10")
for i in range(10):
for j in range(10):
print(format((i + 1)*(j + 1), "4"), end="")
print()
Пример. Написати Пајтон функцију trougao_brojeva(n)
која исписује следећи троугао бројева:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
итд. Ово је пример позива функције за n = 5.
Решење.
def trougao_brojeva(n):
for i in range(n + 1):
for j in range(i):
print(format(j+1, "4"), end="")
print()
Да видимо како функција ради:
trougao_brojeva(6)
Пример. Написати Пајтон функцију trougao_brojeva_2(n)
која исписује следећи троугао бројева:
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
итд. Ово је пример позива функције за n = 5. Видимо да троугао има n редова, да су дужине редова 1, 2, 3, ..., n, и да се бројеви редом уписују у табелу.
Решење.
Идеја решења је да уведемо бројач који ће садржати следећи број који треба уписати на одговарајуће место, док ће две петље само регулисати облик троугла, овако:
def trougao_brojeva_2(n):
broj = 1
for i in range(n + 1):
for j in range(i):
print(format(broj, "5"), end="")
broj += 1
print()
Да видимо како функција ради:
trougao_brojeva_2(6)
Пример. Наћи све бројеве са највише четири цифре који су једнаки трећем степену збира својих цифара.
Решење. Број са највише четири цифре се може записати у облику $\langle abcd\rangle$, при чему је дозвољено да свака од цифара буде нула (траже се бројеви са највише четири цифре; према томе, за троцифрени број ће бити $a = 0$).
Дакле, тражимо бројеве $\langle abcd\rangle$ такве да је $\langle abcd\rangle = (a + b + c + d)^3$. Подсетимо се још да је: $$ \langle abcd\rangle = 1000 a + 100 b + 10 c + d. $$ Сада се програм лако пише:
for a in range(9):
for b in range(9):
for c in range(9):
for d in range(9):
if 1000*a + 100*b + 10*c + d == (a + b + c + d)**3:
print(1000*a + 100*b + 10*c + d)
5.2. Табеле са подацима¶
Веома често су подаци у вези са неким проблемом представљени табелом. Рецимо, ова табела садржи податке о једној групи деце (при чему је, наравно, старост изражена у годинама, маса у килограмима, а висина у центиметрима):
Ime | Pol | Starost | Masa | Visina |
---|---|---|---|---|
Ana | ž | 13 | 46 | 160 |
Bojan | m | 14 | 52 | 165 |
Vlada | m | 13 | 47 | 157 |
Gordana | ž | 15 | 54 | 165 |
Dejan | m | 15 | 56 | 163 |
Đorđe | m | 13 | 45 | 159 |
Elena | ž | 14 | 49 | 161 |
Žaklina | ž | 15 | 52 | 164 |
Zoran | m | 15 | 57 | 167 |
Ivana | ž | 13 | 45 | 158 |
Jasna | ž | 14 | 51 | 162 |
Да бисмо могли машински да обрађујемо и анализирамо податке, прво их морамо представити на погодан начин.
Један једноставан начин да се то уради је да сваки ред табеле представимо једном низом, и да потом све те низове запакујемо у један велики низ, рецимо овако:
razred = [["Ana", "ž", 13, 46, 160],
["Bojan", "m", 14, 52, 165],
["Vlada", "m", 13, 47, 157],
["Gordana", "ž", 15, 54, 165],
["Dejan", "m", 15, 56, 163],
["Đorđe", "m", 13, 45, 159],
["Elena", "ž", 14, 49, 161],
["Žaklina", "ž", 15, 52, 164],
["Zoran", "m", 15, 57, 167],
["Ivana", "ž", 13, 45, 158],
["Jasna", "ž", 14, 51, 162]]
Као и у већини модерних програмских језика, индекси елемената низа у Пајтону почињу од нуле, тако да
razred[0]
даје први ред табеле,
razred[1]
даје други ред табеле, и тако даље.
Ако желимо да видимо колико је висок Влада, написаћемо
razred[2][4]
зато што се подаци о Влади налазе у трећем реду табеле (чији индекс је 2 -- индексирање почиње од нуле!), а висина се налази у том низу на петом месту (чији индекс је 4). Дакле, овај ред каже:
из табеле razred
одабери прво ред са индексом 2, па из тог реда податак са индексом 4 (при томе водећи рачуна да индексирање почиње од нуле!)
Ако желимо да израчунамо просечну висину ученика у разреду учинићемо то овако:
br_ucenika = len(razred)
zbir = 0
for ucenik in razred:
zbir += ucenik[4]
print("Prosecna visina je", zbir/br_ucenika)
Ако желимо да пребројимо колико у разреду има дечака, а колико девојчица, можемо то учинити овако (имајући у виду да се информација о полу налази на другом месту у реду, чији индекс је 1):
br_decaka = 0
br_devojcica = 0
for ucenik in razred:
if ucenik[1] == "m":
br_decaka += 1
else:
br_devojcica += 1
print("Decaka ima", br_decaka)
print("Devojcica ima", br_devojcica)
Ево како можемо одредити највишу девојчицу:
# ne znamo koja devojcica je najvisa, pa stavljamo prazan string u ime
ime = ""
# ne znamo nista o njenoj visini, pa stavljamo vrednost koja je manja od svake razumne vrednosti
visina = 0
for ucenik in razred:
if ucenik[1] == "ž" and ucenik[4] > visina:
ime = ucenik[0]
print("Najvisa devojcica je", ime)
5.3. Задаци¶
Задатак 1. Испистати таблицу сабирања за цифре десетичног система:
+ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
2 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
3 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
4 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
5 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
6 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
7 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
8 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
9 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
Задатак 2. Написати функцију spec_trougao(n)
која исписује првих n редова следећег троугла бројева:
(а)
1
1 1
1 1 1
1 1 1 1
(б)
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
(в!)
1
2 3 2
3 4 5 4 3
4 5 6 7 6 5 4
5 6 7 8 9 8 7 6 5
Задатак 3. Написати функцију zmijasto(n)
која бројеве 1, 2, 3, ..., $n^2$ уписује у квадрат $n \times n$ "змијасто". На пример, за n = 5 функција исписује
1 2 3 4 5
10 9 8 7 6
11 12 13 14 15
20 19 18 17 16
21 22 23 24 25
Задатак 4. Наћи све бројеве са највише четири цифре који су једнаки
(а) квадрату збира својих цифара;
(б) четвртом степену збира својих цифара.
Задатак 5*. Наћи сва могућа дешифровања следећег сабирања:
АВ + ... + АВ = ЛАВ
где са десне стране имамо најмање два сабирка. Наравно, истим словима одговарају исте цифре, а различитим словима различите. При томе цифре А и Л не смеју да буду 0.
Задатак 6*. Наћи сва могућа дешифровања следећег сабирања:
ЛАВ + ... + ЛАВ = МРАВ
где са десне стране имамо најмање два сабирка. Наравно, истим словима одговарају исте цифре, а различитим словима различите. При томе цифре Л и М не смеју да буду 0.
Задатак 7. Дати су подаци о ученицима једног разреда:
razred = [["Ana", "ž", 13, 46, 160],
["Bojan", "m", 14, 52, 165],
["Vlada", "m", 13, 47, 157],
["Gordana", "ž", 15, 54, 165],
["Dejan", "m", 15, 56, 163],
["Đorđe", "m", 13, 45, 159],
["Elena", "ž", 14, 49, 161],
["Žaklina", "ž", 15, 52, 164],
["Zoran", "m", 15, 57, 167],
["Ivana", "ž", 13, 45, 158],
["Jasna", "ž", 14, 51, 162]]
Написати Пајтон програм који одређује
(а) ко је најлакши у разреду;
(б) ко је налјакши дечак у разреду.
Задатак 8. У следећој табели су дати подаци о националним парковима Србије. За сваки национални парк је наведено његово име, површина у хектарима и година оснивања:
nac_parkovi = [["Fruška gora", 25393, 1960],
["Đerdap", 64000, 1974],
["Tara", 22000, 1981],
["Kopaonik", 11810, 1981],
["Šar-planina", 39000, 1985]]
Напиши Пајтон програм који рачуна просечну површину националног парка (у хектарима), и укупну површину коју заузимају национални паркови у Србији (у квадратним километрима; 1 квадратни километар = 100 хектара).
Задатак 9. Производња кукуруза и пшенице у периоду 2008-2012. у Србији је дата у следећој табели (подаци су исказани у хиљадама тона):
Godina | Kukuruz | Pšenica |
---|---|---|
2008. | 6.158 | 2.095 |
2009. | 6.396 | 2.067 |
2010. | 7.207 | 1.631 |
2011. | 6.480 | 2.076 |
2012. | 3.532 | 1.911 |
(а) Напиши Пајтон програм који рачуна максималну производњу кукуруза и минималну производњу пшенице у наведеном периоду.
(б) Напиши Пајтон програм који рачуна просечну годишњу производњу кукуруза за наведени период, као и за колико се разликовала производња пшенице у најбољој и најлошијој години наведеног периода (у хиљадама тона).
Задатак 10. Ево трошкова живота једне породице током једне године, по месецима (сви износи су представљени у динарима):
Stavka | Jan | Feb | Mar | Apr | Maj | Jun | Jul | Avg | Sep | Okt | Nov | Dec |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Stanarina | 8.251 | 8.436 | 8.524 | 8.388 | 8.241 | 8.196 | 8.004 | 7.996 | 7.991 | 8.015 | 8.353 | 8.456 |
Struja | 4.321 | 4.530 | 4.115 | 3.990 | 3.985 | 3.726 | 3.351 | 3.289 | 3.295 | 3.485 | 3.826 | 3.834 |
Telefon (fiksni) | 1.425 | 1.538 | 1.623 | 1.489 | 1.521 | 1.485 | 1.491 | 1.399 | 1.467 | 1.531 | 1.410 | 1.385 |
Telefon (mobilni) | 2.181 | 2.235 | 2.073 | 1.951 | 1.989 | 1.945 | 3.017 | 2.638 | 2.171 | 1.831 | 1.926 | 1.833 |
TV i internet | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 | 2.399 |
Prevoz | 1.830 | 1.830 | 1.830 | 1.830 | 1.950 | 1.950 | 1.450 | 1.450 | 1.950 | 1.950 | 2.050 | 2.050 |
Hrana | 23.250 | 23.780 | 24.019 | 24.117 | 24.389 | 24.571 | 24.736 | 24.951 | 25.111 | 25.389 | 25.531 | 25.923 |
Ostalo | 4.500 | 3.700 | 5.100 | 3.500 | 2.750 | 4.250 | 7.320 | 8.250 | 3.270 | 4.290 | 3.200 | 8.390 |
У ћелији испод су исти подаци представљени табелом:
troskovi = [
["Stanarina", 8251, 8436, 8524, 8388, 8241, 8196, 8004, 7996, 7991, 8015, 8353, 8456],
["Struja", 4321, 4530, 4115, 3990, 3985, 3726, 3351, 3289, 3295, 3485, 3826, 3834],
["Telefon (fiksni)", 1425, 1538, 1623, 1489, 1521, 1485, 1491, 1399, 1467, 1531, 1410, 1385],
["Telefon (mobilni)", 2181, 2235, 2073, 1951, 1989, 1945, 3017, 2638, 2171, 1831, 1926, 1833],
["TV i internet", 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399 ],
["Prevoz", 1830, 1830, 1830, 1830, 1950, 1950, 1450, 1450, 1950, 1950, 2050, 2050],
["Hrana", 23250, 23780, 24019, 24117, 24389, 24571, 24736, 24951, 25111, 25389, 25531, 25923],
["Ostalo", 4500, 3700, 5100, 3500, 2750, 4250, 7320, 8250, 3270, 4290, 3200, 8390]
]
Напиши Пајтон програм који рачуна укупне трошкове ове породице по месецима (колико је породица укупно потрошила у јануару, колико у фебруару итд).