1. Metoda tabelului de trasare
Sa luam fragmentul din provocare:
s = 0 for i in range(1, 6): s = s + i print(s)
Trasam fiecare iteratie: coloana i = valoarea curenta a contorului, coloana s = valoarea dupa atribuire.
| Iteratie | i | s = s + i | s dupa pas |
|---|---|---|---|
| start | — | — | 0 |
| 1 | 1 | 0 + 1 | 1 |
| 2 | 2 | 1 + 2 | 3 |
| 3 | 3 | 3 + 3 | 6 |
| 4 | 4 | 6 + 4 | 10 |
| 5 | 5 | 10 + 5 | 15 |
Iesire reala (rulat cu python):
15
In Python, range(1, 6) NU include 6. Multi elevi aduna gresit pana la 6 si obtin 21. Citeste mereu cu atentie limitele lui range.
2. Trasarea unei bucle WHILE: suma cifrelor
La buclele WHILE, atentia merge la conditia de oprire. Sa trasam un algoritm clasic de Bac — suma cifrelor unui numar:
n = 2451 s = 0 while n != 0: s = s + n % 10 # adauga ultima cifra n = n // 10 # elimina ultima cifra print(s)
| Pas | n (inainte) | n % 10 | s | n (dupa // 10) |
|---|---|---|---|---|
| 1 | 2451 | 1 | 1 | 245 |
| 2 | 245 | 5 | 6 | 24 |
| 3 | 24 | 4 | 10 | 2 |
| 4 | 2 | 2 | 12 | 0 |
| stop | 0 | conditia n != 0 este FALSA → bucla se opreste | ||
Iesire reala (rulat cu python):
12
Verifica intotdeauna ca exista un pas care apropie variabila de conditia de oprire (aici n = n // 10). Daca lipseste, bucla devine infinita.
3. IF imbricat intr-o bucla FOR
Cele mai grele probleme combina o bucla cu o decizie. Aici, la fiecare pas decidem dupa paritatea lui i:
x = 0 for i in range(1, 8): if i % 2 == 0: x = x + i # i par: aduna i else: x = x - 1 # i impar: scade 1 print(x)
range(1, 8) parcurge 1, 2, 3, 4, 5, 6, 7. Notam si ramura aleasa:
| i | i par? | ramura | operatie | x |
|---|---|---|---|---|
| 1 | nu | else | x - 1 | -1 |
| 2 | da | if | x + 2 | 1 |
| 3 | nu | else | x - 1 | 0 |
| 4 | da | if | x + 4 | 4 |
| 5 | nu | else | x - 1 | 3 |
| 6 | da | if | x + 6 | 9 |
| 7 | nu | else | x - 1 | 8 |
Iesire reala (rulat cu python):
8
4. Trasare cu doua variabile care se schimba
Acesta este nucleul descompunerii in factori primi (tema 2.2 din programa). Doua variabile evolueaza: n (numarul ramas) si d (divizorul incercat). Numaram in nr cati factori primi are 60:
n = 60 d = 2 nr = 0 while n > 1: if n % d == 0: nr = nr + 1 n = n // d else: d = d + 1 print(nr)
| Pas | n | d | n % d == 0? | actiune | nr |
|---|---|---|---|---|---|
| 1 | 60 | 2 | da | n=30 | 1 |
| 2 | 30 | 2 | da | n=15 | 2 |
| 3 | 15 | 2 | nu | d=3 | 2 |
| 4 | 15 | 3 | da | n=5 | 3 |
| 5 | 5 | 3 | nu | d=4 | 3 |
| 6 | 5 | 4 | nu | d=5 | 3 |
| 7 | 5 | 5 | da | n=1 | 4 |
| stop | 1 | 5 | n > 1 este FALS → stop | ||
Iesire reala (rulat cu python):
4
Intr-adevar 60 = 2 · 2 · 3 · 5, deci 4 factori primi (numarati cu multiplicitate). Acest algoritm face un numar de pasi proportional cu numarul incercarilor de divizor; pentru cazul cel mai rau (n prim) complexitatea este O(n).
5. Acelasi tipar in C++ intensiv
La specializarea intensiv informatica, al doilea limbaj este C++. Subiectele de tip Bac in C++ folosesc EXACT aceeasi metoda de trasare; doar sintaxa difera. Daca esti la profil standard, poti sari peste acest atom.
Problema clasica: oglinda (rasturnatul) unui numar. Trasam constructia in r:
#include <iostream> using namespace std; int main() { int n = 1234, r = 0; while (n != 0) { r = r * 10 + n % 10; // adauga ultima cifra la dreapta lui r n = n / 10; // elimina ultima cifra din n } cout << r << endl; return 0; }
| Pas | n | n % 10 | r = r*10 + n%10 | n / 10 |
|---|---|---|---|---|
| 1 | 1234 | 4 | 4 | 123 |
| 2 | 123 | 3 | 43 | 12 |
| 3 | 12 | 2 | 432 | 1 |
| 4 | 1 | 1 | 4321 | 0 |
| stop | 0 | n != 0 este FALS → stop | ||
Iesire reala (compilat cu g++ -std=c++17):
4321
In C++, n / 10 pe variabile int face impartire INTREAGA (echivalentul lui // din Python). Daca n ar fi double, / 10 ar pastra zecimalele si algoritmul nu ar mai functiona.
6. Bucle imbricate: numara executiile intensiv
Buclele imbricate cu limita dependenta (interiorul porneste de la i) sunt frecvente la profilul intensiv. Aici contorul depinde de iteratia exterioara.
Cand bucla interioara incepe de la i (nu de la 1), numarul de pasi scade la fiecare runda. Trasam contorul c:
#include <iostream> using namespace std; int main() { int c = 0; for (int i = 1; i <= 3; i++) for (int j = i; j <= 3; j++) c++; cout << c << endl; return 0; }
| i | valori j | cati pasi | c cumulat |
|---|---|---|---|
| 1 | 1, 2, 3 | 3 | 3 |
| 2 | 2, 3 | 2 | 5 |
| 3 | 3 | 1 | 6 |
Iesire reala (compilat cu g++ -std=c++17):
6
Pentru limita generala n in loc de 3, corpul se executa de 1 + 2 + ... + n = n(n+1)/2 ori, deci complexitatea este O(n²) — tipic pentru doua bucle imbricate.