Informatica clasa 9
Curs Complet de Informatică — Clasa a IX-a¶
Specializarea: Matematică-Informatică (Curriculum de Specialitate)
Limbaje: Python (principal) și C++ (secundar)
📋 Cuprins¶
- Introducere
- Capitolul 1: Principii de elaborare a unui program
- Capitolul 2: Prelucrări ale numerelor
- Capitolul 3: Subprograme
- Capitolul 4: Introducere în programarea orientată pe obiecte
- Capitolul 5: Interfețe grafice (Tkinter)
- Capitolul 6: Fișiere text
- Capitolul 7: Modelul conceptual liniar — lista
- Capitolul 8: Clasa
listdin Python și vectori în C++ - Capitolul 9: Generarea sistematică a elementelor unei liste
- Capitolul 10: Metode de sortare
- Anexe
Introducere¶
Despre acest curs¶
Acest curs acoperă integral programa școlară de informatică pentru clasa a IX-a, specializarea matematică-informatică (Ordin MEC 4.350/2025). Conținutul este structurat în ordinea recomandată de programă și include:
- Noțiuni teoretice explicate riguros și cu exemple intuitive.
- Cod sursă în Python (limbaj principal) și C++ (limbaj secundar, pentru clasele intensive).
- Probleme rezolvate din viața reală.
- Exerciții propuse la finalul fiecărui capitol.
Competențele formate¶
Programa vizează 6 competențe generale (CG) derivate din taxonomia Bloom:
| CG | Nivel cognitiv | Descriere |
|---|---|---|
| CG1 | Identificare | Recunoașterea caracteristicilor modelelor |
| CG2 | Înțelegere | Explicarea principiilor |
| CG3 | Aplicare | Utilizarea modelelor în soluții |
| CG4 | Analiză | Compararea soluțiilor |
| CG5 | Evaluare | Aprecierea corectitudinii și eficienței |
| CG6 | Creare | Elaborarea de algoritmi personalizați |
De ce Python + C++?¶
- Python este limbajul de bază: sintaxă simplă, concentrare pe logică, potrivit pentru învățarea conceptelor fundamentale.
- C++ aprofundează mecanismele interne: gestionarea memoriei, tipuri stricte, eficiență ridicată — esențial pentru olimpiade și studii avansate.
Medii de dezvoltare recomandate¶
Pentru Python: PyCharm (Community/Educational), IDLE, Spyder, VS Code.
Pentru C++: Code::Blocks, VS Code (cu extensia C/C++), Visual Studio.
Online: OnlineGDB, Programiz, Repl.it.
Capitolul 1: Principii de elaborare a unui program¶
1.1. Gândirea computațională¶
Gândirea computațională reprezintă ansamblul de procese mentale folosite pentru a formula probleme și soluții într-o formă pe care un calculator (sau un om) le poate executa.
Cele 4 pilonii ai gândirii computaționale:
- Descompunere (Decomposition) — împărțirea unei probleme complexe în subprobleme mai simple.
- Recunoașterea tiparelor (Pattern Recognition) — identificarea asemănărilor între probleme.
- Abstractizare (Abstraction) — reținerea detaliilor esențiale, ignorarea celor irelevante.
- Proiectarea algoritmilor (Algorithm Design) — elaborarea pașilor concreți de rezolvare.
Exemplu intuitiv: Pregătirea unui sandwich.
- Descompunere: prăjim pâinea, ungem unt, adăugăm brânza, adăugăm legumele.
- Tipare: toate sandwich-urile au o bază (pâine) + umplutură.
- Abstractizare: nu contează culoarea farfuriei.
- Algoritm: pași secvențiali cu decizii („dacă brânza e topită, scoate din cuptor”).
1.2. Etapele elaborării unui program¶
Orice program parcurge 5 etape fundamentale:
┌──────────┐ ┌───────────┐ ┌────────────────┐ ┌──────────┐ ┌─────────┐
│ ANALIZĂ │ → │ PROIECTARE│ → │ IMPLEMENTARE │ → │ TESTARE │ → │DEPANARE │
└──────────┘ └───────────┘ └────────────────┘ └──────────┘ └─────────┘
- Analiza problemei — ce date avem (intrare), ce vrem să obținem (ieșire), ce constrângeri există.
- Proiectarea algoritmului — reprezentare prin pseudocod/schemă logică, descompunere modulară.
- Implementarea — scrierea codului într-un limbaj de programare.
- Testarea — verificarea cu date de intrare diverse (inclusiv cazuri limită).
- Depanarea (debugging) — identificarea și corectarea erorilor.
1.3. Tipuri de erori¶
| Tip de eroare | Când apare | Exemplu |
|---|---|---|
| Sintactică | La compilare/interpretare | Lipsă : în Python sau ; în C++ |
| De logică | Programul rulează dar rezultatul e greșit | Am scris < în loc de <= |
| De executare (runtime) | În timpul rulării | Împărțire la zero, index în afara listei |
1.4. Moduri de reprezentare a algoritmilor¶
a) Scheme logice (blocuri grafice)¶
Conform programei, simbolurile standard sunt:
| Simbol | Rol |
|---|---|
| Dreptunghi | Bloc de proces (calcul, atribuire) |
| Romb | Bloc de decizie (2 ieșiri: Da/Nu) |
| Paralelogram | Intrare/ieșire date |
| Elipsă | START / STOP |
| Săgeată | Linie de flux |
b) Pseudocod¶
Limbaj intermediar, apropiat de limba naturală, independent de orice limbaj de programare.
Exemplu: citește două numere și afișează maximul.
START
citește a, b
dacă a > b atunci
scrie a
altfel
scrie b
sfârșit dacă
STOP
c) Limbaje de programare¶
- Nivel înalt (Python, C++, Java) — apropiate de limbajul uman.
- Nivel scăzut (Assembly) — apropiate de limbajul mașinii.
Interpretor vs. Compilator:
- Interpretor (Python): execută codul linie cu linie.
- Compilator (C++): traduce tot codul în cod mașină înainte de execuție.
1.5. Primul program¶
Python¶
# Afișează un mesaj de întâmpinare
print("Bună, lume!")
print("Bine ai venit la informatică!")
C++¶
#include <iostream>
using namespace std;
int main() {
cout << "Bună, lume!" << endl;
cout << "Bine ai venit la informatică!" << endl;
return 0;
}
1.6. Variabile și tipuri de date¶
O variabilă este o locație de memorie cu un nume, care stochează o valoare.
Tipuri de bază — comparație¶
| Concept | Python | C++ |
|---|---|---|
| Întreg | int (nelimitat) |
int (32 biți), long long (64 biți) |
| Real | float |
float, double |
| Caracter | str (lungime 1) |
char |
| Șir | str |
string, char[] |
| Logic | bool (True/False) |
bool (true/false) |
Python — tipizare dinamică¶
varsta = 15 # int
pi = 3.14159 # float
nume = "Alex" # str
este_elev = True # bool
# Variabila poate schimba tipul
x = 10
x = "acum sunt text" # Legal în Python
C++ — tipizare statică¶
#include <iostream>
#include <string>
using namespace std;
int main() {
int varsta = 15;
double pi = 3.14159;
string nume = "Alex";
bool este_elev = true;
// varsta = "text"; // EROARE de compilare!
return 0;
}
1.7. Citirea și scrierea datelor¶
Python¶
# Citire
nume = input("Introdu numele: ")
varsta = int(input("Introdu vârsta: "))
nota = float(input("Introdu nota: "))
# Afișare
print("Salut,", nume)
print(f"Ai {varsta} ani și nota {nota}")
C++¶
#include <iostream>
#include <string>
using namespace std;
int main() {
string nume;
int varsta;
double nota;
cout << "Introdu numele: ";
cin >> nume;
cout << "Introdu vârsta: ";
cin >> varsta;
cout << "Introdu nota: ";
cin >> nota;
cout << "Salut, " << nume << endl;
cout << "Ai " << varsta << " ani și nota " << nota << endl;
return 0;
}
1.8. Operatori¶
Operatori aritmetici¶
| Op. | Python | C++ | Exemplu |
|---|---|---|---|
| Adunare | + |
+ |
5+3=8 |
| Scădere | - |
- |
5-3=2 |
| Înmulțire | * |
* |
5*3=15 |
| Împărțire reală | / |
/ (cu double) |
5/2=2.5 |
| Împărțire întreagă | // |
/ (cu int) |
5//2=2 |
| Modulo (rest) | % |
% |
5%2=1 |
| Putere | ** |
pow(a,b) |
2**3=8 |
Operatori relaționali¶
Ambele limbaje folosesc: ==, !=, <, >, <=, >=.
Operatori logici¶
| Operație | Python | C++ |
|---|---|---|
| ȘI logic | and |
&& |
| SAU logic | or |
|| |
| NU logic | not |
! |
1.9. Structuri de control¶
a) Structura decizională (if)¶
Python:
nota = float(input("Nota: "))
if nota >= 5:
print("Promovat")
else:
print("Nepromovat")
# if-elif-else
if nota >= 9:
print("Excelent")
elif nota >= 7:
print("Bine")
elif nota >= 5:
print("Satisfăcător")
else:
print("Nepromovat")
C++:
double nota;
cin >> nota;
if (nota >= 5) {
cout << "Promovat";
} else {
cout << "Nepromovat";
}
// if-else if-else
if (nota >= 9) cout << "Excelent";
else if (nota >= 7) cout << "Bine";
else if (nota >= 5) cout << "Satisfăcător";
else cout << "Nepromovat";
b) Structura repetitivă cu test inițial (while)¶
Python:
# Afișează numerele de la 1 la 10
i = 1
while i <= 10:
print(i)
i += 1
C++:
int i = 1;
while (i <= 10) {
cout << i << " ";
i++;
}
c) Structura repetitivă cu test final (do-while)¶
Python nu are do-while, dar îl putem simula:
while True:
n = int(input("Numărul (>0): "))
if n > 0:
break
C++:
int n;
do {
cout << "Numărul (>0): ";
cin >> n;
} while (n <= 0);
d) Structura repetitivă cu contor (for)¶
Python:
# range(start, stop, step) — stop este exclus
for i in range(1, 11): # 1, 2, ..., 10
print(i)
for i in range(10, 0, -1): # 10, 9, ..., 1
print(i)
for i in range(0, 20, 2): # 0, 2, 4, ..., 18
print(i)
C++:
for (int i = 1; i <= 10; i++)
cout << i << " ";
for (int i = 10; i >= 1; i--)
cout << i << " ";
for (int i = 0; i < 20; i += 2)
cout << i << " ";
1.10. Eficiența algoritmilor — notația O¶
Complexitatea temporală exprimă cum crește numărul de operații în funcție de dimensiunea datelor (notată n).
| Notație | Denumire | Exemplu |
|---|---|---|
| O(1) | Constantă | Acces la un element din listă prin index |
| O(log n) | Logaritmică | Căutare binară |
| O(n) | Liniară | Parcurgerea unui tablou |
| O(n log n) | Liniar-logaritmică | Sortare eficientă (MergeSort) |
| O(n²) | Pătratică | Metoda bulelor, selecția minimului |
| O(2ⁿ) | Exponențială | Fibonacci recursiv fără memorare |
Exemplu — calcularea ordinului:
# O(n) — o singură buclă
for i in range(n):
print(i)
# O(n²) — bucle imbricate
for i in range(n):
for j in range(n):
print(i, j)
1.11. Testarea programelor¶
Un program bun trebuie testat cu:
- Date tipice (cazuri obișnuite).
- Cazuri limită (valori minime, maxime, listă vidă, un element).
- Date invalide (pentru a verifica validarea).
Exemplu: pentru un program care calculează media a n note, testăm:
n = 1(un singur element).n = 0(listă vidă — ar trebui să afișeze eroare).- Note la limită: 1 și 10.
- Medie fracționară: note = [7, 8] → media = 7.5.
✏️ Exerciții propuse — Capitolul 1¶
- Scrie un program care citește 3 numere și afișează suma, produsul și media lor.
- Citește un număr și verifică dacă este par sau impar.
- Citește un an și stabilește dacă este bisect (divizibil cu 4, dar nu cu 100 — sau divizibil cu 400).
- Afișează tabla înmulțirii pentru un număr citit.
- Calculează
n!(factorial) pentru unncitit.
Capitolul 2: Prelucrări ale numerelor¶
2.1. Operații cu cifrele unui număr¶
Acces la ultima cifră¶
Ultima cifră a unui număr n = n % 10.
Eliminarea ultimei cifre¶
n // 10 (Python) sau n / 10 (C++ cu int).
Adăugarea unei cifre la dreapta¶
Dacă avem numărul n și vrem să adăugăm cifra c la dreapta: n = n * 10 + c.
Exemplu: n = 25, c = 7 → n = 25*10 + 7 = 257.
Adăugarea unei cifre la stânga¶
Dacă n are k cifre: n = c * 10^k + n.
Exemplu: n = 25 (2 cifre), c = 7 → n = 7*100 + 25 = 725.
2.2. Parcurgerea cifrelor unui număr¶
Python¶
def afiseaza_cifre(n):
"""Afișează cifrele unui număr, de la dreapta la stânga."""
while n > 0:
print(n % 10, end=" ")
n //= 10
afiseaza_cifre(12345) # 5 4 3 2 1
C++¶
void afiseaza_cifre(int n) {
while (n > 0) {
cout << n % 10 << " ";
n /= 10;
}
}
2.3. Oglinditul unui număr¶
Oglinditul lui 1234 este 4321.
Python¶
def oglindit(n):
o = 0
while n > 0:
o = o * 10 + n % 10
n //= 10
return o
print(oglindit(1234)) # 4321
print(oglindit(100)) # 1 (zerourile de la sfârșit se pierd!)
C++¶
int oglindit(int n) {
int o = 0;
while (n > 0) {
o = o * 10 + n % 10;
n /= 10;
}
return o;
}
⚠️ Observație:
oglindit(oglindit(n))NU este întotdeauna egal cun! Exemplu:oglindit(100) = 1, iaroglindit(1) = 1 ≠ 100.
2.4. Suma și numărul cifrelor¶
def suma_cifrelor(n):
s = 0
while n > 0:
s += n % 10
n //= 10
return s
def numar_cifre(n):
nr = 0
while n > 0:
nr += 1
n //= 10
return nr
print(suma_cifrelor(1234)) # 10
print(numar_cifre(1234)) # 4
int suma_cifrelor(int n) {
int s = 0;
while (n > 0) { s += n % 10; n /= 10; }
return s;
}
int numar_cifre(int n) {
int nr = 0;
while (n > 0) { nr++; n /= 10; }
return nr;
}
2.5. Eliminarea unor cifre dintr-un număr¶
Problema: Dintr-un număr, să eliminăm toate cifrele impare, păstrând ordinea.
def elimina_impare(n):
rezultat = 0
putere = 1
# Parcurgem cifrele de la dreapta la stânga
cifre_pastrate = []
while n > 0:
c = n % 10
if c % 2 == 0:
cifre_pastrate.append(c)
n //= 10
# Reconstruim numărul
for c in reversed(cifre_pastrate):
rezultat = rezultat * 10 + c
return rezultat
print(elimina_impare(123456)) # 246
print(elimina_impare(2040)) # 2040
2.6. Divizorii unui număr¶
Un divizor al lui n este un număr d astfel încât n % d == 0.
Metoda 1 — parcurgere până la n (O(n))¶
def divizori_v1(n):
for d in range(1, n + 1):
if n % d == 0:
print(d, end=" ")
Metoda 2 — parcurgere până la n/2 + n (O(n/2))¶
def divizori_v2(n):
for d in range(1, n // 2 + 1):
if n % d == 0:
print(d, end=" ")
print(n) # n este întotdeauna divizor al lui n
Metoda 3 — parcurgere până la √n (O(√n)) ⭐¶
import math
def divizori_v3(n):
for d in range(1, int(math.sqrt(n)) + 1):
if n % d == 0:
print(d, end=" ")
if d != n // d:
print(n // d, end=" ")
De ce √n? Dacă
deste divizor șid ≤ √n, atuncin/d ≥ √n. Deci toți divizorii apar în perechi(d, n/d).
C++ — Metoda √n¶
#include <cmath>
void divizori(int n) {
for (int d = 1; d * d <= n; d++) {
if (n % d == 0) {
cout << d << " ";
if (d != n / d)
cout << n / d << " ";
}
}
}
2.7. Numere prime¶
Un număr n > 1 este prim dacă are exact 2 divizori: 1 și n.
def este_prim(n):
if n < 2:
return False
for d in range(2, int(n**0.5) + 1):
if n % d == 0:
return False
return True
print(este_prim(7)) # True
print(este_prim(15)) # False
bool este_prim(int n) {
if (n < 2) return false;
for (int d = 2; d * d <= n; d++)
if (n % d == 0) return false;
return true;
}
2.8. Descompunerea în factori primi¶
def descompunere(n):
d = 2
while n > 1:
while n % d == 0:
print(d, end=" ")
n //= d
d += 1
descompunere(60) # 2 2 3 5 (pentru că 60 = 2²·3·5)
2.9. Algoritmul lui Euclid — CMMDC¶
Cel mai mare divizor comun al două numere a și b se poate calcula eficient folosind algoritmul lui Euclid.
a) Cu scăderi repetate¶
Cât timp a ≠ b:
dacă a > b: a = a - b
altfel: b = b - a
CMMDC = a
def cmmdc_scaderi(a, b):
while a != b:
if a > b:
a -= b
else:
b -= a
return a
b) Cu împărțiri repetate (mai eficient — O(log n))¶
Cât timp b ≠ 0:
r = a % b
a = b
b = r
CMMDC = a
def cmmdc(a, b):
while b != 0:
a, b = b, a % b
return a
print(cmmdc(48, 18)) # 6
int cmmdc(int a, int b) {
while (b != 0) {
int r = a % b;
a = b;
b = r;
}
return a;
}
2.10. CMMMC — Cel mai mic multiplu comun¶
Relația fundamentală: a * b = cmmdc(a,b) * cmmmc(a,b).
def cmmmc(a, b):
return a * b // cmmdc(a, b)
print(cmmmc(4, 6)) # 12
Problemă practică: Două semafoare durează 30s, respectiv 45s. După cât timp se sincronizează?
Răspuns: cmmmc(30, 45) = 90 secunde.
2.11. Conversia între baze de numerație¶
Din baza 10 în baza 2 (sau oricare b)¶
Algoritm: împărțim succesiv la b și citim resturile în ordine inversă.
25 : 2 = 12 rest 1
12 : 2 = 6 rest 0
6 : 2 = 3 rest 0
3 : 2 = 1 rest 1
1 : 2 = 0 rest 1
Citit invers: 11001 → 25₁₀ = 11001₂.
def baza_10_la_b(n, b):
if n == 0:
return "0"
cifre = []
while n > 0:
cifre.append(str(n % b))
n //= b
return "".join(reversed(cifre))
print(baza_10_la_b(25, 2)) # 11001
print(baza_10_la_b(255, 16)) # FF? — doar cifre! Pentru hexa ar fi nevoie de conversie
Din baza b în baza 10¶
Algoritm (Horner): 11001₂ = 1·2⁴ + 1·2³ + 0·2² + 0·2¹ + 1·2⁰ = 25
def baza_b_la_10(s, b):
rezultat = 0
for c in s:
rezultat = rezultat * b + int(c)
return rezultat
print(baza_b_la_10("11001", 2)) # 25
✏️ Exerciții propuse — Capitolul 2¶
- Citește un număr și afișează suma cifrelor sale.
- Verifică dacă un număr este palindrom (ex: 12321).
- Afișează toți divizorii unui număr folosind metoda O(√n).
- Verifică dacă un număr este perfect (suma divizorilor proprii = n). Exemplu: 6 = 1+2+3.
- Calculează CMMDC pentru 3 numere.
- Transformă un număr din baza 10 în baza 8.
- Afișează toate numerele prime până la
n(Ciurul lui Eratostene).
Capitolul 3: Subprograme¶
3.1. Ce sunt subprogramele?¶
Un subprogram (sau funcție) este o secvență de cod nominalizată care execută o sarcină specifică și poate fi apelată ori de câte ori este nevoie.
Analogie: O rețetă. O scrii o singură dată, dar o folosești de câte ori vrei să gătești acel preparat.
Beneficiile subprogramelor:
- Reutilizare — scriem o dată, folosim de mai multe ori.
- Claritate — codul devine mai ușor de citit.
- Modularitate — împărțim problemele mari în bucăți mici.
- Mentenanță — corectăm o eroare într-un singur loc.
3.2. Structura unui subprogram¶
Componente:
- Antet — numele și parametrii.
- Corp — instrucțiunile executate.
- Valoare returnată (opțional).
3.3. Definire și apel în Python¶
def saluta(nume): # antet
print(f"Salut, {nume}!") # corp
saluta("Alex") # apel
saluta("Maria") # alt apel
Funcție cu valoare returnată:
def patrat(x):
return x * x
rezultat = patrat(5)
print(rezultat) # 25
print(patrat(7)) # 49
Funcție cu mai mulți parametri:
def suma(a, b):
return a + b
def maxim(a, b):
if a > b:
return a
return b
print(suma(3, 5)) # 8
print(maxim(10, 7)) # 10
3.4. Definire și apel în C++¶
#include <iostream>
using namespace std;
void saluta(string nume) {
cout << "Salut, " << nume << "!" << endl;
}
int patrat(int x) {
return x * x;
}
int maxim(int a, int b) {
return (a > b) ? a : b;
}
int main() {
saluta("Alex");
cout << patrat(5) << endl; // 25
cout << maxim(10, 7) << endl;// 10
return 0;
}
3.5. Variabile locale și globale¶
- Variabilă locală: definită în interiorul unui subprogram. Există doar pe durata executării subprogramului.
- Variabilă globală: definită în afara oricărui subprogram. Există pe toată durata programului.
Python¶
x = 10 # variabilă globală
def test():
y = 5 # variabilă locală
print(x + y) # poate citi x
test() # afișează 15
# print(y) # EROARE — y nu există aici
def modifica():
global x
x = 100 # modifică variabila globală
modifica()
print(x) # 100
C++¶
int x = 10; // globală
void test() {
int y = 5; // locală
cout << x + y << endl;
}
int main() {
test();
// cout << y; // EROARE
return 0;
}
3.6. Transmiterea parametrilor¶
Prin valoare (copie)¶
Parametrul primește o copie a valorii. Modificările nu se reflectă în afara funcției.
Python (pentru tipuri imutabile: int, float, str, tuple):
def modifica(x):
x = 100
print("În funcție:", x)
a = 5
modifica(a)
print("După apel:", a) # 5 — neschimbat
C++:
void modifica(int x) { // x este o copie
x = 100;
}
int a = 5;
modifica(a);
cout << a; // 5
Prin referință (în C++)¶
void modifica(int &x) { // x este alias pentru variabila originală
x = 100;
}
int a = 5;
modifica(a);
cout << a; // 100 — modificat!
În Python, listele și dicționarele sunt transmise „prin referință” implicit:
def adauga(lista):
lista.append(99)
l = [1, 2, 3]
adauga(l)
print(l) # [1, 2, 3, 99]
3.7. Subprograme predefinite — matematice¶
Python¶
import math
abs(-5) # 5
round(3.7) # 4
round(3.14, 1) # 3.1
int(3.9) # 3 (trunchiere)
math.sqrt(16) # 4.0
math.floor(3.7) # 3
math.ceil(3.2) # 4
math.pow(2, 10) # 1024.0
C++¶
#include <cmath>
abs(-5); // 5
round(3.7); // 4
(int)3.9; // 3
sqrt(16); // 4.0
floor(3.7); // 3
ceil(3.2); // 4
pow(2, 10); // 1024
3.8. Subprograme predefinite — conversii¶
int("42") # 42
int("FF", 16) # 255 (conversie din hexa)
float("3.14") # 3.14
str(42) # "42"
bool(0) # False
bool(1) # True
3.9. Subprograme predefinite — colecții¶
Funcții foarte utile pentru liste și alte colecții:
lista = [3, 7, 2, 8, 1]
len(lista) # 5 — numărul de elemente
min(lista) # 1 — minimul
max(lista) # 8 — maximul
sum(lista) # 21 — suma
sorted(lista) # [1, 2, 3, 7, 8] — listă sortată (nouă)
3.10. Problemă rezolvată — calculator de note¶
def media(note):
return sum(note) / len(note)
def nota_maxima(note):
return max(note)
def afiseaza_raport(nume_elev, note):
print(f"Elev: {nume_elev}")
print(f" Note: {note}")
print(f" Medie: {media(note):.2f}")
print(f" Maxim: {nota_maxima(note)}")
print(f" Minim: {min(note)}")
note_alex = [9, 10, 8, 7, 9]
afiseaza_raport("Alex", note_alex)
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <string>
using namespace std;
double media(vector<int>& note) {
return (double)accumulate(note.begin(), note.end(), 0) / note.size();
}
int nota_maxima(vector<int>& note) {
return *max_element(note.begin(), note.end());
}
void afiseaza_raport(string nume, vector<int>& note) {
cout << "Elev: " << nume << endl;
cout << " Medie: " << media(note) << endl;
cout << " Maxim: " << nota_maxima(note) << endl;
}
int main() {
vector<int> note_alex = {9, 10, 8, 7, 9};
afiseaza_raport("Alex", note_alex);
return 0;
}
✏️ Exerciții propuse — Capitolul 3¶
- Scrie o funcție care primește un număr și returnează suma cifrelor sale.
- Scrie o funcție
este_prim(n)și folosește-o pentru a afișa toate numerele prime de la 1 la 100. - Scrie o funcție
distanta(x1, y1, x2, y2)care calculează distanța euclidiană. - Scrie un mini-calculator cu funcții pentru
+,-,*,/. - Scrie o funcție care primește o listă și returnează media fără a folosi
sum().
Capitolul 4: Introducere în programarea orientată pe obiecte¶
4.1. Concepte fundamentale¶
Programarea orientată pe obiecte (POO) modelează realitatea prin obiecte care au:
- Proprietăți (atribute/date) — ce știe obiectul despre sine.
- Comportamente (metode) — ce poate face obiectul.
Analogie: Un câine are:
- Proprietăți: nume, rasă, vârstă, culoare.
- Comportamente: latră, mănâncă, aleargă.
4.2. Clasă vs. Obiect¶
- Clasa este un șablon (un plan arhitectural).
- Obiectul este o instanță concretă a clasei (o clădire construită după plan).
Clasa: Mașină Obiecte (instanțe):
- culoare mașina lui Alex: roșie, Dacia, 2020
- marcă mașina Mariei: albastră, BMW, 2022
- an
4.3. Utilizarea claselor predefinite¶
La clasa a IX-a folosim în principal clase predefinite, nu le creăm noi. Exemple de clase deja disponibile:
Python¶
# Clasa str (șiruri de caractere)
s = "Alex" # instanțiere implicită
print(s.upper()) # "ALEX" — metodă
print(s.lower()) # "alex"
print(len(s)) # 4 — funcție predefinită
# Clasa list
lista = [1, 2, 3]
lista.append(4) # metodă
print(lista) # [1, 2, 3, 4]
# Clasa dict
persoana = {"nume": "Alex", "varsta": 15}
print(persoana["nume"]) # "Alex"
Accesul la membri¶
- Atribute se accesează prin
obiect.atribut. - Metode se apelează prin
obiect.metoda().
4.4. Exemplu — clasa list folosită orientat-obiect¶
# Crearea obiectului (instanțiere)
numere = [5, 3, 8, 1, 9]
# Apelul metodelor
numere.append(100) # adaugă 100 la final
numere.sort() # sortează crescător
numere.reverse() # inversează
numere.pop() # elimină ultimul
# Accesul la informații
print(len(numere)) # dimensiunea
print(numere.count(3)) # numărul de apariții ale lui 3
4.5. Biblioteci¶
O bibliotecă (sau modul) este o colecție de clase și funcții utile.
Python — bibliotecile se importă cu import:
import math # biblioteca matematică
import random # numere aleatoare
import datetime # lucru cu date și timp
print(math.pi) # 3.141592...
print(random.randint(1, 100)) # număr aleator între 1 și 100
print(datetime.datetime.now())# data și ora curentă
C++ — bibliotecile se includ cu #include:
#include <iostream> // pentru cout, cin
#include <cmath> // pentru funcții matematice
#include <string> // pentru clasa string
#include <vector> // pentru clasa vector
#include <algorithm> // pentru sort, max_element, etc.
4.6. Exemplu practic — utilizarea clasei datetime¶
from datetime import datetime, timedelta
# Obiect reprezentând data curentă
acum = datetime.now()
print(acum)
# Atribute
print(acum.year) # anul
print(acum.month) # luna
print(acum.day) # ziua
# Operații
peste_o_sapt = acum + timedelta(days=7)
print(peste_o_sapt)
✏️ Exerciții propuse — Capitolul 4¶
- Folosind clasa
str, citește un șir și afișează-l cu majuscule, apoi cu litere mici. - Folosind biblioteca
random, simulează aruncarea a două zaruri de 10 ori. - Folosind
math, calculează aria și circumferința unui cerc de rază dată.
Capitolul 5: Interfețe grafice (Tkinter)¶
5.1. De ce interfețe grafice?¶
Până acum am folosit interfață de tip consolă (text). Interfața grafică (GUI) oferă:
- Ferestre, butoane, casete de text.
- Experiență vizuală mai bună.
- Programul este „user-friendly”.
5.2. Primul program cu Tkinter¶
tkinter este biblioteca standard Python pentru GUI.
import tkinter as tk
# Crearea ferestrei principale
fereastra = tk.Tk()
fereastra.title("Prima mea aplicație")
fereastra.geometry("400x300") # lățime x înălțime
# Pornirea buclei de evenimente
fereastra.mainloop()
5.3. Label — etichete¶
import tkinter as tk
fereastra = tk.Tk()
fereastra.title("Salut")
eticheta = tk.Label(fereastra, text="Bună, lume!", font=("Arial", 20))
eticheta.pack(pady=20)
fereastra.mainloop()
5.4. Button — butoane¶
import tkinter as tk
def la_apasare():
eticheta.config(text="Ai apăsat butonul!")
fereastra = tk.Tk()
fereastra.geometry("300x200")
eticheta = tk.Label(fereastra, text="Apasă butonul de mai jos")
eticheta.pack(pady=10)
buton = tk.Button(fereastra, text="Apasă-mă!", command=la_apasare)
buton.pack(pady=10)
fereastra.mainloop()
5.5. Entry — casete de text¶
import tkinter as tk
def afiseaza_salut():
nume = caseta.get()
eticheta_rezultat.config(text=f"Salut, {nume}!")
fereastra = tk.Tk()
tk.Label(fereastra, text="Numele tău:").pack()
caseta = tk.Entry(fereastra, width=30)
caseta.pack(pady=5)
tk.Button(fereastra, text="Salută", command=afiseaza_salut).pack(pady=5)
eticheta_rezultat = tk.Label(fereastra, text="")
eticheta_rezultat.pack(pady=10)
fereastra.mainloop()
5.6. MessageBox¶
import tkinter as tk
from tkinter import messagebox
def alerta():
messagebox.showinfo("Info", "Salut!")
def intrebare():
raspuns = messagebox.askyesno("Întrebare", "Continui?")
print(raspuns) # True sau False
fereastra = tk.Tk()
tk.Button(fereastra, text="Info", command=alerta).pack()
tk.Button(fereastra, text="Întrebare", command=intrebare).pack()
fereastra.mainloop()
5.7. Metode de aranjare (Layout)¶
| Metodă | Descriere |
|---|---|
pack() |
Aranjare secvențială (sus, jos, stânga, dreapta) |
grid() |
Aranjare în tabel (rânduri, coloane) |
place() |
Poziționare absolută (x, y) |
Exemplu cu grid:
import tkinter as tk
fereastra = tk.Tk()
tk.Label(fereastra, text="Nume:").grid(row=0, column=0)
tk.Entry(fereastra).grid(row=0, column=1)
tk.Label(fereastra, text="Vârstă:").grid(row=1, column=0)
tk.Entry(fereastra).grid(row=1, column=1)
tk.Button(fereastra, text="Trimite").grid(row=2, column=0, columnspan=2)
fereastra.mainloop()
5.8. Aplicație completă — calculator al divizorilor¶
import tkinter as tk
from tkinter import messagebox
def calculeaza_divizori():
try:
n = int(caseta.get())
if n <= 0:
messagebox.showerror("Eroare", "Introdu un număr natural pozitiv!")
return
divizori = [d for d in range(1, n + 1) if n % d == 0]
rezultat.config(text=f"Divizori: {divizori}\nNumăr: {len(divizori)}")
except ValueError:
messagebox.showerror("Eroare", "Introdu un număr valid!")
fereastra = tk.Tk()
fereastra.title("Calculator divizori")
fereastra.geometry("400x250")
tk.Label(fereastra, text="Introdu un număr:", font=("Arial", 12)).pack(pady=10)
caseta = tk.Entry(fereastra, font=("Arial", 14))
caseta.pack(pady=5)
tk.Button(fereastra, text="Calculează divizorii",
command=calculeaza_divizori, bg="#4CAF50", fg="white").pack(pady=10)
rezultat = tk.Label(fereastra, text="", font=("Arial", 11), wraplength=380)
rezultat.pack(pady=10)
fereastra.mainloop()
5.9. Canvas — desenare grafică¶
import tkinter as tk
fereastra = tk.Tk()
canvas = tk.Canvas(fereastra, width=400, height=300, bg="white")
canvas.pack()
canvas.create_rectangle(50, 50, 150, 100, fill="red")
canvas.create_oval(200, 50, 300, 150, fill="blue")
canvas.create_line(0, 200, 400, 200, fill="black", width=2)
canvas.create_text(200, 250, text="Desen cu Canvas", font=("Arial", 14))
fereastra.mainloop()
✏️ Exerciții propuse — Capitolul 5¶
- Construiește o aplicație care citește două numere din două casete și afișează suma lor la apăsarea unui buton.
- Realizează un „convertor de temperatură” (Celsius ↔ Fahrenheit) cu interfață grafică.
- Creează un quiz cu 3 întrebări cu variante de răspuns (radiobuttons).
Capitolul 6: Fișiere text¶
6.1. De ce fișiere?¶
Până acum datele introduse s-au pierdut la închiderea programului. Fișierele permit:
- Stocarea permanentă a datelor.
- Schimbul de date între programe.
- Lucrul cu volume mari de date.
6.2. Operații fundamentale¶
Cele 4 operații de bază:
- Deschidere — stabilirea legăturii cu fișierul.
- Citire / Scriere — transferul de date.
- Închidere — eliberarea resurselor.
6.3. Lucrul cu fișiere în Python¶
Deschiderea unui fișier¶
f = open("date.txt", "r") # citire (read)
f = open("date.txt", "w") # scriere (write) — șterge conținutul
f = open("date.txt", "a") # adăugare (append) la sfârșit
f = open("date.txt", "r+") # citire + scriere
Citirea dintr-un fișier¶
# Citirea întregului conținut
f = open("date.txt", "r")
continut = f.read()
print(continut)
f.close()
# Citirea linie cu linie
f = open("date.txt", "r")
for linie in f:
print(linie.strip()) # strip() elimină \n de la sfârșit
f.close()
# Citirea tuturor liniilor într-o listă
f = open("date.txt", "r")
linii = f.readlines()
f.close()
Scrierea într-un fișier¶
f = open("iesire.txt", "w")
f.write("Prima linie\n")
f.write("A doua linie\n")
f.close()
Gestionarea automată — with¶
Metoda recomandată: fișierul se închide automat.
with open("date.txt", "r") as f:
continut = f.read()
# Aici fișierul este deja închis
print(continut)
6.4. Exemplu complet — numere dintr-un fișier¶
Fișierul numere.txt:
10 25 3
17 8 42
99 1 56
Program — calculează suma tuturor numerelor:
suma = 0
with open("numere.txt", "r") as f:
for linie in f:
for cuvant in linie.split():
suma += int(cuvant)
print(f"Suma totală: {suma}")
# Scrierea rezultatului
with open("rezultat.txt", "w") as f:
f.write(f"Suma este: {suma}\n")
6.5. Fișiere text în C++¶
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
// Scriere
ofstream fout("iesire.txt");
fout << "Prima linie\n";
fout << "A doua linie\n";
fout.close();
// Citire — numere
ifstream fin("numere.txt");
int suma = 0, x;
while (fin >> x) {
suma += x;
}
fin.close();
cout << "Suma: " << suma << endl;
return 0;
}
6.6. Tratarea erorilor¶
Python:
try:
with open("fisier_inexistent.txt", "r") as f:
continut = f.read()
except FileNotFoundError:
print("Fișierul nu există!")
except PermissionError:
print("Nu ai permisiuni!")
C++:
ifstream fin("fisier.txt");
if (!fin.is_open()) {
cerr << "Nu pot deschide fișierul!" << endl;
return 1;
}
6.7. Problemă rezolvată — statistici din fișier¶
Citim numere dintr-un fișier și calculăm min, max, media, numărul de elemente.
def statistici(nume_fisier):
cu open(nume_fisier, "r") as f: # atenție: citim numere separate prin spații
continut = f.read()
numere = [int(x) for x in continut.split()]
if not numere:
print("Fișier gol!")
return
print(f"Elemente: {len(numere)}")
print(f"Minim: {min(numere)}")
print(f"Maxim: {max(numere)}")
print(f"Sumă: {sum(numere)}")
print(f"Medie: {sum(numere)/len(numere):.2f}")
statistici("numere.txt")
✏️ Exerciții propuse — Capitolul 6¶
- Citește un text dintr-un fișier și numără câte cuvinte conține.
- Copiază conținutul unui fișier în altul, transformând literele mici în majuscule.
- Citește numere dintr-un fișier și scrie în alt fișier doar numerele prime.
- Citește un fișier și afișează primele 5 linii.
Capitolul 7: Modelul conceptual liniar — lista¶
7.1. Ce este o listă?¶
O listă este o colecție de elemente dispuse liniar, în care:
- Fiecare element (cu excepția primului și ultimului) are un predecesor și un succesor.
- Ordinea contează.
- Putem avea elemente duplicate.
Exemple din realitate:
- Pasagerii într-un autobuz (dispuși pe rânduri).
- Cărțile pe un raft (de la stânga la dreapta).
- Notele unui elev în catalog (în ordinea introducerii).
7.2. Tipuri de liste după tipul de acces¶
a) Listă cu acces direct (indexată)¶
Putem accesa orice element direct, cunoscându-i poziția (index).
Exemplu: Catalogul clasei — putem vedea direct al 5-lea elev fără a parcurge primii 4.
clasa = ["Ana", "Bogdan", "Cristina", "Daniel", "Elena"]
print(clasa[4]) # "Elena" — accesul direct
b) Listă cu acces secvențial¶
Pentru a accesa un element, trebuie să parcurgem elementele de dinaintea lui.
Exemplu: Trenul pe șine — pentru a ajunge la vagonul 5, trebuie să treci prin 1, 2, 3, 4.
7.3. Stiva (Stack) — LIFO¶
LIFO = Last In, First Out (ultimul intrat, primul ieșit).
Analogie: Stiva de farfurii. Pui farfurii una peste alta. Când vrei să iei una, o iei pe cea de deasupra (ultima pusă).
Operații principale:
push(x)— adaugăxla vârf.pop()— elimină și returnează vârful.top()— vede vârful fără a-l elimina.
Aplicații:
- Funcția „Undo” (anulare ultimă acțiune).
- Evaluarea expresiilor matematice.
- Stivă de apeluri de funcții (call stack).
Implementare în Python¶
stiva = []
# Push
stiva.append(10)
stiva.append(20)
stiva.append(30)
print(stiva) # [10, 20, 30]
# Pop
x = stiva.pop()
print(x) # 30
print(stiva) # [10, 20]
# Top
print(stiva[-1]) # 20 (fără a elimina)
Implementare în C++¶
#include <stack>
using namespace std;
stack<int> s;
s.push(10);
s.push(20);
s.push(30);
cout << s.top(); // 30
s.pop();
cout << s.top(); // 20
7.4. Coada (Queue) — FIFO¶
FIFO = First In, First Out (primul intrat, primul ieșit).
Analogie: Coada la magazin. Primul care intră în rând este primul servit.
Operații:
enqueue(x)— adaugă la coada listei.dequeue()— elimină de la capul listei.
Aplicații:
- Imprimantele (documentele imprimă în ordinea trimiterii).
- Simularea cozilor din realitate.
- Procesarea evenimentelor.
Implementare în Python¶
coada = []
# Enqueue (adăugare la final)
coada.append("Ion")
coada.append("Maria")
coada.append("Alex")
# Dequeue (eliminare de la început)
primul = coada.pop(0)
print(primul) # "Ion"
print(coada) # ["Maria", "Alex"]
Implementare în C++¶
#include <queue>
using namespace std;
queue<int> q;
q.push(10);
q.push(20);
q.push(30);
cout << q.front(); // 10
q.pop();
cout << q.front(); // 20
7.5. Comparație stivă vs. coadă¶
| Criteriu | Stivă | Coadă |
|---|---|---|
| Regulă | LIFO | FIFO |
| Adăugare | La vârf | La coadă |
| Eliminare | De la vârf | De la cap |
| Analogie | Farfurii stivuite | Rând la casă |
| Aplicație tipică | Undo | Imprimantă |
7.6. Lista de frecvențe¶
O listă de frecvențe f pentru un set de valori este o listă în care f[i] reprezintă de câte ori apare valoarea i.
Exemplu: Într-un sondaj, avem notele (de la 1 la 5 stele):
[5, 3, 4, 5, 2, 5, 3, 5, 4, 1]
Lista de frecvențe este:
f[1] = 1(1 stea apare 1 dată)f[2] = 1(2 stele apar 1 dată)f[3] = 2(3 stele apar 2 ori)f[4] = 2(4 stele apar 2 ori)f[5] = 4(5 stele apar 4 ori)
Construcția listei de frecvențe¶
note = [5, 3, 4, 5, 2, 5, 3, 5, 4, 1]
frecvente = [0] * 6 # index 0..5
for nota in note:
frecvente[nota] += 1
for i in range(1, 6):
print(f"Nota {i}: {frecvente[i]} apariții")
int note[] = {5, 3, 4, 5, 2, 5, 3, 5, 4, 1};
int n = 10;
int frecvente[6] = {0}; // inițializat cu 0
for (int i = 0; i < n; i++)
frecvente[note[i]]++;
for (int i = 1; i <= 5; i++)
cout << "Nota " << i << ": " << frecvente[i] << endl;
Aplicații ale listei de frecvențe:
- Sortarea (vom vedea în Capitolul 10).
- Găsirea elementului cel mai frecvent (modulul).
- Statistici (histogramă).
7.7. Parcurgerea liniară¶
Parcurgere fără memorare — procesăm elementul curent fără a reține rezultate intermediare.
Problemă: Numără câți elevi au notă peste 7.
note = [9, 6, 8, 5, 10, 4, 7, 9, 8]
contor = 0
for n in note:
if n > 7:
contor += 1
print(contor) # 5
Parcurgere cu memorare — reținem informațiile relevante într-o altă structură.
Problemă: Găsește toți elevii cu notă peste medie.
note = [9, 6, 8, 5, 10, 4, 7, 9, 8]
media = sum(note) / len(note) # 7.33
peste_medie = []
for n in note:
if n > media:
peste_medie.append(n)
print(peste_medie) # [9, 8, 10, 9, 8]
7.8. Repere pentru parcurgere¶
Pentru a identifica perechi de elemente consecutive:
lista = [1, 2, 3, 4, 5]
# Parcurgem de la index 0 la len-2
for i in range(len(lista) - 1):
a = lista[i]
b = lista[i + 1]
print(f"({a}, {b})")
# (1,2) (2,3) (3,4) (4,5)
✏️ Exerciții propuse — Capitolul 7¶
- Implementează o stivă folosind doar o listă și scrie funcții
push,pop,top. - Folosind o stivă, inversează o listă.
- Construiește histogramul (lista de frecvențe) pentru literele unui cuvânt.
- Într-un magazin, simulează o coadă de clienți care intră și sunt serviți.
Capitolul 8: Clasa list din Python și vectori în C++¶
8.1. Clasa list — caracteristici¶
Clasa list din Python este predefinită și are următoarele caracteristici:
- Mutabilă — poate fi modificată după creare.
- Ordonată — elementele păstrează ordinea de inserare.
- Indexată — acces prin poziție (0, 1, 2, …).
- Eterogenă — poate conține tipuri diferite de date.
- Dimensiune dinamică — crește/scade automat.
8.2. Crearea listelor în Python¶
# Listă vidă
lista1 = []
lista2 = list()
# Listă cu valori inițiale
numere = [1, 2, 3, 4, 5]
nume = ["Ana", "Bogdan", "Cristina"]
mix = [1, "text", 3.14, True]
# Listă generată
patrate = [x*x for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
zerouri = [0] * 10 # [0,0,0,0,0,0,0,0,0,0]
# Din input
n = int(input("Câte numere: "))
numere = []
for i in range(n):
x = int(input(f"a[{i}] = "))
numere.append(x)
# Sau mai compact:
numere = [int(x) for x in input().split()] # "1 2 3 4" → [1, 2, 3, 4]
8.3. Acces la elemente¶
a = [10, 20, 30, 40, 50]
# Indexare directă (de la 0)
print(a[0]) # 10
print(a[4]) # 50
# Indexare negativă (de la sfârșit)
print(a[-1]) # 50
print(a[-2]) # 40
# Slicing
print(a[1:4]) # [20, 30, 40] — de la index 1 la 3 inclusiv
print(a[:3]) # [10, 20, 30] — primele 3
print(a[2:]) # [30, 40, 50] — de la index 2 la final
print(a[::2]) # [10, 30, 50] — din 2 în 2
print(a[::-1]) # [50, 40, 30, 20, 10] — inversat
8.4. Operatori specifici¶
| Operator | Descriere | Exemplu |
|---|---|---|
[] |
Acces la element | a[0] |
+ |
Concatenare | [1,2] + [3,4] = [1,2,3,4] |
* |
Multiplicare | [0]*3 = [0,0,0] |
in |
Apartenență | 3 in [1,2,3] → True |
not in |
Non-apartenență | 5 not in [1,2,3] → True |
== |
Egalitate | [1,2] == [1,2] → True |
<, >, <=, >= |
Comparație lexicografică | [1,2] < [1,3] → True |
a = [1, 2, 3]
b = [4, 5]
c = a + b # [1, 2, 3, 4, 5]
d = a * 3 # [1, 2, 3, 1, 2, 3, 1, 2, 3]
print(2 in a) # True
print(10 not in a) # True
print([1, 2] == [1, 2]) # True
8.5. Metode ale clasei list¶
Adăugare¶
a = [1, 2, 3]
a.append(4) # [1, 2, 3, 4] — la final
a.insert(0, 10) # [10, 1, 2, 3, 4] — la poziția 0
a.extend([5, 6]) # [10, 1, 2, 3, 4, 5, 6] — extinde cu altă listă
Eliminare¶
a = [1, 2, 3, 2, 4]
a.remove(2) # [1, 3, 2, 4] — elimină PRIMA apariție a lui 2
x = a.pop() # x = 4, a = [1, 3, 2]
y = a.pop(0) # y = 1, a = [3, 2]
a.clear() # a = []
Căutare și numărare¶
a = [1, 2, 3, 2, 4, 2]
print(a.count(2)) # 3 — de câte ori apare 2
print(a.index(3)) # 2 — poziția primei apariții a lui 3
# a.index(100) # eroare — nu este în listă
Ordonare și manipulare¶
a = [3, 1, 4, 1, 5, 9, 2, 6]
a.sort() # [1, 1, 2, 3, 4, 5, 6, 9] — modifică lista
a.sort(reverse=True) # [9, 6, 5, 4, 3, 2, 1, 1]
a.reverse() # inversează ordinea
b = sorted(a) # creează o listă NOUĂ sortată, nu modifică `a`
Copiere¶
# ATENȚIE: atribuirea directă NU face copie!
a = [1, 2, 3]
b = a # b și a se referă la ACEEAȘI listă
b.append(99)
print(a) # [1, 2, 3, 99] — modificat!
# Copie superficială
a = [1, 2, 3]
b = a.copy() # sau b = a[:] sau b = list(a)
b.append(99)
print(a) # [1, 2, 3] — neschimbat
print(b) # [1, 2, 3, 99]
8.6. Tabel sintetic — metode list¶
| Metodă | Acțiune | Modifică lista? |
|---|---|---|
append(x) |
Adaugă x la final |
Da |
insert(i, x) |
Inserează x la poziția i |
Da |
extend(lst) |
Extinde cu elementele din lst |
Da |
remove(x) |
Elimină prima apariție a lui x |
Da |
pop([i]) |
Elimină și returnează elementul de la poziția i (default: ultimul) |
Da |
clear() |
Elimină toate elementele | Da |
count(x) |
Returnează numărul de apariții ale lui x |
Nu |
index(x) |
Returnează poziția primei apariții a lui x |
Nu |
sort() |
Sortează crescător | Da |
reverse() |
Inversează ordinea | Da |
copy() |
Returnează o copie superficială | Nu |
8.7. Parcurgerea unei liste¶
a = [10, 20, 30, 40, 50]
# Prin valoare
for x in a:
print(x)
# Prin index
for i in range(len(a)):
print(f"a[{i}] = {a[i]}")
# Prin index și valoare (elegant)
for i, x in enumerate(a):
print(f"a[{i}] = {x}")
8.8. Vectori în C++¶
În C++ avem două opțiuni principale:
a) Tablou static¶
int a[100]; // tablou de 100 de elemente int
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
// Afișare
for (int i = 0; i < n; i++)
cout << a[i] << " ";
b) std::vector (recomandat — echivalent cu list din Python)¶
#include <vector>
#include <algorithm>
using namespace std;
vector<int> a; // vector vid
vector<int> b(10); // 10 elemente inițializate cu 0
vector<int> c(10, 5);// 10 elemente inițializate cu 5
vector<int> d = {1, 2, 3, 4, 5};
// Adăugare
a.push_back(10);
a.push_back(20);
a.insert(a.begin(), 0); // inserare la început
// Acces
cout << a[0] << endl;
cout << a.front() << endl; // primul
cout << a.back() << endl; // ultimul
cout << a.size() << endl; // dimensiune
// Eliminare
a.pop_back(); // ultimul element
a.erase(a.begin() + 1); // elementul de la poziția 1
a.clear(); // toate
// Sortare
sort(d.begin(), d.end());
// Parcurgere
for (int x : d)
cout << x << " ";
for (int i = 0; i < d.size(); i++)
cout << d[i] << " ";
8.9. Probleme rezolvate¶
Problema 1 — Numărul de apariții ale unei valori¶
def numar_aparitii(lista, valoare):
contor = 0
for x in lista:
if x == valoare:
contor += 1
return contor
# Echivalent cu: lista.count(valoare)
print(numar_aparitii([1, 2, 3, 2, 4, 2], 2)) # 3
Problema 2 — Elementele unice dintr-o listă¶
def elemente_unice(lista):
unice = []
for x in lista:
if x not in unice:
unice.append(x)
return unice
print(elemente_unice([1, 2, 3, 2, 4, 3, 5])) # [1, 2, 3, 4, 5]
Problema 3 — Găsirea perechilor consecutive cu aceeași paritate¶
def perechi_par_par(lista):
contor = 0
for i in range(len(lista) - 1):
if lista[i] % 2 == 0 and lista[i+1] % 2 == 0:
contor += 1
return contor
print(perechi_par_par([2, 4, 3, 6, 8, 1])) # 2: (2,4) și (6,8)
✏️ Exerciții propuse — Capitolul 8¶
- Citește
nnumere într-o listă și afișează-le în ordine inversă (fărăreverse()). - Calculează suma elementelor de pe pozițiile pare.
- Găsește al doilea element ca valoare (al doilea maxim).
- Șterge duplicatele dintr-o listă, păstrând ordinea.
- Rotește o listă la stânga cu k poziții.
Capitolul 9: Generarea sistematică a elementelor unei liste¶
9.1. Ce înseamnă generare sistematică?¶
Generarea sistematică = construirea unei liste în care elementele respectă o regulă clară, pas cu pas.
Tipuri de reguli:
- Formulă explicită:
a[i] = f(i)(ex:a[i] = i²) - Recurență:
a[i] = f(a[i-1], a[i-2], ...)(ex: Fibonacci) - Condiție: toate numerele până la
ncare respectă o proprietate.
9.2. Generare cu formulă explicită¶
Exemplu 1 — primele n pătrate perfecte¶
def patrate(n):
return [i*i for i in range(1, n+1)]
print(patrate(5)) # [1, 4, 9, 16, 25]
Exemplu 2 — primele n puteri ale lui 2¶
def puteri_doi(n):
return [2**i for i in range(n)]
print(puteri_doi(10)) # [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
9.3. Generare recurentă¶
Șir recurent: fiecare termen se calculează pe baza unor termeni anteriori.
Formula generală¶
a[0], a[1], ... — termeni inițiali (dați)
a[n] = f(a[n-1], a[n-2], ...) — relația de recurență
9.4. Șirul lui Fibonacci¶
Definiție:
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2), pentru n ≥ 2
Primii termeni: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …
Implementare iterativă (eficientă, O(n))¶
def fibonacci(n):
"""Returnează o listă cu primii n termeni Fibonacci."""
if n == 0:
return []
if n == 1:
return [0]
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fib
print(fibonacci(10)) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
#include <vector>
vector<int> fibonacci(int n) {
vector<int> fib;
if (n == 0) return fib;
fib.push_back(0);
if (n == 1) return fib;
fib.push_back(1);
for (int i = 2; i < n; i++)
fib.push_back(fib[i-1] + fib[i-2]);
return fib;
}
Implementare recursivă (elegantă dar INEFICIENTĂ — O(2ⁿ))¶
def fib_rec(n):
if n < 2:
return n
return fib_rec(n-1) + fib_rec(n-2)
print(fib_rec(10)) # 55
# print(fib_rec(50)) # foarte lent!
Lecție: Recursivitatea este elegantă, dar fără memorare poate duce la explozii exponențiale de timp.
9.5. Proporția de aur (φ)¶
Raportul a doi termeni consecutivi Fibonacci tinde la φ ≈ 1.618, numit numărul de aur.
fib = fibonacci(20)
for i in range(2, 20):
print(f"F({i})/F({i-1}) = {fib[i]/fib[i-1]:.6f}")
# Se apropie de 1.618034...
Aplicații ale proporției de aur:
- Arhitectură (Parthenonul).
- Artă (pictura renascentistă).
- Natură (spiralele cochiliilor, aranjarea semințelor de floarea-soarelui).
9.6. Problemă practică — investiție bancară¶
Problemă: Ai S lei depuși cu dobânda d% anual. După câți ani suma depășește T?
def ani_pentru_suma(S, d, T):
ani = 0
suma = S
while suma <= T:
suma = suma * (1 + d/100)
ani += 1
return ani, suma
ani, suma_finala = ani_pentru_suma(1000, 5, 2000)
print(f"După {ani} ani: {suma_finala:.2f}") # ~15 ani
9.7. Alte secvențe recurente clasice¶
Factorialul¶
n! = 1 * 2 * 3 * ... * n
0! = 1 (convenție)
Recurență: n! = n * (n-1)!
def factoriale(n):
fact = [1] # 0! = 1
for i in range(1, n+1):
fact.append(fact[i-1] * i)
return fact
print(factoriale(5)) # [1, 1, 2, 6, 24, 120]
Șirul triunghiular¶
T(n) = 1 + 2 + 3 + ... + n = n*(n+1)/2
def triunghiulare(n):
t = [0]
for i in range(1, n+1):
t.append(t[i-1] + i)
return t
print(triunghiulare(5)) # [0, 1, 3, 6, 10, 15]
9.8. Generare cu condiție¶
Problemă: Generează toate numerele naturale până la n care sunt divizibile cu 3 și 5.
def divizibile(n):
return [x for x in range(1, n+1) if x % 3 == 0 and x % 5 == 0]
print(divizibile(50)) # [15, 30, 45]
Problemă: Generează toate pătratele perfecte ≤ n.
def patrate_pana_la(n):
rezultat = []
i = 1
while i*i <= n:
rezultat.append(i*i)
i += 1
return rezultat
print(patrate_pana_la(100)) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
✏️ Exerciții propuse — Capitolul 9¶
- Generează primii
ntermeni ai șiruluia[i] = 2*a[i-1] + 1, cua[0] = 1. - Generează lista
[3, 6, 9, 12, ...]până lan. - Șirul Lucas:
L[0]=2, L[1]=1, L[n]=L[n-1]+L[n-2]. Generează primii 15 termeni. - Generează primele
nnumere prime. - Temperaturile dintr-un oraș cresc în medie cu 1.2% pe an. Știind temperatura inițială, determină în câți ani va depăși o valoare dată.
Capitolul 10: Metode de sortare¶
10.1. Ce este sortarea?¶
Sortarea = rearanjarea elementelor unei liste într-o ordine specificată (crescătoare sau descrescătoare).
Exemple din realitate:
- Aranjarea cărților în bibliotecă după nume.
- Ordonarea elevilor după medie.
- Aranjarea cărților de joc în mână.
10.2. Sortare prin selecția minimului (Selection Sort)¶
Idee¶
La fiecare pas, găsim cel mai mic element din partea nesortată și îl mutăm la începutul acesteia.
Algoritm¶
Pentru i de la 0 la n-2:
Găsim poziția minimului din a[i..n-1], să zicem poz_min.
Interschimbăm a[i] cu a[poz_min].
Vizualizare¶
Inițial: [5, 3, 8, 1, 9]
↓ minim: 1 la poz 3
Pas 1: [1, 3, 8, 5, 9] (schimbăm 5 și 1)
↓ minim din [3,8,5,9]: 3 la poz 1 (deja acolo)
Pas 2: [1, 3, 8, 5, 9]
↓ minim din [8,5,9]: 5 la poz 3
Pas 3: [1, 3, 5, 8, 9] (schimbăm 8 și 5)
↓ minim din [8,9]: 8
Pas 4: [1, 3, 5, 8, 9] (gata)
Implementare Python¶
def selection_sort(a):
n = len(a)
for i in range(n - 1):
poz_min = i
for j in range(i + 1, n):
if a[j] < a[poz_min]:
poz_min = j
# Interschimbare
a[i], a[poz_min] = a[poz_min], a[i]
return a
print(selection_sort([5, 3, 8, 1, 9])) # [1, 3, 5, 8, 9]
Implementare C++¶
void selection_sort(vector<int>& a) {
int n = a.size();
for (int i = 0; i < n - 1; i++) {
int poz_min = i;
for (int j = i + 1; j < n; j++)
if (a[j] < a[poz_min])
poz_min = j;
swap(a[i], a[poz_min]);
}
}
Complexitate¶
- Comparări:
(n-1) + (n-2) + ... + 1 = n(n-1)/2→ O(n²) - Interschimbări: maxim
n-1→ O(n) - Funcționează la fel indiferent de distribuția datelor (favorabil = defavorabil).
10.3. Sortarea cu listă de frecvențe (Counting Sort)¶
Idee¶
Dacă valorile sunt întregi într-un interval mic [0..k], putem număra aparițiile fiecărei valori și reconstitui lista sortată.
Algoritm¶
1. Construim lista de frecvențe f[0..k].
2. Parcurgem f de la 0 la k:
Scriem valoarea i de f[i] ori în lista rezultat.
Vizualizare¶
Inițial: [3, 1, 2, 3, 1, 2, 3]
Frecvențe: f[1]=2, f[2]=2, f[3]=3
Rezultat: [1, 1, 2, 2, 3, 3, 3]
Implementare Python¶
def counting_sort(a, val_max):
frecvente = [0] * (val_max + 1)
for x in a:
frecvente[x] += 1
rezultat = []
for i in range(val_max + 1):
for _ in range(frecvente[i]):
rezultat.append(i)
return rezultat
# Pentru note între 1 și 10
note = [7, 10, 5, 9, 7, 10, 6, 8, 9, 10]
print(counting_sort(note, 10)) # [5, 6, 7, 7, 8, 9, 9, 10, 10, 10]
Implementare C++¶
void counting_sort(vector<int>& a, int val_max) {
vector<int> f(val_max + 1, 0);
for (int x : a) f[x]++;
int idx = 0;
for (int i = 0; i <= val_max; i++)
while (f[i]-- > 0)
a[idx++] = i;
}
Complexitate¶
- Timp: O(n + k), unde k = valoarea maximă.
- Spațiu: O(k) pentru lista de frecvențe.
Avantaj: Foarte rapid dacă valorile sunt într-un interval mic.
Dezavantaj: Ineficient dacă k este foarte mare comparativ cu n.
Când să folosești: triaj de pacienți (valori 1-5), note școlare (1-10), categorii de produse.
10.4. Metoda bulelor (Bubble Sort)¶
Idee¶
Parcurgem lista în mod repetat, comparând elementele adiacente. Dacă sunt în ordine greșită, le interschimbăm. Procesul se repetă până când lista este sortată.
Vizualizare¶
Inițial: [5, 3, 8, 1, 9]
Pas 1: [3, 5, 8, 1, 9] (schimb 5 și 3)
[3, 5, 8, 1, 9] (5 < 8, nu se schimbă)
[3, 5, 1, 8, 9] (schimb 8 și 1)
[3, 5, 1, 8, 9] (8 < 9, nu se schimbă)
Pas 2: [3, 5, 1, 8, 9]
[3, 1, 5, 8, 9] (schimb 5 și 1)
...
Continuă până nu mai sunt schimbări.
Implementare Python — varianta de bază¶
def bubble_sort(a):
n = len(a)
for i in range(n):
for j in range(n - i - 1):
if a[j] > a[j+1]:
a[j], a[j+1] = a[j+1], a[j]
return a
print(bubble_sort([5, 3, 8, 1, 9])) # [1, 3, 5, 8, 9]
Implementare optimizată (oprire dacă nu s-au făcut schimbări)¶
def bubble_sort_opt(a):
n = len(a)
for i in range(n):
schimbat = False
for j in range(n - i - 1):
if a[j] > a[j+1]:
a[j], a[j+1] = a[j+1], a[j]
schimbat = True
if not schimbat:
break # lista este deja sortată
return a
Implementare C++¶
void bubble_sort(vector<int>& a) {
int n = a.size();
for (int i = 0; i < n; i++) {
bool schimbat = false;
for (int j = 0; j < n - i - 1; j++) {
if (a[j] > a[j+1]) {
swap(a[j], a[j+1]);
schimbat = true;
}
}
if (!schimbat) break;
}
}
Complexitate¶
- Caz favorabil (deja sortat, cu optimizare): O(n)
- Caz mediu și defavorabil: O(n²)
10.5. Comparație între metode¶
| Metodă | Timp (mediu) | Timp (cel mai rău) | Memorie adițională | Stabilă? |
|---|---|---|---|---|
| Selecția minimului | O(n²) | O(n²) | O(1) | Nu |
| Listă de frecvențe | O(n+k) | O(n+k) | O(k) | Da |
| Metoda bulelor | O(n²) | O(n²) | O(1) | Da |
Când să folosești fiecare:
- Selecția minimului: când interschimbările sunt costisitoare (garantează minim de schimbări).
- Listă de frecvențe: când valorile sunt în interval mic și avem multe elemente.
- Metoda bulelor: educațional; în practică se preferă alte metode.
💡 Notă: În practică, pentru sortări generale se folosesc algoritmi mai eficienți precum QuickSort sau MergeSort (O(n log n)). Python folosește intern TimSort. Pentru clasa a IX-a, metodele prezentate sunt suficiente.
10.6. Probleme rezolvate¶
Problema 1 — Primele k elemente mai mari¶
Din [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5], afișează cele mai mari 3 valori.
def top_k_mari(lista, k):
# Sortăm descrescător și luăm primele k
sortata = sorted(lista, reverse=True)
return sortata[:k]
print(top_k_mari([3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5], 3)) # [9, 6, 5]
Problema 2 — Triaj de pacienți¶
Într-o urgență, pacienții au coduri de gravitate 1-5 (5 fiind cel mai grav). Ordonează-i descrescător pentru a-i servi.
def triaj(pacienti):
"""Folosim counting sort pentru că avem interval mic."""
frecvente = [0] * 6 # 0..5
for cod in pacienti:
frecvente[cod] += 1
rezultat = []
# Descrescător — de la 5 la 1
for i in range(5, 0, -1):
for _ in range(frecvente[i]):
rezultat.append(i)
return rezultat
pacienti = [3, 1, 5, 2, 5, 4, 3, 1, 5]
print(triaj(pacienti)) # [5, 5, 5, 4, 3, 3, 2, 1, 1]
Problema 3 — Sortarea după două criterii¶
Elevi cu nume și notă. Sortare după notă descrescător, apoi alfabetic la egalitate.
elevi = [
("Ana", 9),
("Bogdan", 10),
("Cristina", 9),
("Daniel", 8)
]
# key = funcție care spune după ce sortăm
# -x[1] = sortare descrescătoare după notă
# x[0] = sortare alfabetică după nume
elevi_sortati = sorted(elevi, key=lambda x: (-x[1], x[0]))
print(elevi_sortati)
# [('Bogdan', 10), ('Ana', 9), ('Cristina', 9), ('Daniel', 8)]
✏️ Exerciții propuse — Capitolul 10¶
- Implementează selection sort care sortează descrescător.
- Sortează o listă de cuvinte în ordine alfabetică folosind metoda bulelor.
- Folosind counting sort, sortează literele dintr-un cuvânt.
- Sortează o listă de perechi
(nume, vârstă)după vârstă. - Numără câte interschimbări face bubble sort pentru o listă dată.
- Găsește al k-lea cel mai mic element fără a sorta complet lista.
Anexe¶
Anexa A — Recapitulare: Python vs. C++ — cheat sheet¶
| Concept | Python | C++ |
|---|---|---|
| Comentariu | # comentariu |
// comentariu sau /* ... */ |
| Importuri | import math |
#include <cmath> |
| Punct de intrare | codul direct | int main() { ... } |
| Afișare | print(x) |
cout << x |
| Citire | x = input() |
cin >> x |
| Delimitator bloc | indentare | { ... } |
| Definire funcție | def f(x): |
int f(int x) { ... } |
| Lista | lista = [1, 2, 3] |
vector<int> v = {1, 2, 3} |
| Lungime | len(lista) |
v.size() |
| Adaugă | lista.append(x) |
v.push_back(x) |
| Sortare | lista.sort() |
sort(v.begin(), v.end()) |
| String | s = "text" |
string s = "text" |
Anexa B — Probleme de proiect (pentru lucrul în echipă)¶
- Gestionar de note — aplicație GUI cu Tkinter care stochează notele într-un fișier text.
- Calculator științific — aplicație cu butoane pentru operații matematice.
- Simulare de bursă — ține evidența prețurilor unor acțiuni, calculează statistici.
- Quiz de matematică — aplicație care generează probleme, verifică răspunsurile, păstrează scoruri.
- Agenda personală — adaugă, căutare, ștergere de contacte într-un fișier.
- Analiză de text — număr de cuvinte, histogramă de litere, cuvinte frecvente.
- Joc „Ghici numărul” — cu interfață grafică și scor păstrat în fișier.
Anexa C — Resurse utile online¶
Vizualizări interactive¶
- VisuAlgo — animații pentru sortare, structuri de date.
- Python Tutor — vizualizare pas cu pas a execuției codului.
- Algorithm Visualizer — algoritmi animați.
Platforme de exerciții¶
- pbinfo.ro — probleme pentru gimnaziu și liceu.
- Codeforces — concursuri de programare.
- HackerRank — exerciții gradate.
Documentație¶
Anexa D — Glosar de termeni¶
| Termen | Definiție |
|---|---|
| Algoritm | Succesiune finită și precisă de pași pentru rezolvarea unei probleme. |
| Variabilă | Locație de memorie cu un nume, ce stochează o valoare. |
| Listă / Vector / Tablou | Colecție ordonată de elemente accesibile prin index. |
| Index | Poziția unui element într-o listă (începe de la 0 în Python și C++). |
| Subprogram / Funcție | Secvență de cod nominalizată care execută o sarcină. |
| Parametru | Variabilă folosită pentru a transmite date unei funcții. |
| Argument | Valoarea concretă transmisă când apelăm o funcție. |
| Complexitate | Măsura eficienței unui algoritm în funcție de dimensiunea intrării. |
| LIFO | Last In, First Out — principiu de acces al stivei. |
| FIFO | First In, First Out — principiu de acces al cozii. |
| Iterație | O singură execuție a corpului unei bucle. |
| Recursivitate | Tehnică prin care o funcție se apelează pe sine. |
| Modularizare | Împărțirea unui program în module independente. |
| GUI | Graphical User Interface — interfață grafică. |
| IDE | Integrated Development Environment — mediu integrat de dezvoltare. |
Anexa E — Pseudocodul programei — referință rapidă¶
// Citire/Scriere
citește a, b
scrie "Rezultat:", x
// Atribuire
x ← 5
// Decizie
dacă a > b atunci
scrie a
altfel
scrie b
sfârșit dacă
// Repetitivă cu test inițial
cât timp i <= n execută
...
sfârșit cât timp
// Repetitivă cu test final
repetă
...
până când condiție
// Repetitivă cu contor
pentru i ← 1, n execută
...
sfârșit pentru
// Subprogram
subprogram dublu(x) returnează întreg
return 2 * x
sfârșit subprogram
apel dublu(5)
🎓 Încheiere¶
Ai parcurs integral materia de clasa a IX-a! Cursul a acoperit:
✅ Principiile elaborării programelor
✅ Prelucrări ale numerelor (CMMDC, divizori, baze)
✅ Subprograme și modularitate
✅ POO și clase predefinite
✅ Interfețe grafice (Tkinter)
✅ Fișiere text
✅ Modelul conceptual liniar (listă, stivă, coadă)
✅ Clasa list din Python / vector din C++
✅ Generarea sistematică (Fibonacci, secvențe recurente)
✅ Metode de sortare (selecție, frecvențe, bule)
Recomandări pentru continuare:
- Practică zilnică — rezolvă cel puțin o problemă pe zi pe pbinfo.ro.
- Proiecte personale — aplică ce ai învățat în proiecte care te pasionează (jocuri, aplicații utilitare).
- Contribuie — participă la cercuri de informatică, olimpiade locale.
- Aprofundează — explorează structuri mai complexe (dicționare, seturi) și biblioteci (NumPy, Pandas).
- Programează zilnic — fluența vine din repetiție.
„Programarea nu este despre a scrie cod — este despre a gândi.”
Document generat în conformitate cu Programa școlară pentru disciplina Informatică, clasa a IX-a, curriculum de specialitate, Ordin MEC 4.350/2025.