Author: admin

  • Operații asupra Cifrelor unui Număr: “Dezmembrarea” unui Număr în Cifre

    Bun, hai să vorbim despre unul dintre cele mai fundamentale și utile algoritme din programare: OPERATIILE CU CIFRELE UNUI NUMAR. Nu e doar despre cifre (cuvânt simplu) și descompunere. E despre cum transformi un număr întreg într-o colecție de cifre pe care le poți analiza, modifica și manipula. E un concept atât de esențial încât aproape orice problemă cu numerele începe cu “ia cifrele numărului”.

    1. Ce înseamnă “Operații asupra Cifrelor”? “Spargerea Numărului”

    Gândește-te la un număr ca la un tren cu vagoane: fiecare vagon este o cifră, iar tu vrei să:

    • Numări câte vagoane are (câte cifre)
    • Vezi ce e în fiecare vagon (care e fiecare cifră)
    • Schimbi ordinea vagoanelor (inversezi numărul)
    • Aduni ce e în vagoane (suma cifrelor)

    Analogie cu un PIN de telefon:

    PIN: 1 9 8 4

    • Numărul de cifre: 4
    • Suma cifrelor: 1+9+8+4 = 22
    • Cifra maximă: 9
    • Numărul invers: 4 8 9 1

    2. Cum Extragem Cifrele unui Număr? “Diviziunea cu 10”

    Secretul: Folosim operațiile % 10 și / 10 pe numere întregi!

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 1234;
    
        cout << "Numarul initial: " << numar << endl;
        cout << "Extragem cifrele de la dreapta la stanga:\n\n";
    
        while(numar > 0) {
            int cifra = numar % 10;      // Ia ultima cifră
            cout << "Cifra: " << cifra << endl;
    
            numar = numar / 10;          // Elimină ultima cifră
            cout << "Numar ramas: " << numar << endl;
        }
    
        return 0;
    }

    Ce se întâmplă pas cu pas:

    Start: numar = 1234
    
    Pasul 1: cifra = 1234 % 10 = 4, numar = 1234 / 10 = 123
    Pasul 2: cifra = 123 % 10 = 3, numar = 123 / 10 = 12  
    Pasul 3: cifra = 12 % 10 = 2, numar = 12 / 10 = 1
    Pasul 4: cifra = 1 % 10 = 1, numar = 1 / 10 = 0 (STOP)

    3. Algoritmi Elementari cu Cifre

    3.1 Numărul de Cifre

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 12345;
        int copie = numar;
        int contor = 0;
    
        while(copie > 0) {
            contor++;
            copie = copie / 10;  // Elimină o cifră
        }
    
        cout << "Numarul " << numar << " are " << contor << " cifre" << endl;
        return 0;
    }

    3.2 Suma Cifrelor

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 1234;
        int suma = 0;
        int copie = numar;
    
        while(copie > 0) {
            suma += copie % 10;  // Adaugă ultima cifră
            copie /= 10;         // Elimină ultima cifră
        }
    
        cout << "Suma cifrelor lui " << numar << " este: " << suma << endl;
        return 0;
    }

    3.3 Cifra Maximă

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 5298;
        int maxim = 0;
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
            if(cifra > maxim) {
                maxim = cifra;
            }
            copie /= 10;
        }
    
        cout << "Cifra maxima din " << numar << " este: " << maxim << endl;
        return 0;
    }

    3.4 Numărul Invers

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 1234;
        int invers = 0;
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
            invers = invers * 10 + cifra;  // Construiește inversul
            copie /= 10;
        }
    
        cout << "Inversul lui " << numar << " este: " << invers << endl;
        return 0;
    }

    Cum funcționează inversul:

    Start: invers = 0, numar = 1234
    
    Pasul 1: cifra = 4, invers = 0*10 + 4 = 4
    Pasul 2: cifra = 3, invers = 4*10 + 3 = 43  
    Pasul 3: cifra = 2, invers = 43*10 + 2 = 432
    Pasul 4: cifra = 1, invers = 432*10 + 1 = 4321

    3.5 Verificare Palindrom

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 12321;
        int invers = 0;
        int copie = numar;
    
        // Construiește inversul
        while(copie > 0) {
            invers = invers * 10 + (copie % 10);
            copie /= 10;
        }
    
        // Verifică dacă e palindrom
        if(numar == invers) {
            cout << numar << " este palindrom!" << endl;
        } else {
            cout << numar << " NU este palindrom!" << endl;
        }
    
        return 0;
    }

    3.6 Numărul de Cifre Pare/Impare

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 123456;
        int pare = 0, impare = 0;
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
    
            if(cifra % 2 == 0) {
                pare++;
            } else {
                impare++;
            }
    
            copie /= 10;
        }
    
        cout << "In " << numar << ":\n";
        cout << "- Cifre pare: " << pare << endl;
        cout << "- Cifre impare: " << impare << endl;
    
        return 0;
    }

    4. Operații Combinatorii

    4.1 Suma cifrelor cu condiție

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 52983;
        int sumaPare = 0;
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
    
            if(cifra % 2 == 0) {  // Dacă e pară
                sumaPare += cifra;
            }
    
            copie /= 10;
        }
    
        cout << "Suma cifrelor pare din " << numar << " este: " << sumaPare << endl;
        return 0;
    }

    4.2 Produsul cifrelor

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 234;
        int produs = 1;
        int copie = numar;
    
        while(copie > 0) {
            produs *= (copie % 10);  // Înmulțește cu cifra
            copie /= 10;
        }
    
        cout << "Produsul cifrelor lui " << numar << " este: " << produs << endl;
        return 0;
    }

    4.3 Cifra minimă și maximă în același timp

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 52981;
        int minim = 9;  // Inițializez cu cea mai mare cifră
        int maxim = 0;  // Inițializez cu cea mai mică cifră
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
    
            if(cifra < minim) minim = cifra;
            if(cifra > maxim) maxim = cifra;
    
            copie /= 10;
        }
    
        cout << "In " << numar << ":\n";
        cout << "- Cifra minima: " << minim << endl;
        cout << "- Cifra maxima: " << maxim << endl;
    
        return 0;
    }

    5. Transformări Avansate

    5.1 Înlocuirea unei cifre

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 12343;
        int vechi = 3;
        int nou = 7;
        int rezultat = 0;
        int putere = 1;
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
    
            if(cifra == vechi) {
                cifra = nou;  // Înlocuiește cifra
            }
    
            rezultat = cifra * putere + rezultat;
            putere *= 10;
            copie /= 10;
        }
    
        cout << "Numarul " << numar << " cu " << vechi 
             << " inlocuit cu " << nou << " devine: " << rezultat << endl;
    
        return 0;
    }

    5.2 Eliminarea unei cifre

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 12343;
        int cifraDeEliminat = 3;
        int rezultat = 0;
        int putere = 1;
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
    
            if(cifra != cifraDeEliminat) {  // Păstrează doar cifrele diferite
                rezultat = cifra * putere + rezultat;
                putere *= 10;
            }
    
            copie /= 10;
        }
    
        cout << "Numarul " << numar << " fara cifra " 
             << cifraDeEliminat << " devine: " << rezultat << endl;
    
        return 0;
    }

    5.3 Sortarea cifrelor (crescător)

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 52981;
        int rezultat = 0;
    
        // Verifică fiecare cifră de la 0 la 9
        for(int cifraCurenta = 0; cifraCurenta <= 9; cifraCurenta++) {
            int copie = numar;
    
            while(copie > 0) {
                if(copie % 10 == cifraCurenta) {
                    rezultat = rezultat * 10 + cifraCurenta;
                }
                copie /= 10;
            }
        }
    
        cout << "Cifrele lui " << numar << " sortate: " << rezultat << endl;
        return 0;
    }

    6. Probleme Practice

    Problema 1: Verifică dacă toate cifrele sunt pare

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 2468;
        int copie = numar;
        bool toatePare = true;
    
        while(copie > 0) {
            if((copie % 10) % 2 != 0) {  // Dacă cifra e impară
                toatePare = false;
                break;
            }
            copie /= 10;
        }
    
        if(toatePare) {
            cout << numar << " are toate cifrele pare!" << endl;
        } else {
            cout << numar << " NU are toate cifrele pare!" << endl;
        }
    
        return 0;
    }

    Problema 2: Numără de câte ori apare o cifră

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 12342343;
        int cifraCautata = 3;
        int aparitii = 0;
        int copie = numar;
    
        while(copie > 0) {
            if(copie % 10 == cifraCautata) {
                aparitii++;
            }
            copie /= 10;
        }
    
        cout << "Cifra " << cifraCautata << " apare de " 
             << aparitii << " ori in " << numar << endl;
    
        return 0;
    }

    Problema 3: Cea mai mică și cea mai mare cifră

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 52981;
        int minim = 9, maxim = 0;
        int copie = numar;
    
        while(copie > 0) {
            int cifra = copie % 10;
            minim = (cifra < minim) ? cifra : minim;
            maxim = (cifra > maxim) ? cifra : maxim;
            copie /= 10;
        }
    
        cout << "In " << numar << ":\n";
        cout << "Minim: " << minim << "\nMaxim: " << maxim << endl;
    
        return 0;
    }

    7. Algoritmul Universal: Schema de Bază

    Schema pentru aproape orice operație cu cifre:

    int numar = /* numărul tău */;
    int copie = numar;  // Mereu lucrează pe o copie!
    
    while(copie > 0) {
        int cifra = copie % 10;  // Ia ultima cifră
    
        // AICI FACI CE VREI CU CIFRA!
        // - Numări
        // - Aduni
        // - Verifici condiții
        // - Modifici
    
        copie = copie / 10;  // Elimină ultima cifră
    }

    8. Cazuri Speciale

    8.1 Numărul 0 are o cifră!

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 0;
    
        // ATENȚIE: while(numar > 0) nu se execută deloc pentru 0!
        // Soluție: tratare specială
    
        if(numar == 0) {
            cout << "Numarul 0 are 1 cifra (cifra 0)" << endl;
        }
    
        return 0;
    }

    8.2 Numere negative

    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = -1234;
    
        // Pentru numere negative, lucrează cu valoarea absolută
        if(numar < 0) {
            numar = -numar;  // Face pozitiv
        }
    
        // Acum poți lucra normal cu cifrele
        cout << "Cifrele lui " << numar << ":\n";
        while(numar > 0) {
            cout << numar % 10 << " ";
            numar /= 10;
        }
    
        return 0;
    }

    9. Exerciții de Înțelegere

    Exercițiul 1: Ce face acest algoritm?

    int numar = 12345;
    int rezultat = 0;
    
    while(numar > 0) {
        rezultat += (numar % 10) * (numar % 10);
        numar /= 10;
    }
    
    cout << rezultat;

    Răspuns: Calculează suma pătratelor cifrelor: 1² + 2² + 3² + 4² + 5² = 55

    Exercițiul 2: Completează algoritmul

    int numar = 1234;
    int produs = 1;
    
    while(/* condiție */) {
        produs *= /* ultima cifră */;
        numar = /* elimină ultima cifră */;
    }
    
    cout << produs;

    Soluție:

    while(numar > 0) {
        produs *= (numar % 10);
        numar = numar / 10;
    }

    Exercițiul 3: Transformă acest număr

    Input: 12345
    Output: 135  (cifrele impare în ordinea originală)

    Soluție:

    int numar = 12345;
    int rezultat = 0;
    int putere = 1;
    
    while(numar > 0) {
        int cifra = numar % 10;
    
        if(cifra % 2 != 0) {  // Dacă e impară
            rezultat = cifra * putere + rezultat;
            putere *= 10;
        }
    
        numar /= 10;
    }

    În concluzie, să-ți spun ceva fundamental:

    Operațiile cu cifre sunt baza pentru multe algoritmi mai complecși. Dacă înțelegi cum să “dezmembrezi” un număr în cifre, poți rezolva o gamă uriașă de probleme.

    Regula de aur:

    • numar % 10 → ultima cifră
    • numar / 10 → numărul fără ultima cifră
    • Întotdeauna lucrează pe o copie a numărului original!

    Așa că ai grijă când lucrezi cu cifre. Cunoștințe-ti operațiile de bază și construiește de acolo algoritmi mai complecși. Pentru că puterea de a manipula numerele cifră cu cifră este una dintre cele mai importante abilități în programare.

  • Diagonalele Matricelor: “Cele Două Cruci” ale Matricei Pătratice – Materie BAC

    Bun, hai să vorbim despre un concept care pare matematic dar e de fapt foarte vizual: DIAGONALELE MATRICELOR. Nu e doar despre linii (cuvânt simplu) și poziții. E despre cum identifici elementele speciale dintr-o matrice pătratică, cele care stau pe cele două “diagonale” importante. E un concept atât de elegant încât dacă ai privi o matrice pătratică, ai vedea imediat cele două diagonale ca două cruci care o împart.

    1. Ce sunt Diagonalele? “Cele Două Linii Speciale”

    Gândește-te la diagonale ca la cele două linii care traversează o matrice pătratică:

    • Diagonala principală: De la stânga-sus la dreapta-jos (ca )
    • Diagonala secundară: De la dreapta-sus la stânga-jos (ca /)

    Analogie cu o Tablă de Șah:

    Pe tabla de șah 8×8:

    • Diagonala principală: de la a1 la h8 (alb-stânga-sus la negru-dreapta-jos)
    • Diagonala secundară: de la h1 la a8 (alb-dreapta-sus la negru-stânga-jos)

    2. Matricea Pătratică: “Terenul de Joacă”

    ATENȚIE: Diagonalele există DOAR la matrice pătratice (nr. rânduri = nr. coloane)!

    #include <iostream>
    using namespace std;
    
    int main() {
        // Matrice pătratică 4x4
        int matrice[4][4] = {
            { 1,  2,  3,  4},
            { 5,  6,  7,  8},
            { 9, 10, 11, 12},
            {13, 14, 15, 16}
        };
    
        cout << "Matricea patratica 4x4:\n";
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                cout << matrice[i][j] << "\t";
            }
            cout << endl;
        }
    
        return 0;
    }

    3. Diagonala Principală: “Linia Identității”

    Regula de aur: Pe diagonala principală, indicele de rând = indicele de coloană!

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[4][4] = {
            {10, 20, 30, 40},
            {50, 60, 70, 80},
            {90, 10, 11, 12},
            {13, 14, 15, 16}
        };
    
        cout << "=== DIAGONALA PRINCIPALA ===\n";
        cout << "Regula: elementele unde i == j\n\n";
    
        cout << "Elementele de pe diagonala principala: ";
        for(int i = 0; i < 4; i++) {
            cout << matrice[i][i] << " ";  // i == j
        }
        cout << endl;
    
        // Demonstrație vizuală
        cout << "\nMatricea cu diagonala principala marcata:\n";
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                if(i == j) {
                    cout << "[" << matrice[i][j] << "]\t";  // În paranteze
                } else {
                    cout << " " << matrice[i][j] << " \t";  // Fără paranteze
                }
            }
            cout << endl;
        }
    
        return 0;
    }

    Ce elemente sunt pe diagonala principală:

    Matrice 4x4:
    [10]   20    30    40
     50   [60]   70    80
     90    10   [11]   12
     13    14    15   [16]
    
    Diagonala principala: [10] [60] [11] [16]

    4. Diagonala Secundară: “Linia Oglindită”

    Regula de aur: Pe diagonala secundară, indicele de rând + indicele de coloană = n-1 (unde n e dimensiunea matricei)!

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[4][4] = {
            {10, 20, 30, 40},
            {50, 60, 70, 80},
            {90, 10, 11, 12},
            {13, 14, 15, 16}
        };
    
        cout << "=== DIAGONALA SECUNDARA ===\n";
        cout << "Regula: elementele unde i + j == n-1 (n=4, deci i+j==3)\n\n";
    
        cout << "Elementele de pe diagonala secundara: ";
        for(int i = 0; i < 4; i++) {
            int j = 3 - i;  // Pentru că i + j = 3
            cout << matrice[i][j] << " ";
        }
        cout << endl;
    
        // Demonstrație vizuală
        cout << "\nMatricea cu diagonala secundara marcata:\n";
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                if(i + j == 3) {  // i + j = n-1 = 3
                    cout << "[" << matrice[i][j] << "]\t";
                } else {
                    cout << " " << matrice[i][j] << " \t";
                }
            }
            cout << endl;
        }
    
        return 0;
    }

    Ce elemente sunt pe diagonala secundară:

    Matrice 4x4:
     10    20    30   [40]
     50    60   [70]   80
     90   [10]   11    12
    [13]   14    15    16
    
    Diagonala secundara: [40] [70] [10] [13]

    5. Comparație Directă între Cele Două Diagonale

    #include <iostream>
    using namespace std;
    
    int main() {
        const int n = 5;  // Matrice 5x5
        int matrice[n][n];
    
        // Umple matricea cu numere consecutive
        int contor = 1;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                matrice[i][j] = contor++;
            }
        }
    
        cout << "Matricea 5x5:\n";
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                cout << matrice[i][j] << "\t";
            }
            cout << endl;
        }
    
        cout << "\n=== COMPARATIE DIAGONALE ===\n\n";
    
        // Diagonala principala
        cout << "Diagonala principala (i == j):\n";
        cout << "Pozitii: ";
        for(int i = 0; i < n; i++) {
            cout << "[" << i << "][" << i << "] ";
        }
        cout << "\nValori:  ";
        for(int i = 0; i < n; i++) {
            cout << matrice[i][i] << "        ";
        }
    
        cout << "\n\nDiagonala secundara (i + j == n-1):\n";
        cout << "Pozitii: ";
        for(int i = 0; i < n; i++) {
            int j = n - 1 - i;
            cout << "[" << i << "][" << j << "] ";
        }
        cout << "\nValori:  ";
        for(int i = 0; i < n; i++) {
            int j = n - 1 - i;
            cout << matrice[i][j] << "        ";
        }
    
        return 0;
    }

    6. Operații cu Diagonalele

    6.1 Suma elementelor de pe diagonala principală

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
    
        int sumaDiagonalaPrincipala = 0;
    
        for(int i = 0; i < 3; i++) {
            sumaDiagonalaPrincipala += matrice[i][i];
        }
    
        cout << "Suma diagonalei principale: " 
             << sumaDiagonalaPrincipala << endl;  // 1+5+9 = 15
    
        return 0;
    }

    6.2 Suma elementelor de pe diagonala secundară

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
    
        int sumaDiagonalaSecundara = 0;
        int n = 3;  // Dimensiunea matricei
    
        for(int i = 0; i < n; i++) {
            int j = n - 1 - i;  // Calculăm coloana
            sumaDiagonalaSecundara += matrice[i][j];
        }
    
        cout << "Suma diagonalei secundare: " 
             << sumaDiagonalaSecundara << endl;  // 3+5+7 = 15
    
        return 0;
    }

    6.3 Compararea sumelor diagonalelor

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[4][4] = {
            {1, 0, 0, 2},
            {0, 3, 4, 0},
            {0, 5, 6, 0},
            {7, 0, 0, 8}
        };
    
        int sumaPrincipala = 0;
        int sumaSecundara = 0;
        int n = 4;
    
        // Calcul ambele sume într-o singură parcurgere
        for(int i = 0; i < n; i++) {
            // Diagonala principala
            sumaPrincipala += matrice[i][i];
    
            // Diagonala secundara
            int j = n - 1 - i;
            sumaSecundara += matrice[i][j];
        }
    
        cout << "Suma diagonalei principale: " << sumaPrincipala << endl;
        cout << "Suma diagonalei secundare: " << sumaSecundara << endl;
    
        if(sumaPrincipala > sumaSecundara) {
            cout << "Diagonala principala are suma mai mare!\n";
        } else if(sumaPrincipala < sumaSecundara) {
            cout << "Diagonala secundara are suma mai mare!\n";
        } else {
            cout << "Sumele sunt egale!\n";
        }
    
        return 0;
    }

    7. Zonele Matricei Definite de Diagonale

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[5][5];
        int n = 5;
    
        // Umple matricea cu numere consecutive
        int contor = 1;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                matrice[i][j] = contor++;
            }
        }
    
        cout << "=== ZONELE MATRICEI ===\n\n";
    
        // 1. Deasupra diagonalei principale (i < j)
        cout << "Deasupra diagonalei principale (i < j):\n";
        for(int i = 0; i < n; i++) {
            for(int j = i + 1; j < n; j++) {  // j > i
                cout << matrice[i][j] << " ";
            }
        }
        cout << endl;
    
        // 2. Sub diagonala principală (i > j)
        cout << "\nSub diagonala principala (i > j):\n";
        for(int i = 1; i < n; i++) {          // i > 0
            for(int j = 0; j < i; j++) {      // j < i
                cout << matrice[i][j] << " ";
            }
        }
        cout << endl;
    
        // 3. Deasupra diagonalei secundare (i + j < n-1)
        cout << "\nDeasupra diagonalei secundare (i + j < n-1):\n";
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(i + j < n - 1) {
                    cout << matrice[i][j] << " ";
                }
            }
        }
        cout << endl;
    
        // 4. Sub diagonala secundară (i + j > n-1)
        cout << "\nSub diagonala secundara (i + j > n-1):\n";
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(i + j > n - 1) {
                    cout << matrice[i][j] << " ";
                }
            }
        }
    
        return 0;
    }

    8. Matricea Unitate: “Cea mai Simplă Matrice”

    Matricea unitate are 1 pe diagonala principală și 0 în rest. E ca “1” pentru matrice!

    #include <iostream>
    using namespace std;
    
    int main() {
        const int n = 4;
        int unitate[n][n];
    
        // Construiește matricea unitate
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(i == j) {
                    unitate[i][j] = 1;  // Pe diagonala principala
                } else {
                    unitate[i][j] = 0;  // In rest
                }
            }
        }
    
        cout << "Matricea unitate " << n << "x" << n << ":\n";
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                cout << unitate[i][j] << " ";
            }
            cout << endl;
        }
    
        // Varianta mai eficientă
        cout << "\nMatricea unitate (initializare directa):\n";
        int unitate2[n][n] = {0};  // Toate elementele 0
    
        for(int i = 0; i < n; i++) {
            unitate2[i][i] = 1;  // Pune 1 doar pe diagonala principala
        }
    
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                cout << unitate2[i][j] << " ";
            }
            cout << endl;
        }
    
        return 0;
    }

    9. Probleme Practice cu Diagonalele

    Problema 1: Verifică dacă o matrice este simetrică față de diagonala principală

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {1, 2, 3},
            {2, 4, 5},
            {3, 5, 6}
        };
    
        bool esteSimetrica = true;
        int n = 3;
    
        // Verifică simetria
        for(int i = 0; i < n; i++) {
            for(int j = i + 1; j < n; j++) {
                // Compară elementul de deasupra diagonalei cu cel de sub diagonala
                if(matrice[i][j] != matrice[j][i]) {
                    esteSimetrica = false;
                    break;
                }
            }
            if(!esteSimetrica) break;
        }
    
        if(esteSimetrica) {
            cout << "Matricea este simetrica fata de diagonala principala!\n";
        } else {
            cout << "Matricea NU este simetrica.\n";
        }
    
        return 0;
    }

    Problema 2: Schimbă diagonalele între ele

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[4][4] = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 16}
        };
    
        cout << "Matricea initiala:\n";
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                cout << matrice[i][j] << "\t";
            }
            cout << endl;
        }
    
        // Schimbă diagonalele
        int n = 4;
        for(int i = 0; i < n; i++) {
            // Elementul de pe diagonala principala
            int temp = matrice[i][i];
    
            // Elementul de pe diagonala secundara
            int j = n - 1 - i;
    
            // Schimbă-le
            matrice[i][i] = matrice[i][j];
            matrice[i][j] = temp;
        }
    
        cout << "\nDupa schimbarea diagonalelor:\n";
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                cout << matrice[i][j] << "\t";
            }
            cout << endl;
        }
    
        return 0;
    }

    Problema 3: Verifică dacă o matrice este “magică” pe diagonale

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {2, 9, 4},
            {7, 5, 3},
            {6, 1, 8}
        };
    
        int n = 3;
        int sumaPrincipala = 0;
        int sumaSecundara = 0;
    
        // Calculează sumele diagonalelor
        for(int i = 0; i < n; i++) {
            sumaPrincipala += matrice[i][i];
            sumaSecundara += matrice[i][n-1-i];
        }
    
        cout << "Suma diagonalei principale: " << sumaPrincipala << endl;
        cout << "Suma diagonalei secundare: " << sumaSecundara << endl;
    
        if(sumaPrincipala == sumaSecundara) {
            cout << "Diagonalele au aceeasi suma!\n";
    
            // Bonus: verifică și sumele rândurilor
            bool toateEgale = true;
            int sumaReferinta = sumaPrincipala;
    
            for(int i = 0; i < n; i++) {
                int sumaRand = 0;
                for(int j = 0; j < n; j++) {
                    sumaRand += matrice[i][j];
                }
    
                if(sumaRand != sumaReferinta) {
                    toateEgale = false;
                    break;
                }
            }
    
            if(toateEgale) {
                cout << "MATRICE MAGICA! Toate sumele sunt egale cu " << sumaReferinta << endl;
            }
        }
    
        return 0;
    }

    10. Diagonale în Matrici de Dimensiuni Impar vs Par

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "=== DIFERENTE DIMENSIUNI IMPAR vs PAR ===\n\n";
    
        // Matrice 3x3 (impar)
        cout << "Matrice 3x3 (n=impar):\n";
        cout << "Elementul central: matrice[1][1]\n";
        cout << "Apare pe AMBELE diagonale!\n";
        cout << "Diagonalele se INTERSECTEAZA in centru.\n\n";
    
        // Matrice 4x4 (par)  
        cout << "Matrice 4x4 (n=par):\n";
        cout << "Nu exista 'element central' unic\n";
        cout << "Diagonalele NU se intersecteaza\n";
        cout << "Cele 4 elemente centrale: [1][1], [1][2], [2][1], [2][2]\n";
    
        return 0;
    }

    11. Cum Gândești cu Diagonalele: “Reguli Memorabile”

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "=== REGULI DE MEMORAT ===\n\n";
    
        cout << "1. DIAGONALA PRINCIPALA:\n";
        cout << "   - Indicele rand = Indicele coloana\n";
        cout << "   - Formula: i == j\n";
        cout << "   - Ex: matrice[0][0], matrice[1][1], matrice[2][2]\n\n";
    
        cout << "2. DIAGONALA SECUNDARA:\n";
        cout << "   - Suma indicilor = n-1\n";
        cout << "   - Formula: i + j == n-1\n";
        cout << "   - Ex pentru n=4: [0][3], [1][2], [2][1], [3][0]\n\n";
    
        cout << "3. DEASUPRA diagonalei principale:\n";
        cout << "   - Formula: i < j\n";
        cout << "   - Ex: [0][1], [0][2], [1][2]\n\n";
    
        cout << "4. SUB diagonala principala:\n";
        cout << "   - Formula: i > j\n";
        cout << "   - Ex: [1][0], [2][0], [2][1]\n\n";
    
        cout << "5. CENTRUL matricei (doar pentru n impar):\n";
        cout << "   - Pozitia: [n/2][n/2]\n";
        cout << "   - Ex pentru n=5: [2][2]\n";
    
        return 0;
    }

    12. EXERCIȚII Practice

    Exercițiul 1: Completează codul

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[4][4] = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 16}
        };
    
        // TODO: Calculează produsul elementelor de pe diagonala principala
        int produsPrincipal = 1;
        // Scrie codul aici
    
        cout << "Produsul diagonalei principale: " << produsPrincipal << endl;
    
        // TODO: Numără câte numere pare sunt pe diagonala secundară
        int numerePareSecundara = 0;
        // Scrie codul aici
    
        cout << "Numere pare pe diagonala secundara: " << numerePareSecundara << endl;
    
        return 0;
    }

    Soluție:

    // Pentru produsul diagonalei principale:
    for(int i = 0; i < 4; i++) {
        produsPrincipal *= matrice[i][i];
    }
    
    // Pentru numere pare pe diagonala secundară:
    for(int i = 0; i < 4; i++) {
        int j = 3 - i;  // n=4, deci n-1=3
        if(matrice[i][j] % 2 == 0) {
            numerePareSecundara++;
        }
    }

    Exercițiul 2: Întrebări rapide

    1. Care este elementul de pe diagonala secundară al matricei 5×5 de pe poziția [2][?]?
    2. Cum accesezi toate elementele de sub diagonala principală?
    3. Ce are în comun elementul [0][4] și [4][0] într-o matrice 5×5?

    Răspunsuri:

    1. [2][2] pentru că 2 + 2 = 4 și n-1 = 4
    2. for(int i = 1; i < n; i++) for(int j = 0; j < i; j++)
    3. Sunt ambele pe diagonala secundară (0+4=4 și 4+0=4)

    În concluzie, să-ți spun ceva fundamental:

    Diagonalele nu sunt doar linii abstracte într-o matrice – sunt “scheletul” ei. Dacă matricea ar fi o clădire, diagonalele ar fi grinzile principale care o susțin. Înțelegând diagonalele, înțelegi structura internă a oricărei matrice pătratice.

    Dar tratarea diagonalelor ca simple colecții de elemente fără a înțelege relațiile dintre indici poate fi, paradoxal, o sursă de erori când încerci să accesezi elemente sau să faci calcule complexe.

    Așa că ai grijă când lucrezi cu diagonale. Cunoștințe-ti formulele: când suntem pe diagonala principală? Când pe cea secundară? Care e relația dintre indici? Pentru că puterea de a manipula eficient matricele este goală fără înțelegerea structurii lor diagonale. Și această putere vine cu o responsabilitate: să fii precis cu formulele indicilor.

    Stăpânirea diagonalelor este cheia pentru algoritmi avansați cu matrice: determinanți, valori proprii, diagonalizare. Ai grijă de ea cu aceeași seriozitate.

  • Matrici în C++: “Tablouri cu Două Dimensiuni – Ca o Foaie de Matematica” – Materie BAC

    Bun, hai să vorbim despre un concept care pare intimidant dar e de fapt foarte intuitiv: MATRICILE (Array-uri bidimensionale). Nu e doar despre tabele (cuvânt plictisitor) și grid-uri. E despre cum organizezi datele pe rânduri și coloane, exact ca într-o foaie de Excel sau ca tablele de șah. E un concept atât de natural încât dacă ai privi o matrice, ai recunoaște imediat structura.

    1. Ce este o Matrice? “O Tablă de Șah cu Numere”

    Gândește-te la o matrice ca la o foaie de matematica împărțită în căsuțe: fiecare căsuță are o adresă (rând, coloană) și poate conține o valoare.

    Definiția Matricei:
    O matrice este un vector de vectori – un tablou bidimensional cu rânduri și coloane.

    Analogie cu o Clasă de Școală:

    Fără matrice: “Elevul 1, randul 1, scaunul 1”, “Elevul 2, randul 1, scaunul 2″…

    Cu matrice: clasa[rand][scaun]

    • clasa[0][0] = randul 1, scaunul 1 (Popescu)
    • clasa[0][1] = randul 1, scaunul 2 (Ionescu)
    • clasa[1][0] = randul 2, scaunul 1 (Georgescu)

    2. Cum se Declară o Matrice? “Desenăm Tabloul”

    #include <iostream>
    using namespace std;
    
    int main() {
        // METODA 1: Matrice cu dimensiuni fixe
        int matrice[3][4];  // 3 rânduri, 4 coloane
    
        // METODA 2: Matrice cu inițializare directă
        int tabla[2][3] = {
            {1, 2, 3},   // Randul 0
            {4, 5, 6}    // Randul 1
        };
    
        // METODA 3: Matrice pătratică (număr egal de rânduri și coloane)
        int patrat[3][3] = {
            {1, 0, 0},
            {0, 1, 0},
            {0, 0, 1}
        };
    
        // METODA 4: Lăsăm compilatorul să numere rândurile
        int autoMatrice[][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };  // Compilatorul înțelege că sunt 3 rânduri
    
        return 0;
    }

    3. Cum se Accesează Elementele? “Citesc de pe Tablă”

    CHEIE IMPORTANTĂ: Indicele începe de la 0 pentru ambele dimensiuni!

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[2][3] = {
            {10, 20, 30},  // Randul 0
            {40, 50, 60}   // Randul 1
        };
    
        cout << "=== ACCESARE ELEMENTE MATRICE ===\n\n";
    
        // Accesare element individual
        cout << "Elementul de pe randul 0, coloana 1: " << matrice[0][1] << endl;  // 20
        cout << "Elementul de pe randul 1, coloana 2: " << matrice[1][2] << endl;  // 60
    
        // Modificare element
        matrice[0][1] = 99;  // Schimbă 20 în 99
        cout << "\nDupa modificare, matrice[0][1] = " << matrice[0][1] << endl;
    
        // Calcul cu elemente
        int suma = matrice[0][0] + matrice[1][2];  // 10 + 60 = 70
        cout << "Suma primului si ultimului element: " << suma << endl;
    
        return 0;
    }

    Imaginează-ți matricea astfel:

            Coloana 0   Coloana 1   Coloana 2
    Randul 0:    10          20          30
    Randul 1:    40          50          60
    
    matrice[rand][coloana]

    4. Cum se Parcurg Matricile? “Plimbare prin Toate Căsuțele”

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][4] = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}
        };
    
        cout << "=== PARCURGERE MATRICE ===\n\n";
    
        // Parcurgere completă - două bucle for imbricate
        for(int rand = 0; rand < 3; rand++) {        // Pentru fiecare rând
            for(int coloana = 0; coloana < 4; coloana++) {  // Pentru fiecare coloană
                cout << matrice[rand][coloana] << "\t";  // Afișează elementul
            }
            cout << endl;  // Linie nouă după fiecare rând
        }
    
        return 0;
    }

    Ce se întâmplă în spate:

    Prima iterație: rand=0, coloana=0 → matrice[0][0] = 1
    A doua iterație: rand=0, coloana=1 → matrice[0][1] = 2
    ...
    Când termină coloanele pentru rand=0, trece la rand=1

    5. Cum se Citesc Matricile de la Tastatură? “Umplem Tabloul”

    #include <iostream>
    using namespace std;
    
    int main() {
        const int RANDURI = 3;
        const int COLOANE = 3;
        int matrice[RANDURI][COLOANE];
    
        cout << "=== CITIRE MATRICE DE LA TASTATURA ===\n\n";
    
        // Citire element cu element
        for(int rand = 0; rand < RANDURI; rand++) {
            cout << "Randul " << rand + 1 << ":\n";
    
            for(int coloana = 0; coloana < COLOANE; coloana++) {
                cout << "  Coloana " << coloana + 1 << ": ";
                cin >> matrice[rand][coloana];
            }
        }
    
        // Afișare pentru verificare
        cout << "\nMatricea introdusa este:\n";
        for(int rand = 0; rand < RANDURI; rand++) {
            for(int coloana = 0; coloana < COLOANE; coloana++) {
                cout << matrice[rand][coloana] << " ";
            }
            cout << endl;
        }
    
        return 0;
    }

    Varianta mai compactă:

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[2][3];
    
        cout << "Introdu 6 numere (2 randuri × 3 coloane):\n";
    
        // Citire compactă
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < 3; j++) {
                cin >> matrice[i][j];
            }
        }
    
        return 0;
    }

    6. Operații Esentiale cu Matrici

    6.1 Suma elementelor unei matrice

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
    
        int suma = 0;
    
        // Parcurge și adună toate elementele
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 3; j++) {
                suma += matrice[i][j];
            }
        }
    
        cout << "Suma tuturor elementelor: " << suma << endl;  // 1+2+...+9 = 45
    
        return 0;
    }

    6.2 Găsirea elementului maxim

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[2][4] = {
            {15, 23, 8, 41},
            {7, 32, 19, 5}
        };
    
        // Presupunem că primul element e maxim
        int maxim = matrice[0][0];
        int randMax = 0, coloanaMax = 0;
    
        // Caută un element mai mare
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < 4; j++) {
                if(matrice[i][j] > maxim) {
                    maxim = matrice[i][j];
                    randMax = i;
                    coloanaMax = j;
                }
            }
        }
    
        cout << "Elementul maxim este " << maxim 
             << " la pozitia [" << randMax << "][" << coloanaMax << "]" << endl;
    
        return 0;
    }

    6.3 Suma pe fiecare rând

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
    
        cout << "Suma pe fiecare rand:\n";
    
        for(int rand = 0; rand < 3; rand++) {
            int sumaRand = 0;
    
            for(int coloana = 0; coloana < 3; coloana++) {
                sumaRand += matrice[rand][coloana];
            }
    
            cout << "Randul " << rand << ": " << sumaRand << endl;
        }
    
        return 0;
    }

    6.4 Suma pe fiecare coloană

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
    
        cout << "Suma pe fiecare coloana:\n";
    
        for(int coloana = 0; coloana < 3; coloana++) {
            int sumaColoana = 0;
    
            for(int rand = 0; rand < 3; rand++) {
                sumaColoana += matrice[rand][coloana];
            }
    
            cout << "Coloana " << coloana << ": " << sumaColoana << endl;
        }
    
        return 0;
    }

    7. Matricea Transpusă: “Întoarcerea pe Dos”

    Transpusa unei matrice se obține schimbând rândurile cu coloanele.

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[2][3] = {
            {1, 2, 3},
            {4, 5, 6}
        };
    
        cout << "Matricea originala (2x3):\n";
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < 3; j++) {
                cout << matrice[i][j] << " ";
            }
            cout << endl;
        }
    
        // Matricea transpusă va fi 3x2
        int transpusa[3][2];
    
        // Construim transpusa
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < 3; j++) {
                transpusa[j][i] = matrice[i][j];  // Schimbă indicii!
            }
        }
    
        cout << "\nMatricea transpusa (3x2):\n";
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 2; j++) {
                cout << transpusa[i][j] << " ";
            }
            cout << endl;
        }
    
        return 0;
    }

    Ce se întâmplă:

    Originala:    Transpusa:
    1 2 3         1 4
    4 5 6         2 5
                  3 6

    8. Matrice Pătratică: “Când Rândurile = Coloanele”

    #include <iostream>
    using namespace std;
    
    int main() {
        // Matrice pătratică 4x4
        int patrat[4][4] = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 16}
        };
    
        cout << "=== OPERATII CU MATRICE PATRATICA ===\n\n";
    
        // 1. Diagonala principală (de la stânga-sus la dreapta-jos)
        cout << "Diagonala principala: ";
        for(int i = 0; i < 4; i++) {
            cout << patrat[i][i] << " ";  // i == j
        }
        cout << endl;
    
        // 2. Diagonala secundară (de la dreapta-sus la stânga-jos)
        cout << "Diagonala secundara: ";
        for(int i = 0; i < 4; i++) {
            cout << patrat[i][3 - i] << " ";  // i + j = n-1
        }
        cout << endl;
    
        // 3. Elemente de deasupra diagonalei principale
        cout << "\nElemente de deasupra diagonalei principale:\n";
        for(int i = 0; i < 4; i++) {
            for(int j = i + 1; j < 4; j++) {  // j > i
                cout << patrat[i][j] << " ";
            }
        }
        cout << endl;
    
        // 4. Elemente de sub diagonala principală
        cout << "\nElemente de sub diagonala principala:\n";
        for(int i = 1; i < 4; i++) {          // i > 0
            for(int j = 0; j < i; j++) {      // j < i
                cout << patrat[i][j] << " ";
            }
        }
    
        return 0;
    }

    9. Aplicații Practice Simple

    Aplicația 1: Nota elevilor la mai multe materii

    #include <iostream>
    using namespace std;
    
    int main() {
        // 5 elevi, 4 materii
        double note[5][4];  // [elev][materie]
    
        cout << "=== SISTEM DE NOTE ===\n\n";
    
        // Citire note
        for(int elev = 0; elev < 5; elev++) {
            cout << "Elevul " << elev + 1 << ":\n";
    
            for(int materie = 0; materie < 4; materie++) {
                cout << "  Materia " << materie + 1 << ": ";
                cin >> note[elev][materie];
            }
        }
    
        // Calcul medii elevi
        cout << "\n=== MEDII ELEVI ===\n";
        for(int elev = 0; elev < 5; elev++) {
            double suma = 0;
    
            for(int materie = 0; materie < 4; materie++) {
                suma += note[elev][materie];
            }
    
            double medie = suma / 4;
            cout << "Elevul " << elev + 1 << ": " << medie << endl;
        }
    
        // Calcul medii pe materii
        cout << "\n=== MEDII MATERII ===\n";
        for(int materie = 0; materie < 4; materie++) {
            double suma = 0;
    
            for(int elev = 0; elev < 5; elev++) {
                suma += note[elev][materie];
            }
    
            double medie = suma / 5;
            cout << "Materia " << materie + 1 << ": " << medie << endl;
        }
    
        return 0;
    }

    Aplicația 2: Tabla înmulțirii

    #include <iostream>
    using namespace std;
    
    int main() {
        int tabla[10][10];  // 10x10
    
        // Generează tabla înmulțirii
        for(int i = 0; i < 10; i++) {
            for(int j = 0; j < 10; j++) {
                tabla[i][j] = (i + 1) * (j + 1);
            }
        }
    
        // Afișează tabla
        cout << "=== TABLA INMULTIRII (1-10) ===\n\n";
        cout << "   ";  // Colțul stânga-sus
    
        // Antet coloane
        for(int j = 0; j < 10; j++) {
            cout << j + 1 << "\t";
        }
        cout << "\n   -----------------------------------------\n";
    
        // Conținut tabla
        for(int i = 0; i < 10; i++) {
            cout << i + 1 << "| ";  // Antet rânduri
    
            for(int j = 0; j < 10; j++) {
                cout << tabla[i][j] << "\t";
            }
            cout << endl;
        }
    
        return 0;
    }

    10. Parcurgeri Speciale

    10.1 Parcurgere pe coloane

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
    
        cout << "Parcurgere pe coloane (mai intai coloana, apoi randul):\n";
    
        for(int coloana = 0; coloana < 3; coloana++) {
            for(int rand = 0; rand < 3; rand++) {
                cout << matrice[rand][coloana] << " ";
            }
            cout << endl;
        }
    
        return 0;
    }

    10.2 Parcurgere în spirală (concept)

    Imaginează-ți că mergi în spirală:
    1. Mergi pe primul rând de la stânga la dreapta
    2. Mergi pe ultima coloană de sus în jos  
    3. Mergi pe ultimul rând de la dreapta la stânga
    4. Mergi pe prima coloană de jos în sus
    5. Repetă pentru interior

    11. Cum Păstrăm Dimensiunile Matricei?

    #include <iostream>
    using namespace std;
    
    int main() {
        // Folosim constante pentru claritate
        const int RANDURI = 3;
        const int COLOANE = 4;
    
        int matrice[RANDURI][COLOANE];
    
        // Folosim constantele peste tot
        for(int i = 0; i < RANDURI; i++) {
            for(int j = 0; j < COLOANE; j++) {
                matrice[i][j] = i * j;
            }
        }
    
        // Dacă vrem să afișăm dimensiunile
        cout << "Matricea are " << RANDURI << " randuri si " 
             << COLOANE << " coloane\n";
    
        return 0;
    }

    12. Matrici de Caractere (Tablouri de String-uri)

    #include <iostream>
    using namespace std;
    
    int main() {
        // Matrice de caractere - ca un vector de string-uri
        char cuvinte[3][10] = {  // 3 cuvinte, maxim 9 caractere + terminator
            "calculator",
            "programare", 
            "algoritm"
        };
    
        cout << "Cuvintele noastre:\n";
        for(int i = 0; i < 3; i++) {
            cout << i + 1 << ". " << cuvinte[i] << endl;
        }
    
        // Matrice pentru X si O (joc X si 0)
        char tabla[3][3] = {
            {'X', 'O', 'X'},
            {'O', 'X', 'O'},
            {'X', 'O', 'X'}
        };
    
        cout << "\nTabla de X si 0:\n";
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 3; j++) {
                cout << tabla[i][j] << " ";
            }
            cout << endl;
        }
    
        return 0;
    }

    13. Greșeli Comune și Cum Să Le Evităm

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[2][3];
    
        cout << "=== ATENTIE LA GRESELI COMUNE ===\n\n";
    
        // 1. Accesare în afara limitelor
        // matrice[2][3] = 5;  // GRESIT! Matricea e 2x3, deci indicii merg 0-1 și 0-2
    
        // 2. Amestecarea rândurilor cu coloanele
        int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
    
        cout << "a[0][2] = " << a[0][2] << endl;  // Corect: 3
        cout << "a[2][0] = " << "GRESIT! Matricea are doar 2 randuri (0-1)\n";
    
        // 3. Uitarea că indicii încep de la 0
        cout << "\nPrimul element e a[0][0], nu a[1][1]!\n";
        cout << "Ultimul element e a[1][2], nu a[2][3]!\n";
    
        // 4. Parcurgere greșită
        cout << "\nParcurgere corecta (doua bucle):\n";
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < 3; j++) {
                cout << a[i][j] << " ";
            }
        }
    
        return 0;
    }

    14. EXERCIȚII Practice de Înțelegere

    Exercițiul 1: Completează codul

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[2][3] = {
            {5, 8, 3},
            {2, 7, 4}
        };
    
        // TODO: Calculează suma elementelor
        int suma = 0;
        // Scrie codul aici
    
        cout << "Suma elementelor: " << suma << endl;
    
        // TODO: Găsește elementul minim
        int minim = matrice[0][0];
        // Scrie codul aici
    
        cout << "Elementul minim: " << minim << endl;
    
        return 0;
    }

    Soluție:

    // Pentru suma:
    for(int i = 0; i < 2; i++) {
        for(int j = 0; j < 3; j++) {
            suma += matrice[i][j];
        }
    }
    
    // Pentru minim:
    for(int i = 0; i < 2; i++) {
        for(int j = 0; j < 3; j++) {
            if(matrice[i][j] < minim) {
                minim = matrice[i][j];
            }
        }
    }

    Exercițiul 2: Întrebări rapide

    1. Cum accesezi elementul din colțul dreapta-jos al unei matrice 4×5?
    2. Cum parcurgi doar elementele de pe prima coloană?
    3. Ce face matrice[i][j] = i + j?

    Răspunsuri:

    1. matrice[3][4] (pentru că indicii încep de la 0)
    2. for(int i = 0; i < numarRanduri; i++) cout << matrice[i][0];
    3. Completează matricea cu suma indicilor

    În concluzie, să-ți spun ceva fundamental:

    Matricile nu sunt doar un concept abstract de matematică – sunt modul în care calculatorul vede tabelele, imaginile (pixeli), hărțile, orice are rânduri și coloane. O matrice e ca o fotografie digitală: fiecare pixel are coordonatele lui (rând, coloană) și o valoare (culoare).

    Dar tratarea matricelor ca simple colecții de numere fără a înțelege structura lor bidimensională poate fi, paradoxal, o sursă de confuzie când încerci să rezolvi probleme spațiale sau de poziționare.

    Așa că ai grijă când lucrezi cu matrici. Cunoștințe-ti coordonatele: unde ești? Ce înseamnă rândul 0? Ce înseamnă coloana 0? Pentru că puterea de a organiza datele pe două dimensiuni este goală fără înțelegerea sistemului de coordonate. Și această putere vine cu o responsabilitate: să fii precis cu indicii.

    Stăpânirea matricelor este cheia pentru multe domenii avansate: grafică pe calculator, inteligenta artificiala, procesare de imagini. Ai grijă de ea cu aceeași seriozitate.

  • Vectorul de Frecvență: “Contorul Secret” al Programatorului – Materie BAC

    Bun, hai să vorbim despre unul dintre cele mai elegante și utile trucuri din programare: VECTORUL DE FRECVENȚĂ. Nu e doar despre numărare (cuvânt simplu) și statistică. E despre cum transformi o problemă complexă de căutare într-o operație instantanee. E un concept atât de puternic încât dacă ai înțelege-l bine, ai rezolva multe probleme care altfel par grele.

    1. Ce este un Vector de Frecvență? “O Tablă de Scor” pentru Numere

    Gândește-te la el ca la un tabel unde notezi de câte ori ai văzut fiecare număr:

    Dacă ai numerele: 3, 1, 4, 1, 5, 9, 2, 6, 5, 3

    Număr0123456789
    De câte ori apare0212121001

    Asta e vectorul de frecvență!

    De ce e atât de util?

    • Căutare instantanee: “Numărul 3 apare?” → Verifici poziția 3 în vector
    • Numărări rapide: “Câte numere pare sunt?” → Aduni frecvențele numerelor pare
    • Statistici: Care e cel mai frecvent număr? → Cauți maximul în vector

    2. Cum Funcționează? “Index Direct”

    #include <iostream>
    using namespace std;
    
    int main() {
        // Vector cu numere între 0 și 9
        int numere[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
        int n = 10;
    
        // Vector de frecvență pentru numere 0-9
        int frecventa[10] = {0};  // Toate elementele 0
    
        cout << "Numerele noastre: ";
        for(int i = 0; i < n; i++) {
            cout << numere[i] << " ";
        }
        cout << endl;
    
        // Construim vectorul de frecvență
        for(int i = 0; i < n; i++) {
            int numar = numere[i];
            frecventa[numar]++;  // Crește contorul pentru acel număr
        }
    
        // Afișăm rezultatele
        cout << "\n=== VECTORUL DE FRECVENȚĂ ===\n";
        for(int i = 0; i < 10; i++) {
            if(frecventa[i] > 0) {  // Afișăm doar numerele care apar
                cout << "Numarul " << i << " apare de " << frecventa[i] << " ori\n";
            }
        }
    
        return 0;
    }

    Ce se întâmplă în spate:

    Când întâlnește 3: frecventa[3] devine 1
    Când întâlnește 1: frecventa[1] devine 1  
    Când întâlnește 4: frecventa[4] devine 1
    Când întâlnește 1: frecventa[1] devine 2 (a doua apariție)
    ... și așa mai departe

    3. Aplicații Practice Simple

    Aplicația 1: Verifică dacă toate numerele sunt unice

    #include <iostream>
    using namespace std;
    
    int main() {
        int numere[] = {3, 1, 4, 2, 5, 6};
        int n = 6;
    
        int frecventa[10] = {0};
        bool toateUnice = true;
    
        for(int i = 0; i < n; i++) {
            int numar = numere[i];
    
            if(frecventa[numar] > 0) {
                // Am mai văzut acest număr!
                toateUnice = false;
                cout << "Numarul " << numar << " se repeta!\n";
                break;
            }
    
            frecventa[numar]++;
        }
    
        if(toateUnice) {
            cout << "Toate numerele sunt unice!\n";
        }
    
        return 0;
    }

    Aplicația 2: Găsește elementul care apare cel mai mult

    #include <iostream>
    using namespace std;
    
    int main() {
        int numere[] = {2, 3, 2, 4, 3, 2, 5, 2, 3};
        int n = 9;
    
        // Presupunem numere între 0 și 10
        int frecventa[11] = {0};
    
        // Calculează frecvențele
        for(int i = 0; i < n; i++) {
            frecventa[numere[i]]++;
        }
    
        // Găsește maximul
        int maxFrecventa = 0;
        int numarMax = -1;
    
        for(int i = 0; i < 11; i++) {
            if(frecventa[i] > maxFrecventa) {
                maxFrecventa = frecventa[i];
                numarMax = i;
            }
        }
    
        cout << "Numarul " << numarMax << " apare de cele mai multe ori: " 
             << maxFrecventa << " ori\n";
    
        return 0;
    }

    4. Cum Decizi Dimensiunea Vectorului de Frecvență?

    Regula importantă: Vectorul trebuie să aibă cel puțin (valoare_maximă + 1) elemente!

    #include <iostream>
    using namespace std;
    
    int main() {
        // Exemplu: Note la un test (nota maximă posibilă este 10)
        int note[] = {9, 7, 10, 5, 8, 9, 7, 6, 10, 8};
        int n = 10;
    
        // Dimensiunea corectă: nota_maxima + 1 = 10 + 1 = 11
        int frecventaNote[11] = {0};  // Indici de la 0 la 10
    
        for(int i = 0; i < n; i++) {
            int nota = note[i];
            frecventaNote[nota]++;  // Corect: nota 10 merge în frecventaNote[10]
        }
    
        cout << "Distributia notelor:\n";
        for(int i = 0; i < 11; i++) {
            if(frecventaNote[i] > 0) {
                cout << "Nota " << i << ": " << frecventaNote[i] << " elevi\n";
            }
        }
    
        // GREȘIT: int frecventaGresita[10] - nota 10 ar da eroare!
    
        return 0;
    }

    5. Vector de Frecvență pentru Caractere (Litere)

    #include <iostream>
    using namespace std;
    
    int main() {
        string text = "abracadabra";
    
        // Vector de frecvență pentru litere mici (a-z)
        // Literele au coduri ASCII: 'a'=97, 'b'=98, ..., 'z'=122
        int frecventaLitere[26] = {0};  // 26 de litere
    
        for(int i = 0; i < text.length(); i++) {
            char litera = text[i];
            // Transformă din caracter în index 0-25
            int index = litera - 'a';  // 'a'-'a'=0, 'b'-'a'=1, etc.
            frecventaLitere[index]++;
        }
    
        cout << "Frecventa literelor in \"" << text << "\":\n";
        for(int i = 0; i < 26; i++) {
            if(frecventaLitere[i] > 0) {
                char litera = 'a' + i;  // Transformă înapoi în caracter
                cout << litera << ": " << frecventaLitere[i] << " aparitii\n";
            }
        }
    
        return 0;
    }

    Cum funcționează conversia:

    char litera = 'c';
    int index = litera - 'a';  // 'c' - 'a' = 99 - 97 = 2
    
    // Pentru a transforma înapoi:
    char literaOriginala = 'a' + index;  // 'a' + 2 = 'c'

    6. Comparație: Vector de Frecvență vs Căutare Tradițională

    #include <iostream>
    #include <ctime>
    using namespace std;
    
    int main() {
        const int n = 10000;
        int numere[n];
    
        // Generează numere aleatoare între 0 și 100
        srand(time(0));
        for(int i = 0; i < n; i++) {
            numere[i] = rand() % 101;  // 0-100
        }
    
        int numarCautat = 42;
    
        // METODA 1: Căutare liniară (tradițională)
        clock_t start = clock();
    
        int aparitiiMetoda1 = 0;
        for(int i = 0; i < n; i++) {
            if(numere[i] == numarCautat) {
                aparitiiMetoda1++;
            }
        }
    
        clock_t end = clock();
        double timpMetoda1 = double(end - start) / CLOCKS_PER_SEC;
    
        // METODA 2: Vector de frecvență (inteligentă)
        start = clock();
    
        int frecventa[101] = {0};
        for(int i = 0; i < n; i++) {
            frecventa[numere[i]]++;
        }
        int aparitiiMetoda2 = frecventa[numarCautat];
    
        end = clock();
        double timpMetoda2 = double(end - start) / CLOCKS_PER_SEC;
    
        // Rezultate
        cout << "Caut numarul " << numarCautat << " in " << n << " numere:\n";
        cout << "Metoda liniara: " << aparitiiMetoda1 << " aparitii, " 
             << timpMetoda1 << " secunde\n";
        cout << "Vector frecventa: " << aparitiiMetoda2 << " aparitii, " 
             << timpMetoda2 << " secunde\n";
    
        if(timpMetoda1 > 0) {
            cout << "Vectorul de frecventa este de " 
                 << timpMetoda1/timpMetoda2 << "x mai rapid!\n";
        }
    
        return 0;
    }

    7. Probleme Practice cu Vector de Frecvență

    Problema 1: Verifică dacă un șir este anagramă

    #include <iostream>
    using namespace std;
    
    int main() {
        string cuvant1 = "listen";
        string cuvant2 = "silent";
    
        // Vector de frecvență pentru ambele cuvinte
        int frecventa1[26] = {0};
        int frecventa2[26] = {0};
    
        // Calculează frecvențele pentru primul cuvânt
        for(int i = 0; i < cuvant1.length(); i++) {
            char c = cuvant1[i];
            frecventa1[c - 'a']++;
        }
    
        // Calculează frecvențele pentru al doilea cuvânt
        for(int i = 0; i < cuvant2.length(); i++) {
            char c = cuvant2[i];
            frecventa2[c - 'a']++;
        }
    
        // Compară vectorii de frecvență
        bool suntAnagrame = true;
        for(int i = 0; i < 26; i++) {
            if(frecventa1[i] != frecventa2[i]) {
                suntAnagrame = false;
                break;
            }
        }
    
        if(suntAnagrame) {
            cout << "\"" << cuvant1 << "\" si \"" << cuvant2 << "\" sunt anagrame!\n";
        } else {
            cout << "NU sunt anagrame!\n";
        }
    
        return 0;
    }

    Problema 2: Elementul lipsă dintr-un șir de numere

    #include <iostream>
    using namespace std;
    
    int main() {
        // Avem numerele de la 1 la 10, dar lipsește unul
        int numere[] = {1, 2, 3, 4, 6, 7, 8, 9, 10};
        int n = 9;  // Ar trebui să fie 10
    
        // Vector de frecvență pentru numere 1-10
        int frecventa[11] = {0};  // Indici 0-10, dar folosim doar 1-10
    
        // Marchează numerele pe care le avem
        for(int i = 0; i < n; i++) {
            int numar = numere[i];
            frecventa[numar] = 1;  // 1 = prezent, 0 = lipsă
        }
    
        // Caută numărul lipsă (cel cu frecvența 0)
        cout << "Numerele noastre: ";
        for(int i = 0; i < n; i++) {
            cout << numere[i] << " ";
        }
        cout << "\n\n";
    
        cout << "Numarul/e lipsa: ";
        for(int i = 1; i <= 10; i++) {
            if(frecventa[i] == 0) {
                cout << i << " ";
            }
        }
        cout << endl;
    
        return 0;
    }

    8. Limitări și Soluții

    Problema: Dacă numerele sunt foarte mari (ex: 1.000.000.000), nu putem face vector de frecvență!

    Soluție 1: Folosește vector de bool (dacă doar vrei să știi dacă există)

    #include <iostream>
    using namespace std;
    
    int main() {
        const int MAX = 1000;  // Dacă știm valoarea maximă
        bool exista[MAX] = {false};
    
        int numere[] = {150, 450, 300, 150, 750};
        int n = 5;
    
        for(int i = 0; i < n; i++) {
            exista[numere[i]] = true;
        }
    
        int numarCautat = 300;
        if(exista[numarCautat]) {
            cout << numarCautat << " exista in sir\n";
        }
    
        return 0;
    }

    Soluție 2: Normalizează numerele (dacă nu sunt prea împrăștiate)

    #include <iostream>
    using namespace std;
    
    int main() {
        // Numere mari dar consecutive
        int numere[] = {1001, 1002, 1003, 1005, 1002};
        int n = 5;
    
        // Găsește minimul
        int minim = numere[0];
        for(int i = 1; i < n; i++) {
            if(numere[i] < minim) {
                minim = numere[i];
            }
        }
    
        // Normalizează (scade minimul)
        int frecventa[10] = {0};  // Presupunem că nu sunt mai mult de 10 numere diferite
    
        for(int i = 0; i < n; i++) {
            int index = numere[i] - minim;  // 1001-1001=0, 1002-1001=1, etc.
            frecventa[index]++;
        }
    
        cout << "Frecventa numerelor (normalizate):\n";
        for(int i = 0; i < 10; i++) {
            if(frecventa[i] > 0) {
                int numarReal = minim + i;
                cout << numarReal << ": " << frecventa[i] << " aparitii\n";
            }
        }
    
        return 0;
    }

    9. PROIECT INTEGRAT: Analizor de Text

    #include <iostream>
    using namespace std;
    
    int main() {
        string text;
    
        cout << "Introdu un text: ";
        getline(cin, text);
    
        // Vectori de frecvență pentru diferite analize
        int litere[26] = {0};      // Litere mici a-z
        int cifre[10] = {0};       // Cifre 0-9
        int spatii = 0;
        int vocale = 0;
        int consoane = 0;
    
        // Analizează fiecare caracter
        for(int i = 0; i < text.length(); i++) {
            char c = text[i];
    
            if(c >= 'a' && c <= 'z') {
                // Literă mică
                litere[c - 'a']++;
    
                // Verifică dacă e vocală
                if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
                    vocale++;
                } else {
                    consoane++;
                }
            }
            else if(c >= 'A' && c <= 'Z') {
                // Literă mare - transformă în mică pentru uniformitate
                char literaMica = c + 32;  // 'A'+32='a'
                litere[literaMica - 'a']++;
    
                if(literaMica == 'a' || literaMica == 'e' || 
                   literaMica == 'i' || literaMica == 'o' || literaMica == 'u') {
                    vocale++;
                } else {
                    consoane++;
                }
            }
            else if(c >= '0' && c <= '9') {
                // Cifră
                cifre[c - '0']++;
            }
            else if(c == ' ') {
                // Spațiu
                spatii++;
            }
        }
    
        // Afișează rezultatele
        cout << "\n=== REZULTATE ANALIZA TEXT ===\n";
        cout << "Lungime text: " << text.length() << " caractere\n";
        cout << "Spatii: " << spatii << "\n";
        cout << "Vocale: " << vocale << "\n";
        cout << "Consoane: " << consoane << "\n\n";
    
        // Literele care apar cel puțin o dată
        cout << "Distributia literelor:\n";
        for(int i = 0; i < 26; i++) {
            if(litere[i] > 0) {
                char litera = 'a' + i;
                cout << litera << ": " << litere[i] << "  ";
                if((i+1) % 8 == 0) cout << endl;  // 8 pe linie
            }
        }
        cout << "\n\n";
    
        // Cifrele care apar
        cout << "Cifre gasite: ";
        bool areCifre = false;
        for(int i = 0; i < 10; i++) {
            if(cifre[i] > 0) {
                cout << i << "(" << cifre[i] << ") ";
                areCifre = true;
            }
        }
        if(!areCifre) cout << "niciuna";
        cout << endl;
    
        // Cea mai frecventă literă
        int maxFrecventa = 0;
        char literaComuna = ' ';
    
        for(int i = 0; i < 26; i++) {
            if(litere[i] > maxFrecventa) {
                maxFrecventa = litere[i];
                literaComuna = 'a' + i;
            }
        }
    
        if(maxFrecventa > 0) {
            cout << "Litera cea mai comuna: '" << literaComuna 
                 << "' (" << maxFrecventa << " aparitii)\n";
        }
    
        return 0;
    }

    10. Exerciții de Înțelegere

    Exercițiul 1: Completează codul

    #include <iostream>
    using namespace std;
    
    int main() {
        int numere[] = {5, 2, 8, 5, 9, 2, 5, 1, 8};
        int n = 9;
    
        // TODO: Crează vector de frecvență pentru numere 0-10
        int frecventa[11] = {0};
    
        // TODO: Calculează frecvențele
        for(int i = 0; i < n; i++) {
            // Scrie codul aici
        }
    
        // TODO: Afișează numerele care apar de exact 2 ori
        cout << "Numere care apar de 2 ori: ";
        for(int i = 0; i < 11; i++) {
            // Scrie codul aici
        }
    
        return 0;
    }

    Soluție:

    // În bucla de calcul:
    frecventa[numere[i]]++;
    
    // În bucla de afișare:
    if(frecventa[i] == 2) {
        cout << i << " ";
    }

    Exercițiul 2: Probleme rapide de rezolvat

    1. Ai numerele: 3, 7, 3, 2, 7, 3, 1. Ce va afișa frecventa[3]?
    2. Cum afli câte numere unice sunt într-un vector?
    3. Cum verifici dacă un vector are doar numere pare folosind frecvența?

    Răspunsuri:

    1. frecventa[3] va fi 3 (numărul 3 apare de 3 ori)
    2. Numări câte elemente din vectorul de frecvență au valoarea 1
    3. Verifici dacă frecventa[1] + frecventa[3] + frecventa[5] + ... sunt 0

    În concluzie, să-ți spun ceva practic:

    Vectorul de frecvență e ca o “memorie cache” pentru datele tale. În loc să cauți de fiecare dată în vectorul mare, întrebi direct memoria cache “de câte ori am văzut acest număr?”.

    Dar folosirea lui pentru numere foarte mari sau foarte împrăștiate poate fi, paradoxal, o pierdere enormă de memorie dacă aloci 1.000.000.000 de elemente pentru 10 numere.

    Așa că ai grijă când îl folosești. Cunoștințe-ti datele: care e intervalul? Câte valori diferite sunt? Merită să aloci atâta memorie? Pentru că puterea de a răspunde instant la întrebări este goală fără înțelegerea costurilor memoriei. Și această putere vine cu o responsabilitate: să fii eficient și practic.

    Vectorul de frecvență e unealta perfectă pentru multe probleme – când știi să o folosești corespunzător. Ai grijă de ea cu aceeași seriozitate.

  • Algoritmi de Căutare într-un Vector: Cum Găsești Acul în Carul cu Fân – Materie BAC

    Bun, hai să vorbim despre una dintre cele mai practice și folosite operații cu vectori: CĂUTAREA. Nu e doar despre găsire (cuvânt simplu) și identificare. E despre cum localizezi rapid ce ai nevoie într-o mare de date. E o abilitate atât de importantă încât dacă ar fi să cauți manual în 1.000.000 de elemente, ți-ar lua o viață. Dar aici intervine și partea inteligentă: alegerea algoritmului potrivit pentru situația ta.

    1. De ce Avem Nevoie de Algoritmi de Căutare? “Sherlock Holmes vs Turma de Oi”

    Gândește-te la căutare ca la găsirea unui prieten într-un stadion plin: poți striga numele lui (căutare liniară) sau poți ști că e în sectorul B, rândul 5, locul 12 (căutare binară dacă stadionul e sortat).

    De ce sunt importanți algoritmii de căutare?

    1. Bazele de date – găsește un utilizator după username
    2. Sisteme de fișiere – găsește un fișier pe hard disk
    3. Motoare de căutare – găsește pagini web relevante
    4. Jocuri – găsește cel mai apropiat inamic
    5. Aplicații de contacte – găsește un nume în agendă

    Analogie cu o Bibliotecă:

    Căutare liniară: Mergi la fiecare raft, te uiți la fiecare carte
    Căutare binară: Știi că cărțile sunt sortate alfabetic, mergi direct la litera potrivită

    2. Căutarea Liniară (Linear Search): “Verifică Toate, Una Câte Una”

    Cum funcționează: Verifici fiecare element din vector până găsești ce cauți sau până ajungi la sfârșit.

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {23, 45, 12, 67, 89, 34, 56, 78, 90, 11};
        int n = 10;  // Numărul de elemente
    
        cout << "Vector: ";
        for(int i = 0; i < n; i++) {
            cout << v[i] << " ";
        }
        cout << endl;
    
        int elementCautat;
        cout << "\nCe element cauti? ";
        cin >> elementCautat;
    
        // Căutare liniară
        bool gasit = false;
        int pozitie = -1;
        int pasi = 0;  // Contor pentru câte verificări facem
    
        for(int i = 0; i < n; i++) {
            pasi++;  // Am făcut o verificare
            if(v[i] == elementCautat) {
                gasit = true;
                pozitie = i;
                break;  // Ieșim imediat când l-am găsit
            }
        }
    
        // Afișare rezultate
        if(gasit) {
            cout << "✓ Elementul " << elementCautat << " a fost gasit pe pozitia " << pozitie << endl;
        } else {
            cout << "✗ Elementul " << elementCautat << " NU a fost gasit in vector!" << endl;
        }
    
        cout << "Am facut " << pasi << " verificari" << endl;
        cout << "Complexitate: O(n) - in cel mai rau caz verificam toate cele " << n << " elemente" << endl;
    
        return 0;
    }

    Varianta cu Funcție:

    #include <iostream>
    using namespace std;
    
    // Funcție care caută liniar și returnează poziția (sau -1 dacă nu găsește)
    int cautaLiniar(int v[], int n, int element) {
        for(int i = 0; i < n; i++) {
            if(v[i] == element) {
                return i;  // Am găsit! Returnează poziția
            }
        }
        return -1;  // Nu am găsit
    }
    
    int main() {
        int v[] = {5, 2, 8, 1, 9, 3};
        int n = 6;
    
        cout << "Test cautare liniara:\n";
        cout << "Caut 8: pozitia " << cautaLiniar(v, n, 8) << endl;  // Ar trebui să returneze 2
        cout << "Caut 4: pozitia " << cautaLiniar(v, n, 4) << endl;  // Ar trebui să returneze -1
    
        return 0;
    }

    3. Căutarea Binară (Binary Search): “Împarte și Câștigă”

    Cum funcționează: Funcționează DOAR pe vectori SORTAȚI! Împarte vectorul în jumătate, decide în care jumătate se află elementul, repetă până îl găsește.

    #include <iostream>
    using namespace std;
    
    int main() {
        // ATENȚIE: Vectorul TREBUIE să fie sortat pentru căutarea binară!
        int v[] = {11, 22, 33, 44, 55, 66, 77, 88, 99, 100};
        int n = 10;
    
        cout << "Vector SORTAT: ";
        for(int i = 0; i < n; i++) {
            cout << v[i] << " ";
        }
        cout << endl;
    
        int elementCautat;
        cout << "\nCe element cauti? ";
        cin >> elementCautat;
    
        // Căutare binară
        int stanga = 0;          // Începutul zonei de căutare
        int dreapta = n - 1;     // Sfârșitul zonei de căutare
        bool gasit = false;
        int pozitie = -1;
        int pasi = 0;
    
        while(stanga <= dreapta) {
            pasi++;
            int mijloc = stanga + (dreapta - stanga) / 2;  // Evită overflow
    
            cout << "Pasul " << pasi << ": caut intre pozitiile " << stanga 
                 << " si " << dreapta << " (mijloc = " << mijloc << ")" << endl;
    
            if(v[mijloc] == elementCautat) {
                gasit = true;
                pozitie = mijloc;
                break;
            }
    
            if(v[mijloc] < elementCautat) {
                // Elementul e în dreapta
                stanga = mijloc + 1;
                cout << "  → Merg la dreapta (" << stanga << "..." << dreapta << ")" << endl;
            } else {
                // Elementul e în stânga
                dreapta = mijloc - 1;
                cout << "  → Merg la stanga (" << stanga << "..." << dreapta << ")" << endl;
            }
        }
    
        // Afișare rezultate
        if(gasit) {
            cout << "\n✓ Elementul " << elementCautat << " a fost gasit pe pozitia " << pozitie << endl;
        } else {
            cout << "\n✗ Elementul " << elementCautat << " NU a fost gasit in vector!" << endl;
        }
    
        cout << "Am facut " << pasi << " verificari" << endl;
        cout << "Complexitate: O(log n) - mult mai rapid decat O(n)!" << endl;
        cout << "Pentru " << n << " elemente, log2(" << n << ") ≈ " << log2(n) << " pasi" << endl;
    
        return 0;
    }

    Demonstrație vizuală căutare binară:

    Vector sortat: [11, 22, 33, 44, 55, 66, 77, 88, 99, 100]
    Căutăm elementul 77
    
    Pasul 1: stanga=0, dreapta=9, mijloc=4, v[4]=55
    77 > 55 → merg în dreapta
    
    Pasul 2: stanga=5, dreapta=9, mijloc=7, v[7]=88  
    77 < 88 → merg în stânga
    
    Pasul 3: stanga=5, dreapta=6, mijloc=5, v[5]=66
    77 > 66 → merg în dreapta
    
    Pasul 4: stanga=6, dreapta=6, mijloc=6, v[6]=77
    GĂSIT! Doar 4 pași pentru 10 elemente!

    Varianta Recursivă a Căutării Binare:

    #include <iostream>
    using namespace std;
    
    // Căutare binară recursivă
    int cautareBinaraRecursiv(int v[], int stanga, int dreapta, int element) {
        if(stanga > dreapta) {
            return -1;  // Nu am găsit
        }
    
        int mijloc = stanga + (dreapta - stanga) / 2;
    
        if(v[mijloc] == element) {
            return mijloc;  // Am găsit!
        }
    
        if(v[mijloc] > element) {
            // Caută în stânga
            return cautareBinaraRecursiv(v, stanga, mijloc - 1, element);
        } else {
            // Caută în dreapta
            return cautareBinaraRecursiv(v, mijloc + 1, dreapta, element);
        }
    }
    
    int main() {
        int v[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
        int n = 10;
    
        cout << "Cautare binara recursiva:\n";
        cout << "Caut 50: pozitia " << cautareBinaraRecursiv(v, 0, n-1, 50) << endl;
        cout << "Caut 25: pozitia " << cautareBinaraRecursiv(v, 0, n-1, 25) << endl;
    
        return 0;
    }

    4. Compararea Căutării Liniare vs Binare

    #include <iostream>
    #include <ctime>  // Pentru măsurarea timpului
    using namespace std;
    
    int cautaLiniar(int v[], int n, int element) {
        for(int i = 0; i < n; i++) {
            if(v[i] == element) {
                return i;
            }
        }
        return -1;
    }
    
    int cautareBinara(int v[], int n, int element) {
        int stanga = 0, dreapta = n - 1;
    
        while(stanga <= dreapta) {
            int mijloc = stanga + (dreapta - stanga) / 2;
    
            if(v[mijloc] == element) {
                return mijloc;
            }
    
            if(v[mijloc] < element) {
                stanga = mijloc + 1;
            } else {
                dreapta = mijloc - 1;
            }
        }
    
        return -1;
    }
    
    int main() {
        const int N = 1000000;  // 1 milion de elemente!
        int* v = new int[N];
    
        // Umple vectorul cu numere sortate
        for(int i = 0; i < N; i++) {
            v[i] = i * 2;  // Numere pare: 0, 2, 4, 6, ...
        }
    
        cout << "=== COMPARATIE CĂUTARE LINIARA vs BINARA ===\n";
        cout << "Vector cu " << N << " elemente sortate\n\n";
    
        int elementeDeCautat[] = {500000, 999998, 250000, 750000, 123456, 999999};
    
        for(int i = 0; i < 6; i++) {
            int element = elementeDeCautat[i];
    
            cout << "Caut elementul " << element << ":\n";
    
            // Căutare liniară
            clock_t start = clock();
            int pozLiniar = cautaLiniar(v, N, element);
            clock_t end = clock();
            double timpLiniar = double(end - start) / CLOCKS_PER_SEC;
    
            cout << "  Liniara: pozitia " << pozLiniar << ", timp: " << timpLiniar << " secunde\n";
    
            // Căutare binară
            start = clock();
            int pozBinara = cautareBinara(v, N, element);
            end = clock();
            double timpBinara = double(end - start) / CLOCKS_PER_SEC;
    
            cout << "  Binara:  pozitia " << pozBinara << ", timp: " << timpBinara << " secunde\n";
    
            cout << "  Diferența: " << timpLiniar / timpBinara << "x mai rapid cu binara!\n\n";
        }
    
        delete[] v;
        return 0;
    }

    Tabel comparativ:

    CaracteristicăCăutare LiniarăCăutare Binară
    Vector necesarOrice vectorDoar vectori SORTAȚI
    ComplexitateO(n)O(log n)
    Timp pentru 1.000.000 elemente~500.000 verificări (în medie)~20 verificări
    Când să foloseștiVectori nesortați sau miciVectori sortați mari
    ImplementareSimplăMai complexă
    MemorieO(1)O(1) iterativ, O(log n) recursiv

    5. Căutarea cu Sentinelă: “Un Truc Inteligent”

    Cum funcționează: Pune elementul căutat la sfârșitul vectorului ca “sentinela”, ca să nu mai verifici dacă ai ajuns la sfârșit.

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {23, 45, 12, 67, 89, 34, 56, 78};
        int n = 8;
        int elementCautat;
    
        cout << "Vector: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        cout << "\nCe element cauti? ";
        cin >> elementCautat;
    
        // Salvăm ultimul element
        int ultimElement = v[n-1];
    
        // Punem elementul căutat ca sentinelă la sfârșit
        v[n-1] = elementCautat;
    
        // Căutare cu sentinelă
        int i = 0;
        while(v[i] != elementCautat) {
            i++;
        }
    
        // Restaurăm ultimul element
        v[n-1] = ultimElement;
    
        // Verificăm dacă am găsit elementul sau sentinela
        if(i < n-1 || elementCautat == ultimElement) {
            cout << "✓ Elementul " << elementCautat << " a fost gasit pe pozitia " << i << endl;
        } else {
            cout << "✗ Elementul " << elementCautat << " NU a fost gasit in vector!" << endl;
        }
    
        cout << "Am facut " << (i+1) << " verificari" << endl;
    
        return 0;
    }

    6. Căutarea Multiplelor Apariții

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {5, 2, 8, 2, 9, 2, 3, 2, 7, 2};
        int n = 10;
    
        cout << "Vector: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        int elementCautat;
        cout << "\nCe element cauti? ";
        cin >> elementCautat;
    
        // Caută TOATE aparițiile
        int pozitii[10];  // Pentru a stoca pozițiile găsite
        int gasite = 0;
    
        cout << "Cautare toate aparitiile lui " << elementCautat << ":\n";
    
        for(int i = 0; i < n; i++) {
            if(v[i] == elementCautat) {
                pozitii[gasite] = i;
                gasite++;
            }
        }
    
        if(gasite > 0) {
            cout << "✓ Am gasit " << gasite << " aparitii pe pozitiile: ";
            for(int i = 0; i < gasite; i++) {
                cout << pozitii[i] << " ";
            }
            cout << endl;
        } else {
            cout << "✗ Nu am gasit nici o aparitie a lui " << elementCautat << "!" << endl;
        }
    
        // Prima apariție
        for(int i = 0; i < n; i++) {
            if(v[i] == elementCautat) {
                cout << "Prima aparitie: pozitia " << i << endl;
                break;
            }
        }
    
        // Ultima apariție
        for(int i = n-1; i >= 0; i--) {
            if(v[i] == elementCautat) {
                cout << "Ultima aparitie: pozitia " << i << endl;
                break;
            }
        }
    
        return 0;
    }

    7. Căutarea în Vectori de Structuri

    #include <iostream>
    #include <string>
    using namespace std;
    
    struct Elev {
        int id;
        string nume;
        double medie;
    };
    
    int main() {
        Elev elevii[] = {
            {101, "Popescu Ana", 9.5},
            {102, "Ionescu Marius", 8.2},
            {103, "Georgescu Ioana", 7.8},
            {104, "Dumitrescu Andrei", 9.1},
            {105, "Stanescu Elena", 8.9}
        };
        int n = 5;
    
        cout << "=== CAUTARE ELEV ===\n\n";
        cout << "1. Cauta dupa ID\n";
        cout << "2. Cauta dupa nume\n";
        cout << "3. Cauta dupa medie minima\n";
        cout << "Alegerea ta: ";
    
        int optiune;
        cin >> optiune;
    
        switch(optiune) {
            case 1: {
                int idCautat;
                cout << "Introdu ID-ul elevului: ";
                cin >> idCautat;
    
                bool gasit = false;
                for(int i = 0; i < n; i++) {
                    if(elevii[i].id == idCautat) {
                        cout << "\n✓ Elev gasit!\n";
                        cout << "ID: " << elevii[i].id << endl;
                        cout << "Nume: " << elevii[i].nume << endl;
                        cout << "Medie: " << elevii[i].medie << endl;
                        gasit = true;
                        break;
                    }
                }
    
                if(!gasit) {
                    cout << "\n✗ Nu exista elev cu ID-ul " << idCautat << endl;
                }
                break;
            }
    
            case 2: {
                string numeCautat;
                cout << "Introdu numele elevului: ";
                cin.ignore();
                getline(cin, numeCautat);
    
                bool gasit = false;
                for(int i = 0; i < n; i++) {
                    if(elevii[i].nume == numeCautat) {
                        cout << "\n✓ Elev gasit!\n";
                        cout << "ID: " << elevii[i].id << endl;
                        cout << "Nume: " << elevii[i].nume << endl;
                        cout << "Medie: " << elevii[i].medie << endl;
                        gasit = true;
                        break;
                    }
                }
    
                if(!gasit) {
                    cout << "\n✗ Nu exista elev cu numele \"" << numeCautat << "\"" << endl;
                }
                break;
            }
    
            case 3: {
                double medieMinima;
                cout << "Introdu media minima: ";
                cin >> medieMinima;
    
                cout << "\nElevii cu media >= " << medieMinima << ":\n";
                int gasiti = 0;
    
                for(int i = 0; i < n; i++) {
                    if(elevii[i].medie >= medieMinima) {
                        cout << "- " << elevii[i].nume << " (" << elevii[i].medie << ")\n";
                        gasiti++;
                    }
                }
    
                if(gasiti == 0) {
                    cout << "Niciun elev nu are media >= " << medieMinima << endl;
                } else {
                    cout << "Total: " << gasiti << " elev(i)\n";
                }
                break;
            }
    
            default:
                cout << "Optiune invalida!" << endl;
        }
    
        return 0;
    }

    8. Căutarea Interpolată: “Căutare Binara Mai Inteligentă”

    Cum funcționează: Ca căutarea binară, dar ghicește unde ar trebui să fie elementul bazat pe valorile extreme.

    #include <iostream>
    using namespace std;
    
    int main() {
        // Vector cu valori uniform distribuite
        int v[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
        int n = 10;
    
        cout << "Vector sortat uniform: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        int elementCautat;
        cout << "\nCe element cauti? ";
        cin >> elementCautat;
    
        // Căutare interpolată
        int stanga = 0;
        int dreapta = n - 1;
        bool gasit = false;
        int pasi = 0;
    
        while(stanga <= dreapta && elementCautat >= v[stanga] && elementCautat <= v[dreapta]) {
            pasi++;
    
            // Formula de interpolare - ghicește poziția
            int pozitie = stanga + ((elementCautat - v[stanga]) * (dreapta - stanga)) / 
                                   (v[dreapta] - v[stanga]);
    
            cout << "Pasul " << pasi << ": pozitie estimata = " << pozitie 
                 << " (valoare: " << v[pozitie] << ")" << endl;
    
            if(v[pozitie] == elementCautat) {
                gasit = true;
                cout << "✓ Gasit pe pozitia " << pozitie << endl;
                break;
            }
    
            if(v[pozitie] < elementCautat) {
                stanga = pozitie + 1;
            } else {
                dreapta = pozitie - 1;
            }
        }
    
        if(!gasit) {
            cout << "✗ Elementul " << elementCautat << " nu a fost gasit!" << endl;
        }
    
        cout << "Total pasi: " << pasi << endl;
        cout << "Cautarea binara ar fi facut ~" << log2(n) << " pasi" << endl;
    
        return 0;
    }

    9. PROIECT INTEGRAT: Sistem Complet de Căutare

    #include <iostream>
    #include <ctime>
    #include <cstdlib>
    using namespace std;
    
    // Funcții pentru diferite tipuri de căutare
    int cautaLiniar(int v[], int n, int x) {
        for(int i = 0; i < n; i++) {
            if(v[i] == x) return i;
        }
        return -1;
    }
    
    int cautareBinara(int v[], int n, int x) {
        int stanga = 0, dreapta = n - 1;
        while(stanga <= dreapta) {
            int mijloc = stanga + (dreapta - stanga) / 2;
            if(v[mijloc] == x) return mijloc;
            if(v[mijloc] < x) stanga = mijloc + 1;
            else dreapta = mijloc - 1;
        }
        return -1;
    }
    
    int cautareCuSentinel(int v[], int n, int x) {
        int ultim = v[n-1];
        v[n-1] = x;
    
        int i = 0;
        while(v[i] != x) i++;
    
        v[n-1] = ultim;
    
        if(i < n-1 || x == ultim) return i;
        return -1;
    }
    
    void sorteazaVector(int v[], int n) {
        for(int i = 0; i < n-1; i++) {
            for(int j = 0; j < n-i-1; j++) {
                if(v[j] > v[j+1]) {
                    int temp = v[j];
                    v[j] = v[j+1];
                    v[j+1] = temp;
                }
            }
        }
    }
    
    void afiseazaVector(int v[], int n, string mesaj) {
        cout << mesaj;
        for(int i = 0; i < n && i < 20; i++) {  // Afișează maxim 20
            cout << v[i] << " ";
        }
        if(n > 20) cout << "... (" << n << " elemente)";
        cout << endl;
    }
    
    int main() {
        const int MAX = 100000;
        int vector[MAX], copie[MAX];
        int n;
    
        cout << "=== SISTEM COMPLET DE CAUTARE ===\n\n";
    
        // Alegere dimensiune
        cout << "Dimensiune vector (max " << MAX << "): ";
        cin >> n;
    
        if(n <= 0 || n > MAX) {
            cout << "Dimensiune invalida!" << endl;
            return 1;
        }
    
        // Generare vector
        srand(time(0));
        for(int i = 0; i < n; i++) {
            vector[i] = rand() % 10000;  // Numere între 0 și 9999
            copie[i] = vector[i];
        }
    
        afiseazaVector(vector, n, "Vector generat (primele 20): ");
    
        // Meniu principal
        while(true) {
            cout << "\n=== MENIU PRINCIPAL ===\n";
            cout << "1. Cautare liniara\n";
            cout << "2. Cautare binara (va sorta vectorul)\n";
            cout << "3. Cautare cu sentinela\n";
            cout << "4. Compara algoritmii\n";
            cout << "5. Regenerare vector\n";
            cout << "0. Iesire\n";
            cout << "Alegerea ta: ";
    
            int optiune;
            cin >> optiune;
    
            if(optiune == 0) break;
    
            if(optiune >= 1 && optiune <= 4) {
                int elementCautat;
                cout << "Elementul de cautat: ";
                cin >> elementCautat;
    
                clock_t start, end;
                double timp;
                int rezultat;
    
                switch(optiune) {
                    case 1:  // Liniară
                        start = clock();
                        rezultat = cautaLiniar(vector, n, elementCautat);
                        end = clock();
                        timp = double(end - start) / CLOCKS_PER_SEC;
    
                        if(rezultat != -1) {
                            cout << "✓ Gasit pe pozitia " << rezultat << endl;
                        } else {
                            cout << "✗ Nu a fost gasit" << endl;
                        }
                        cout << "Timp: " << timp << " secunde" << endl;
                        break;
    
                    case 2:  // Binară
                        // Sortăm vectorul pentru căutarea binară
                        for(int i = 0; i < n; i++) vector[i] = copie[i];
                        start = clock();
                        sorteazaVector(vector, n);
                        rezultat = cautareBinara(vector, n, elementCautat);
                        end = clock();
                        timp = double(end - start) / CLOCKS_PER_SEC;
    
                        if(rezultat != -1) {
                            cout << "✓ Gasit pe pozitia " << rezultat << " (in vectorul sortat)" << endl;
                        } else {
                            cout << "✗ Nu a fost gasit" << endl;
                        }
                        cout << "Timp (inclusiv sortarea): " << timp << " secunde" << endl;
                        break;
    
                    case 3:  // Cu sentinelă
                        for(int i = 0; i < n; i++) vector[i] = copie[i];
                        start = clock();
                        rezultat = cautareCuSentinel(vector, n, elementCautat);
                        end = clock();
                        timp = double(end - start) / CLOCKS_PER_SEC;
    
                        if(rezultat != -1) {
                            cout << "✓ Gasit pe pozitia " << rezultat << endl;
                        } else {
                            cout << "✗ Nu a fost gasit" << endl;
                        }
                        cout << "Timp: " << timp << " secunde" << endl;
                        break;
    
                    case 4:  // Comparație
                        cout << "\n=== COMPARATIE ALGORITMI ===\n";
    
                        // Liniară
                        for(int i = 0; i < n; i++) vector[i] = copie[i];
                        start = clock();
                        rezultat = cautaLiniar(vector, n, elementCautat);
                        end = clock();
                        double timpLiniar = double(end - start) / CLOCKS_PER_SEC;
    
                        // Binară
                        for(int i = 0; i < n; i++) vector[i] = copie[i];
                        start = clock();
                        sorteazaVector(vector, n);
                        rezultat = cautareBinara(vector, n, elementCautat);
                        end = clock();
                        double timpBinara = double(end - start) / CLOCKS_PER_SEC;
    
                        // Cu sentinelă
                        for(int i = 0; i < n; i++) vector[i] = copie[i];
                        start = clock();
                        rezultat = cautareCuSentinel(vector, n, elementCautat);
                        end = clock();
                        double timpSentinel = double(end - start) / CLOCKS_PER_SEC;
    
                        cout << "Liniara:  " << timpLiniar << " secunde\n";
                        cout << "Binara:   " << timpBinara << " secunde (cu sortare)\n";
                        cout << "Sentinela: " << timpSentinel << " secunde\n";
    
                        if(timpLiniar > 0 && timpBinara > 0) {
                            cout << "\nBinara e de " << timpLiniar/timpBinara << "x mai rapida decat liniara!\n";
                        }
                        break;
                }
            }
    
            else if(optiune == 5) {  // Regenerare
                srand(time(0));
                for(int i = 0; i < n; i++) {
                    vector[i] = rand() % 10000;
                    copie[i] = vector[i];
                }
                cout << "Vector regenerat cu succes!\n";
                afiseazaVector(vector, n, "Noul vector (primele 20): ");
            }
    
            else {
                cout << "Optiune invalida!\n";
            }
        }
    
        cout << "\nLa revedere!\n";
        return 0;
    }

    10. Exerciții Practice

    Exercițiul 1: Căutare cu Frecvență

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {5, 2, 8, 2, 9, 5, 2, 1, 5, 2, 7, 5};
        int n = 12;
    
        cout << "Vector: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Crează un vector de frecvență
        const int MAX_VAL = 10;  // Presupunem valori între 0 și 9
        int frecventa[MAX_VAL] = {0};
    
        // Calculează frecvența fiecărui element
        for(int i = 0; i < n; i++) {
            if(v[i] >= 0 && v[i] < MAX_VAL) {
                frecventa[v[i]]++;
            }
        }
    
        // Căutare rapidă - direct în vectorul de frecvență
        int elementCautat;
        cout << "\nCe element cauti? ";
        cin >> elementCautat;
    
        if(elementCautat >= 0 && elementCautat < MAX_VAL) {
            if(frecventa[elementCautat] > 0) {
                cout << "✓ Elementul " << elementCautat << " apare de " 
                     << frecventa[elementCautat] << " ori\n";
    
                // Găsește prima poziție (dacă e nevoie)
                for(int i = 0; i < n; i++) {
                    if(v[i] == elementCautat) {
                        cout << "Prima aparitie: pozitia " << i << endl;
                        break;
                    }
                }
            } else {
                cout << "✗ Elementul " << elementCautat << " nu apare in vector!\n";
            }
        } else {
            cout << "Elementul trebuie sa fie intre 0 si " << MAX_VAL-1 << "!\n";
        }
    
        return 0;
    }

    Exercițiul 2: Căutare în Vector 2D (Matrice)

    #include <iostream>
    using namespace std;
    
    int main() {
        int matrice[3][4] = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}
        };
    
        int elementCautat;
        cout << "Ce element cauti in matrice? ";
        cin >> elementCautat;
    
        bool gasit = false;
        int randGasit, coloanaGasita;
    
        // Căutare liniară în matrice
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 4; j++) {
                if(matrice[i][j] == elementCautat) {
                    gasit = true;
                    randGasit = i;
                    coloanaGasita = j;
                    break;
                }
            }
            if(gasit) break;
        }
    
        if(gasit) {
            cout << "✓ Elementul " << elementCautat << " a fost gasit la pozitia ("
                 << randGasit << ", " << coloanaGasita << ")" << endl;
        } else {
            cout << "✗ Elementul " << elementCautat << " nu a fost gasit in matrice!" << endl;
        }
    
        return 0;
    }

    În concluzie, să-ți spun ceva fundamental:

    Algoritmii de căutare nu sunt doar exerciții teoretice – sunt instrumente practice pe care le folosești în fiecare aplicație. Diferența dintre o căutare care durează 1 secundă și una care durează 1 oră poate fi alegerea algoritmului potrivit.

    Dar folosirea căutării binare pe un vector nesortat poate fi, paradoxal, o sursă de bug-uri grave care îți pot distruge întreaga logică a programului dacă nu verifici dacă vectorul e sortat.

    Așa că ai grijă ce algoritm alegi. Cunoștințe-ti datele: sunt sortate sau nu? Sunt multe sau puține? Cauți o singură apariție sau toate? Pentru că puterea de a găsi rapid ce cauți este goală fără înțelegerea când să folosești fiecare algoritm. Și această putere vine cu o responsabilitate: să fii strategic și precis.

    Stăpânirea algoritmilor de căutare este o parte esențială a rezolvării eficiente a problemelor în programare. Ai grijă de ea cu aceeași seriozitate.

  • Sortarea Elementelor unui Vector: Arta de a Aranja În Ordine – Materie BAC

    Bun, hai să vorbim despre una dintre cele mai importante operații cu vectori: SORTAREA. Nu e doar despre aranjare (cuvânt plictisitor) și ordine. E despre cum transformi o grămadă dezordonată de numere într-o listă perfect organizată. E o operație atât de fundamentală încât dacă ar fi să cauți ceva într-o listă nesortată, ai căuta ca orbul în ceață. Dar aici intervine și partea strategică: alegerea algoritmului de sortare potrivit pentru situația ta.

    1. De ce Să Sortăm? “Căutarea Cheilor în Întuneric vs cu Lanternă”

    Gândește-te la sortare ca la aranjarea cărților în bibliotecă în ordine alfabetică: în loc să cauți o carte mergând prin toată biblioteca, mergi direct la raftul potrivit.

    De ce sortăm vectorii?

    1. Căutarea devine rapidă – poți folosi căutarea binară
    2. Datele sunt mai lizibile – vezi imediat min, max, mediană
    3. Pregătește pentru alte operații – unirea a doi vectori sortați e ușoară
    4. E necesară pentru multe algoritme – statistici, grafice, baze de date

    Analogie cu un pachet de cărți de joc:

    Fără sortare: “Vreau un 7 de cupă” → cauți prin toate cărțile una câte una
    Cu sortare: cărțile sunt aranjate pe culori și valori → găsești imediat

    2. Bubble Sort: “Cel Mai Simplu, Dar Cel Mai Lent”

    Cum funcționează: Compară două elemente vecine, le schimbă dacă sunt în ordine greșită, repetă până când tot vectorul e sortat. Ca bulele care urcă în suprafața apei.

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {64, 34, 25, 12, 22, 11, 90};
        int n = 7;  // Numărul de elemente
    
        cout << "Vector nesortat: ";
        for(int i = 0; i < n; i++) {
            cout << v[i] << " ";
        }
        cout << endl;
    
        // Bubble Sort - versiunea simplă
        for(int i = 0; i < n - 1; i++) {          // Trecem prin vector de n-1 ori
            for(int j = 0; j < n - i - 1; j++) {  // Ultimele i elemente sunt deja sortate
                if(v[j] > v[j + 1]) {             // Dacă sunt în ordine greșită
                    // Schimbă elementele
                    int temp = v[j];
                    v[j] = v[j + 1];
                    v[j + 1] = temp;
                }
            }
    
            // Afișează starea după fiecare trecere (pentru vizualizare)
            cout << "Dupa trecerea " << i + 1 << ": ";
            for(int k = 0; k < n; k++) {
                cout << v[k] << " ";
            }
            cout << endl;
        }
    
        cout << "\nVector sortat crescator: ";
        for(int i = 0; i < n; i++) {
            cout << v[i] << " ";
        }
        cout << endl;
    
        return 0;
    }

    Ce se întâmplă pas cu pas:

    Vector initial: 64 34 25 12 22 11 90
    
    Trecerea 1: Schimbă 64 cu 34, 64 cu 25, 64 cu 12, 64 cu 22, 64 cu 11
    Rezultat: 34 25 12 22 11 64 90  (64 și 90 la locul lor)
    
    Trecerea 2: Schimbă 34 cu 25, 34 cu 12, 34 cu 22, 34 cu 11
    Rezultat: 25 12 22 11 34 64 90  (34 la locul lui)
    
    Trecerea 3: Schimbă 25 cu 12, 25 cu 22, 25 cu 11
    Rezultat: 12 22 11 25 34 64 90  (25 la locul lui)
    
    ... și așa mai departe până tot vectorul e sortat

    Optimizare pentru Bubble Sort:

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {1, 2, 3, 4, 5, 6, 7};  // Deja sortat!
        int n = 7;
    
        // Bubble Sort optimizat - se oprește dacă vectorul e deja sortat
        bool schimbat;
    
        for(int i = 0; i < n - 1; i++) {
            schimbat = false;  // Presupunem că nu s-a făcut niciun schimb
    
            for(int j = 0; j < n - i - 1; j++) {
                if(v[j] > v[j + 1]) {
                    int temp = v[j];
                    v[j] = v[j + 1];
                    v[j + 1] = temp;
                    schimbat = true;  // S-a făcut cel puțin un schimb
                }
            }
    
            // Dacă nu s-a făcut niciun schimb, vectorul e sortat
            if(!schimbat) {
                cout << "Vectorul a fost sortat dupa " << i + 1 << " treceri" << endl;
                break;
            }
        }
    
        return 0;
    }

    3. Selection Sort: “Găsește Minimul și Pune-l la Început”

    Cum funcționează: Găsește cel mai mic element, îl pune pe prima poziție. Apoi găsește următorul cel mai mic din rest, îl pune pe a doua poziție, etc.

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {64, 25, 12, 22, 11};
        int n = 5;
    
        cout << "Vector nesortat: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Selection Sort
        for(int i = 0; i < n - 1; i++) {
            // Găsește poziția minimului în partea nesortată (de la i la sfârșit)
            int pozitieMinim = i;
    
            for(int j = i + 1; j < n; j++) {
                if(v[j] < v[pozitieMinim]) {
                    pozitieMinim = j;  // Am găsit un element mai mic
                }
            }
    
            // Schimbă elementul minim cu primul element din partea nesortată
            if(pozitieMinim != i) {  // Dacă minimul nu e deja pe poziția i
                int temp = v[i];
                v[i] = v[pozitieMinim];
                v[pozitieMinim] = temp;
            }
    
            // Afișează progresul
            cout << "Dupa pasul " << i + 1 << " (minimul pus pe pozitia " << i << "): ";
            for(int k = 0; k < n; k++) cout << v[k] << " ";
            cout << endl;
        }
    
        cout << "\nVector sortat crescator: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        return 0;
    }

    Ce se întâmplă pas cu pas:

    Vector initial: 64 25 12 22 11
    
    Pasul 1: Găsește minimul (11) și îl pune pe poziția 0
    Schimbă 64 cu 11 → 11 25 12 22 64
    
    Pasul 2: Găsește minimul în rest (12) și îl pune pe poziția 1
    Schimbă 25 cu 12 → 11 12 25 22 64
    
    Pasul 3: Găsește minimul în rest (22) și îl pune pe poziția 2
    Schimbă 25 cu 22 → 11 12 22 25 64
    
    Pasul 4: Ultimele două sunt deja în ordine
    Rezultat final: 11 12 22 25 64

    4. Insertion Sort: “Ca Să Înșurubezi un Șurub”

    Cum funcționează: Luați un element, inserați-l în poziția corectă în partea deja sortată. Ca și cum ai sorta cărți de joc în mână.

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {12, 11, 13, 5, 6};
        int n = 5;
    
        cout << "Vector nesortat: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Insertion Sort
        for(int i = 1; i < n; i++) {  // Începe cu al doilea element
            int elementCurent = v[i];  // Elementul pe care vrem să-l inserăm
            int j = i - 1;             // Ultimul element din partea sortată
    
            // Mută elementele mai mari decât elementCurent cu o poziție la dreapta
            while(j >= 0 && v[j] > elementCurent) {
                v[j + 1] = v[j];  // Mută elementul mai mare
                j = j - 1;        // Mergi înapoi în partea sortată
            }
    
            // Inserează elementCurent în poziția corectă
            v[j + 1] = elementCurent;
    
            // Afișează progresul
            cout << "Dupa pasul " << i << " (elementul " << elementCurent << " inserat): ";
            for(int k = 0; k < n; k++) cout << v[k] << " ";
            cout << endl;
        }
    
        cout << "\nVector sortat crescator: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        return 0;
    }

    Ce se întâmplă pas cu pas:

    Vector initial: 12 11 13 5 6
    
    Pasul 1: Luați 11, inserați-l înainte de 12
    11 12 13 5 6
    
    Pasul 2: Luați 13, e deja în poziția corectă (după 12)
    11 12 13 5 6
    
    Pasul 3: Luați 5, inserați-l înaintea tuturor
    5 11 12 13 6
    
    Pasul 4: Luați 6, inserați-l între 5 și 11
    5 6 11 12 13

    5. Compararea Algoritmilor: “Care e Cel Mai Bun?”

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "=== COMPARATIE ALGORITMI DE SORTARE ===\n\n";
    
        cout << "BUBBLE SORT:\n";
        cout << "- Cum functioneaza: Compara vecinii si-i schimba daca sunt gresit\n";
        cout << "- Complexitate: O(n²) în cel mai rău caz\n";
        cout << "- Cand il folosesti: Pentru vectori mici sau aproape sortati\n";
        cout << "- Avantaje: Simplu de inteles si implementat\n";
        cout << "- Dezavantaje: Foarte lent pentru vectori mari\n\n";
    
        cout << "SELECTION SORT:\n";
        cout << "- Cum functioneaza: Gaseste minimul si-l pune la inceput\n";
        cout << "- Complexitate: O(n²) întotdeauna\n";
        cout << "- Cand il folosesti: Cand vrei putine schimbari (ex: sortare flash-uri)\n";
        cout << "- Avantaje: Face doar O(n) schimburi\n";
        cout << "- Dezavantaje: Tot O(n²) comparatii\n\n";
    
        cout << "INSERTION SORT:\n";
        cout << "- Cum functioneaza: Insereaza fiecare element in pozitia corecta\n";
        cout << "- Complexitate: O(n²) în cel mai rău caz, O(n) dacă e aproape sortat\n";
        cout << "- Cand il folosesti: Pentru vectori mici sau aproape sortati\n";
        cout << "- Avantaje: Bun pentru date care vin în flux (online sorting)\n";
        cout << "- Dezavantaje: Lent pentru vectori mari invers sortati\n";
    
        return 0;
    }

    6. Sortare Descrescătoare: “Doar Schimbi Semnul”

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {5, 2, 8, 1, 9, 3};
        int n = 6;
    
        cout << "Vector initial: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Bubble Sort descrescator (schimba doar conditia!)
        for(int i = 0; i < n - 1; i++) {
            for(int j = 0; j < n - i - 1; j++) {
                if(v[j] < v[j + 1]) {  // < în loc de >
                    int temp = v[j];
                    v[j] = v[j + 1];
                    v[j + 1] = temp;
                }
            }
        }
    
        cout << "Vector sortat descrescator: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Selection Sort descrescator (găsește maximul, nu minimul)
        int v2[] = {5, 2, 8, 1, 9, 3};
    
        for(int i = 0; i < n - 1; i++) {
            int pozitieMaxim = i;
    
            for(int j = i + 1; j < n; j++) {
                if(v2[j] > v2[pozitieMaxim]) {  // > în loc de <
                    pozitieMaxim = j;
                }
            }
    
            if(pozitieMaxim != i) {
                int temp = v2[i];
                v2[i] = v2[pozitieMaxim];
                v2[pozitieMaxim] = temp;
            }
        }
    
        cout << "Vector sortat descrescator (Selection): ";
        for(int i = 0; i < n; i++) cout << v2[i] << " ";
        cout << endl;
    
        return 0;
    }

    7. Sortarea Unui Vector Citit de la Tastatură

    #include <iostream>
    using namespace std;
    
    int main() {
        const int MAX = 100;
        int v[MAX];
        int n;
    
        cout << "Cate numere vrei sa sortezi? (max " << MAX << "): ";
        cin >> n;
    
        if(n <= 0 || n > MAX) {
            cout << "Numar invalid!" << endl;
            return 1;
        }
    
        // Citire vector
        cout << "Introdu " << n << " numere:" << endl;
        for(int i = 0; i < n; i++) {
            cout << "v[" << i << "] = ";
            cin >> v[i];
        }
    
        cout << "\nVector inainte de sortare: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Alegerea algoritmului
        int alegere;
        cout << "\nAlege algoritmul de sortare:\n";
        cout << "1. Bubble Sort\n";
        cout << "2. Selection Sort\n";
        cout << "3. Insertion Sort\n";
        cout << "Alegerea ta: ";
        cin >> alegere;
    
        // Sortare după alegere
        switch(alegere) {
            case 1:  // Bubble Sort
                for(int i = 0; i < n - 1; i++) {
                    for(int j = 0; j < n - i - 1; j++) {
                        if(v[j] > v[j + 1]) {
                            int temp = v[j];
                            v[j] = v[j + 1];
                            v[j + 1] = temp;
                        }
                    }
                }
                cout << "Am folosit Bubble Sort\n";
                break;
    
            case 2:  // Selection Sort
                for(int i = 0; i < n - 1; i++) {
                    int minIdx = i;
                    for(int j = i + 1; j < n; j++) {
                        if(v[j] < v[minIdx]) {
                            minIdx = j;
                        }
                    }
                    if(minIdx != i) {
                        int temp = v[i];
                        v[i] = v[minIdx];
                        v[minIdx] = temp;
                    }
                }
                cout << "Am folosit Selection Sort\n";
                break;
    
            case 3:  // Insertion Sort
                for(int i = 1; i < n; i++) {
                    int key = v[i];
                    int j = i - 1;
                    while(j >= 0 && v[j] > key) {
                        v[j + 1] = v[j];
                        j--;
                    }
                    v[j + 1] = key;
                }
                cout << "Am folosit Insertion Sort\n";
                break;
    
            default:
                cout << "Alegere invalida! Nu s-a sortat nimic.\n";
        }
    
        cout << "\nVector dupa sortare: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        return 0;
    }

    8. Probleme Practice cu Sortarea

    Problema 1: Sortare după Ultima Cifră

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {123, 45, 789, 12, 6, 98, 345};
        int n = 7;
    
        cout << "Vector initial: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Bubble Sort care compară ultima cifră
        for(int i = 0; i < n - 1; i++) {
            for(int j = 0; j < n - i - 1; j++) {
                // Compară ultima cifră (v[j] % 10)
                if(v[j] % 10 > v[j + 1] % 10) {
                    int temp = v[j];
                    v[j] = v[j + 1];
                    v[j + 1] = temp;
                }
            }
        }
    
        cout << "Sortat dupa ultima cifra: ";
        for(int i = 0; i < n; i++) {
            cout << v[i] << "(" << v[i] % 10 << ") ";
        }
        cout << endl;
    
        return 0;
    }

    Problema 2: Sortare Alternativă (Min-Max)

    #include <iostream>
    using namespace std;
    
    int main() {
        int v[] = {7, 2, 9, 4, 1, 8, 5, 3, 6};
        int n = 9;
    
        cout << "Vector initial: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Sortare specială: primul minim, apoi maxim, apoi al doilea minim, etc.
    
        // Mai întâi sortăm normal
        for(int i = 0; i < n - 1; i++) {
            for(int j = 0; j < n - i - 1; j++) {
                if(v[j] > v[j + 1]) {
                    int temp = v[j];
                    v[j] = v[j + 1];
                    v[j + 1] = temp;
                }
            }
        }
    
        cout << "Vector sortat normal: ";
        for(int i = 0; i < n; i++) cout << v[i] << " ";
        cout << endl;
    
        // Acum creăm un vector nou cu aranjament min-max
        int rezultat[9];
        int stanga = 0, dreapta = n - 1;
    
        for(int i = 0; i < n; i++) {
            if(i % 2 == 0) {  // Poziții pare: ia din stânga (minime)
                rezultat[i] = v[stanga];
                stanga++;
            } else {          // Poziții impare: ia din dreapta (maxime)
                rezultat[i] = v[dreapta];
                dreapta--;
            }
        }
    
        cout << "Sortat min-max alternativ: ";
        for(int i = 0; i < n; i++) cout << rezultat[i] << " ";
        cout << endl;
    
        return 0;
    }

    Problema 3: Sortare după Mai Multe Criterii

    #include <iostream>
    using namespace std;
    
    int main() {
        // Vector de perechi (nota, număr de absențe)
        int note[] = {9, 7, 10, 5, 8};
        int absente[] = {2, 5, 1, 10, 3};
        int n = 5;
    
        cout << "Elevi inainte de sortare:\n";
        cout << "Nota | Absente\n";
        for(int i = 0; i < n; i++) {
            cout << note[i] << "    | " << absente[i] << endl;
        }
    
        // Sortare după notă descrescător, apoi după absențe crescător
        // (elevii cu note mai mari și mai puține absențe primele)
    
        for(int i = 0; i < n - 1; i++) {
            for(int j = 0; j < n - i - 1; j++) {
                bool schimba = false;
    
                // Criteriul 1: Nota mai mare e mai bun
                if(note[j] < note[j + 1]) {
                    schimba = true;
                }
                // Criteriul 2: Dacă notele sunt egale, mai puține absențe e mai bun
                else if(note[j] == note[j + 1] && absente[j] > absente[j + 1]) {
                    schimba = true;
                }
    
                if(schimba) {
                    // Schimbă notele
                    int tempNota = note[j];
                    note[j] = note[j + 1];
                    note[j + 1] = tempNota;
    
                    // Schimbă absențele (menține corespondența)
                    int tempAbs = absente[j];
                    absente[j] = absente[j + 1];
                    absente[j + 1] = tempAbs;
                }
            }
        }
    
        cout << "\nElevi dupa sortare (nota desc, absente cresc):\n";
        cout << "Nota | Absente\n";
        for(int i = 0; i < n; i++) {
            cout << note[i] << "    | " << absente[i] << endl;
        }
    
        return 0;
    }

    9. Algoritmi Avansați (Conceptual)

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "=== ALGORITMI AVANSATI DE SORTARE (teoretic) ===\n\n";
    
        cout << "QUICK SORT:\n";
        cout << "- Cum functioneaza: Alege un 'pivot', muta elementele mai mici in stanga,\n";
        cout << "  mai mari in dreapta, aplica recursiv pe cele doua jumatati\n";
        cout << "- Complexitate: O(n log n) în medie, O(n²) în cel mai rău caz\n";
        cout << "- Cand il folosesti: Pentru vectori mari, cel mai folosit în practică\n";
        cout << "- Avantaje: Foarte rapid în practică, sortare în loc (nu folosește memorie extra)\n\n";
    
        cout << "MERGE SORT:\n";
        cout << "- Cum functioneaza: Împarte vectorul în jumătăți până când ai elemente singure,\n";
        cout << "  apoi le reunește în ordine\n";
        cout << "- Complexitate: O(n log n) întotdeauna\n";
        cout << "- Cand il folosesti: Când ai nevoie de performanță garantată O(n log n)\n";
        cout << "- Avantaje: Performanță stabilă, bun pentru liste înlănțuite\n";
        cout << "- Dezavantaje: Folosește memorie extra\n\n";
    
        cout << "HEAP SORT:\n";
        cout << "- Cum functioneaza: Construiește un heap (arbore binar), extrage rădăcina (maximul)\n";
        cout << "  repetat până se golește heap-ul\n";
        cout << "- Complexitate: O(n log n) întotdeauna\n";
        cout << "- Cand il folosesti: Când vrei O(n log n) garantat și memorie limitată\n";
        cout << "- Avantaje: Nu folosește memorie extra, performanță garantată\n";
    
        return 0;
    }

    10. PROIECT INTEGRAT: Sistem de Sortare Complet

    #include <iostream>
    using namespace std;
    
    // Funcții pentru diferite tipuri de sortări
    void bubbleSort(int v[], int n) {
        for(int i = 0; i < n - 1; i++) {
            for(int j = 0; j < n - i - 1; j++) {
                if(v[j] > v[j + 1]) {
                    int temp = v[j];
                    v[j] = v[j + 1];
                    v[j + 1] = temp;
                }
            }
        }
    }
    
    void selectionSort(int v[], int n) {
        for(int i = 0; i < n - 1; i++) {
            int minIdx = i;
            for(int j = i + 1; j < n; j++) {
                if(v[j] < v[minIdx]) {
                    minIdx = j;
                }
            }
            if(minIdx != i) {
                int temp = v[i];
                v[i] = v[minIdx];
                v[minIdx] = temp;
            }
        }
    }
    
    void insertionSort(int v[], int n) {
        for(int i = 1; i < n; i++) {
            int key = v[i];
            int j = i - 1;
            while(j >= 0 && v[j] > key) {
                v[j + 1] = v[j];
                j--;
            }
            v[j + 1] = key;
        }
    }
    
    void afiseazaVector(int v[], int n, string mesaj) {
        cout << mesaj;
        for(int i = 0; i < n; i++) {
            cout << v[i] << " ";
        }
        cout << endl;
    }
    
    int main() {
        const int MAX = 50;
        int vector[MAX], copie[MAX];
        int n;
    
        cout << "=== SISTEM COMPLET DE SORTARE ===\n\n";
    
        // Citire dimensiune
        cout << "Cate numere vrei sa sortezi? (max " << MAX << "): ";
        cin >> n;
    
        if(n <= 0 || n > MAX) {
            cout << "Dimensiune invalida!" << endl;
            return 1;
        }
    
        // Generare sau citire numere
        int optiuneGenerare;
        cout << "\nCum vrei sa introduci numerele?\n";
        cout << "1. Manual (de la tastatura)\n";
        cout << "2. Automat (numere aleatoare)\n";
        cout << "Alegerea ta: ";
        cin >> optiuneGenerare;
    
        if(optiuneGenerare == 1) {
            cout << "Introdu " << n << " numere:\n";
            for(int i = 0; i < n; i++) {
                cout << "Numarul " << i+1 << ": ";
                cin >> vector[i];
            }
        } else {
            // Generare numere aleatoare între 1 și 100
            cout << "Generam " << n << " numere aleatoare intre 1 si 100...\n";
            for(int i = 0; i < n; i++) {
                vector[i] = rand() % 100 + 1;
            }
        }
    
        // Salvare copie pentru a testa fiecare algoritm pe aceleași date
        for(int i = 0; i < n; i++) {
            copie[i] = vector[i];
        }
    
        afiseazaVector(vector, n, "\nVector inainte de sortare: ");
    
        // Meniu algoritmi
        cout << "\n=== ALGORITMI DISPONIBILI ===\n";
        cout << "1. Bubble Sort\n";
        cout << "2. Selection Sort\n";
        cout << "3. Insertion Sort\n";
        cout << "4. Toate (comparatie)\n";
        cout << "Alegerea ta: ";
    
        int alegere;
        cin >> alegere;
    
        switch(alegere) {
            case 1:
                bubbleSort(vector, n);
                afiseazaVector(vector, n, "\nRezultat Bubble Sort: ");
                break;
    
            case 2:
                selectionSort(vector, n);
                afiseazaVector(vector, n, "\nRezultat Selection Sort: ");
                break;
    
            case 3:
                insertionSort(vector, n);
                afiseazaVector(vector, n, "\nRezultat Insertion Sort: ");
                break;
    
            case 4:
                // Testează toate algoritmle pe aceleași date
                cout << "\n=== COMPARATIE ALGORITMI ===\n";
    
                // Bubble Sort
                for(int i = 0; i < n; i++) vector[i] = copie[i];
                bubbleSort(vector, n);
                afiseazaVector(vector, n, "Bubble Sort:    ");
    
                // Selection Sort
                for(int i = 0; i < n; i++) vector[i] = copie[i];
                selectionSort(vector, n);
                afiseazaVector(vector, n, "Selection Sort: ");
    
                // Insertion Sort
                for(int i = 0; i < n; i++) vector[i] = copie[i];
                insertionSort(vector, n);
                afiseazaVector(vector, n, "Insertion Sort: ");
                break;
    
            default:
                cout << "Alegere invalida!" << endl;
        }
    
        // Verificare dacă vectorul e sortat corect
        bool sortatCorect = true;
        for(int i = 0; i < n - 1; i++) {
            if(vector[i] > vector[i + 1]) {
                sortatCorect = false;
                break;
            }
        }
    
        if(sortatCorect) {
            cout << "\n✓ Vectorul a fost sortat CORECT (crescator)!" << endl;
        } else {
            cout << "\n✗ Vectorul NU este sortat corect!" << endl;
        }
    
        // Opțiuni suplimentare
        cout << "\n=== OPȚIUNI SUPLIMENTARE ===\n";
        cout << "1. Afiseaza elementul minim si maxim\n";
        cout << "2. Afiseaza mediana\n";
        cout << "3. Cauta un element in vectorul sortat\n";
        cout << "4. Iesire\n";
        cout << "Alegerea ta: ";
    
        int optiuneSuplimentara;
        cin >> optiuneSuplimentara;
    
        switch(optiuneSuplimentara) {
            case 1:
                cout << "\nMinim: " << vector[0] << endl;
                cout << "Maxim: " << vector[n-1] << endl;
                break;
    
            case 2:
                if(n % 2 == 1) {
                    cout << "\nMediana: " << vector[n/2] << endl;
                } else {
                    cout << "\nMediana: (" << vector[n/2 - 1] << " + " << vector[n/2] 
                         << ") / 2 = " << (vector[n/2 - 1] + vector[n/2]) / 2.0 << endl;
                }
                break;
    
            case 3:
                int elementCautat;
                cout << "\nCe element cauti? ";
                cin >> elementCautat;
    
                // Căutare binară (rapidă în vector sortat!)
                int stanga = 0, dreapta = n - 1;
                bool gasit = false;
                int pasi = 0;
    
                while(stanga <= dreapta && !gasit) {
                    pasi++;
                    int mijloc = (stanga + dreapta) / 2;
    
                    if(vector[mijloc] == elementCautat) {
                        gasit = true;
                        cout << "Elementul " << elementCautat << " a fost gasit pe pozitia " 
                             << mijloc << endl;
                    } else if(vector[mijloc] < elementCautat) {
                        stanga = mijloc + 1;
                    } else {
                        dreapta = mijloc - 1;
                    }
                }
    
                if(!gasit) {
                    cout << "Elementul " << elementCautat << " NU a fost gasit in vector!" << endl;
                }
                cout << "Cautarea a durat " << pasi << " pasi (binara vs " << n << " pasi liniara)" << endl;
                break;
        }
    
        cout << "\nLa revedere!" << endl;
        return 0;
    }

    În concluzie, să-ți spun ceva fundamental:

    Sortarea nu e doar o operație tehnică – e o unealtă fundamentală care transformă datele dezorganizate în informație utilă.

  • Vectori în C++: Cutii Magice cu Mai Multe Numere la Un Loc

    Bun, hai să vorbim despre unul dintre cele mai utile și fundamentale concepte din programare: VECTORII (Array-urile). Nu e doar despre liste (cuvânt simplu) și colecții. E despre cum poți stoca și manipula sute, mii, chiar milioane de valori într-un singur nume. E un concept atât de puternic încât dacă ar fi să lucrezi cu date fără vectori, ar fi ca și cum ai încerca să cari 100 de ouă cu mâinile goale în loc să folosești o cutie de ouă.

    1. Ce este un Vector? “O Cutie cu Mai Mulg Compartimente”

    Gândește-te la un vector ca la un rând de cutii numerotate într-un dulap: fiecare cutie are un număr (indicele) și poate conține câte o valoare. Toate cutiile sunt de același tip (toate pentru numere, toate pentru litere, etc.).

    Definiția Vectorului:
    Un vector este o colecție de elemente de același tip, stocate în locații consecutive de memorie, accesibile prin indici.

    Analogie cu un Bloc de Apartamente:

    Fără vector: “Apartamentul lui Popescu”, “Apartamentul lui Ionescu”, “Apartamentul lui Georgescu” – variabile separate

    Cu vector: bloc[0] = Popescu, bloc[1] = Ionescu, bloc[2] = Georgescu

    Toți locuiesc în ACELAȘI BLOC, doar la etaje/numere diferite!

    2. Cum se Declară un Vector? “Cumpărăm Dulapul”

    #include <iostream>
    using namespace std;
    
    int main() {
        // METODA 1: Declarare cu dimensiune fixă
        int note[10];  // Vector cu 10 elemente întregi
    
        // METODA 2: Declarare cu inițializare
        int zileLuna[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
        // METODA 3: Declarare cu dimensiune și inițializare parțială
        int numere[5] = {1, 2, 3};  // Ultimele 2 elemente vor fi 0
    
        // ATENȚIE: Dimensiunea trebuie să fie constantă în C++ standard!
        const int N = 100;
        int vectorMare[N];  // OK pentru că N e constant
    
        return 0;
    }

    3. Cum se Accesează Elementele? “Deschidem Cutia cu Numărul X”

    CHEIE IMPORTANTĂ: Indicele începe de la 0, nu de la 1!

    #include <iostream>
    using namespace std;
    
    int main() {
        int vector[5] = {10, 20, 30, 40, 50};
    
        // ACCESAREA elementelor:
        cout << "Primul element (index 0): " << vector[0] << endl;   // 10
        cout << "Al doilea element (index 1): " << vector[1] << endl;  // 20
        cout << "Ultimul element (index 4): " << vector[4] << endl;   // 50
    
        // MODIFICAREA elementelor:
        vector[0] = 100;   // Schimbă primul element din 10 în 100
        vector[2] = 300;   // Schimbă al treilea element din 30 în 300
    
        cout << "\nDupa modificari:" << endl;
        cout << "vector[0] = " << vector[0] << endl;  // 100
        cout << "vector[2] = " << vector[2] << endl;  // 300
    
        // CALCULE cu elemente:
        int suma = vector[1] + vector[3];  // 20 + 40 = 60
        cout << "Suma elementelor 1 si 3: " << suma << endl;
    
        return 0;
    }

    4. Cum se Parcurg Vectorii? “Vizităm Toate Cutiiile pe Rând”

    #include <iostream>
    using namespace std;
    
    int main() {
        int vector[10] = {5, 8, 3, 9, 1, 7, 2, 6, 4, 0};
    
        cout << "=== PARCURGERE VECTOR ===" << endl;
    
        // Parcurgere cu FOR clasic
        cout << "Elementele vectorului:" << endl;
        for(int i = 0; i < 10; i++) {
            cout << "vector[" << i << "] = " << vector[i] << endl;
        }
    
        // Parcurgere pentru calcul (suma)
        int suma = 0;
        for(int i = 0; i < 10; i++) {
            suma = suma + vector[i];  // Adună fiecare element
        }
        cout << "\nSuma elementelor: " << suma << endl;
    
        // Parcurgere pentru găsirea maximului
        int maxim = vector[0];  // Presupunem că primul e maxim
        for(int i = 1; i < 10; i++) {
            if(vector[i] > maxim) {
                maxim = vector[i];  // Am găsit un număr mai mare
            }
        }
        cout << "Valoarea maxima: " << maxim << endl;
    
        // Parcurgere pentru numărare (câte numere pare)
        int numarPare = 0;
        for(int i = 0; i < 10; i++) {
            if(vector[i] % 2 == 0) {  // Dacă e par
                numarPare++;
            }
        }
        cout << "Numere pare: " << numarPare << endl;
    
        return 0;
    }

    5. Cum se Citesc Vectorii de la Tastatură? “Umplem Cutiiile”

    #include <iostream>
    using namespace std;
    
    int main() {
        const int N = 5;
        int vector[N];
    
        cout << "=== CITIRE VECTOR DE LA TASTATURA ===" << endl;
    
        // Metoda 1: Citire într-o buclă
        cout << "Introdu " << N << " numere:" << endl;
        for(int i = 0; i < N; i++) {
            cout << "vector[" << i << "] = ";
            cin >> vector[i];
        }
    
        // Afișare pentru verificare
        cout << "\nNumerele introduse sunt:" << endl;
        for(int i = 0; i < N; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        // Metoda 2: Citire cu validare
        int altVector[5];
        cout << "\nIntrodu 5 numere pozitive:" << endl;
    
        for(int i = 0; i < 5; i++) {
            do {
                cout << "Numar pozitiv " << i+1 << ": ";
                cin >> altVector[i];
    
                if(altVector[i] < 0) {
                    cout << "Numar negativ! Introdu din nou." << endl;
                }
            } while(altVector[i] < 0);  // Repetă până primești număr pozitiv
        }
    
        return 0;
    }

    6. Operații Esentiale cu Vectori

    6.1 Căutarea unui Element – “Găsește Cheia în Grămadă”

    #include <iostream>
    using namespace std;
    
    int main() {
        int vector[8] = {23, 45, 12, 67, 89, 34, 56, 78};
        int elementCautat;
    
        cout << "Introdu elementul pe care il cauti: ";
        cin >> elementCautat;
    
        // Căutare liniară (verifică fiecare element)
        bool gasit = false;
        int pozitie = -1;
    
        for(int i = 0; i < 8; i++) {
            if(vector[i] == elementCautat) {
                gasit = true;
                pozitie = i;
                break;  // Ieșim din buclă când l-am găsit
            }
        }
    
        if(gasit) {
            cout << "Elementul " << elementCautat << " a fost gasit pe pozitia " << pozitie << endl;
        } else {
            cout << "Elementul " << elementCautat << " NU a fost gasit in vector!" << endl;
        }
    
        return 0;
    }

    6.2 Inversarea unui Vector – “Întoarce Oglinda”

    #include <iostream>
    using namespace std;
    
    int main() {
        int vector[6] = {1, 2, 3, 4, 5, 6};
    
        cout << "Vector initial: ";
        for(int i = 0; i < 6; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        // Inversare vector (schimbă primul cu ultimul, etc.)
        for(int i = 0; i < 3; i++) {  // Doar până la jumătate!
            int temp = vector[i];
            vector[i] = vector[5 - i];  // 5 = ultimul index (6-1)
            vector[5 - i] = temp;
        }
    
        cout << "Vector inversat: ";
        for(int i = 0; i < 6; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        return 0;
    }

    6.3 Sortarea (Bubble Sort) – “Aranjează în Ordine”

    #include <iostream>
    using namespace std;
    
    int main() {
        int vector[7] = {64, 34, 25, 12, 22, 11, 90};
    
        cout << "Vector nesortat: ";
        for(int i = 0; i < 7; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        // Bubble Sort - cel mai simplu algoritm de sortare
        for(int i = 0; i < 7 - 1; i++) {
            for(int j = 0; j < 7 - i - 1; j++) {
                if(vector[j] > vector[j + 1]) {
                    // Schimbă elementele dacă sunt în ordine greșită
                    int temp = vector[j];
                    vector[j] = vector[j + 1];
                    vector[j + 1] = temp;
                }
            }
        }
    
        cout << "Vector sortat crescator: ";
        for(int i = 0; i < 7; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        return 0;
    }

    6.4 Concatenarea a Doi Vectori – “Lipirea a Două Trenuri”

    #include <iostream>
    using namespace std;
    
    int main() {
        int vector1[3] = {1, 2, 3};
        int vector2[4] = {4, 5, 6, 7};
        int rezultat[7];  // 3 + 4 = 7 elemente
    
        // Copiem primul vector
        for(int i = 0; i < 3; i++) {
            rezultat[i] = vector1[i];
        }
    
        // Adăugăm al doilea vector
        for(int i = 0; i < 4; i++) {
            rezultat[3 + i] = vector2[i];  // Începem de la poziția 3
        }
    
        cout << "Vectorul 1: ";
        for(int i = 0; i < 3; i++) cout << vector1[i] << " ";
        cout << endl;
    
        cout << "Vectorul 2: ";
        for(int i = 0; i < 4; i++) cout << vector2[i] << " ";
        cout << endl;
    
        cout << "Vector concatenat: ";
        for(int i = 0; i < 7; i++) cout << rezultat[i] << " ";
        cout << endl;
    
        return 0;
    }

    7. Vectori cu Dimensiune Variabilă (Citită de la Tastatură)

    #include <iostream>
    using namespace std;
    
    int main() {
        // ATENȚIE: În C++ standard, dimensiunea trebuie să fie constantă!
        // Dar putem folosi o constantă mare și folosi doar o parte
    
        const int MAX = 1000;  // Dimensiune maximă
        int vector[MAX];
        int n;  // Dimensiunea reală pe care o vom folosi
    
        cout << "Cate elemente vrei sa introduci? (max " << MAX << "): ";
        cin >> n;
    
        // Verificare dimensiune validă
        if(n <= 0 || n > MAX) {
            cout << "Dimensiune invalida!" << endl;
            return 1;  // Ieșim cu eroare
        }
    
        // Citire elemente
        cout << "Introdu " << n << " numere:" << endl;
        for(int i = 0; i < n; i++) {
            cout << "Elementul " << i+1 << ": ";
            cin >> vector[i];
        }
    
        // Calcul statistici
        int suma = 0, minim = vector[0], maxim = vector[0];
    
        for(int i = 0; i < n; i++) {
            suma += vector[i];
    
            if(vector[i] < minim) minim = vector[i];
            if(vector[i] > maxim) maxim = vector[i];
        }
    
        double media = (double)suma / n;
    
        cout << "\n=== STATISTICI ===" << endl;
        cout << "Suma: " << suma << endl;
        cout << "Media: " << media << endl;
        cout << "Minim: " << minim << endl;
        cout << "Maxim: " << maxim << endl;
    
        return 0;
    }

    8. Vectori de Alte Tipuri (Nu Doar Numere)

    8.1 Vectori de Caractere (String-uri Simple)

    #include <iostream>
    using namespace std;
    
    int main() {
        // Vector de caractere (similar cu string)
        char nume[20];  // Poate stoca 19 caractere + terminatorul '\0'
    
        cout << "Introdu numele tau (max 19 caractere): ";
        cin >> nume;  // Cin funcționează și cu vectori de caractere!
    
        cout << "Salut, " << nume << "!" << endl;
    
        // Parcurgere caracter cu caracter
        cout << "Numele tau litera cu litera: ";
        for(int i = 0; nume[i] != '\0'; i++) {  // '\0' = sfârșitul șirului
            cout << nume[i] << "-";
        }
        cout << endl;
    
        return 0;
    }

    8.2 Vectori de Numere Reale

    #include <iostream>
    using namespace std;
    
    int main() {
        double temperaturi[7];  // Temperaturile săptămânii
    
        cout << "Introdu temperaturile saptamanii:" << endl;
        for(int i = 0; i < 7; i++) {
            cout << "Ziua " << i+1 << ": ";
            cin >> temperaturi[i];
        }
    
        // Calcul temperatură medie
        double suma = 0;
        for(int i = 0; i < 7; i++) {
            suma += temperaturi[i];
        }
        double medie = suma / 7;
    
        // Zilele peste medie
        cout << "\nTemperatura medie: " << medie << "°C" << endl;
        cout << "Zile cu temperatura peste medie:" << endl;
    
        for(int i = 0; i < 7; i++) {
            if(temperaturi[i] > medie) {
                cout << "Ziua " << i+1 << ": " << temperaturi[i] << "°C" << endl;
            }
        }
    
        return 0;
    }

    9. Probleme Practice cu Vectori

    Problema 1: Numărarea Frecvenței

    #include <iostream>
    using namespace std;
    
    int main() {
        const int N = 10;
        int vector[N] = {2, 5, 2, 8, 5, 6, 2, 8, 8, 5};
    
        cout << "Vector: ";
        for(int i = 0; i < N; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        // Pentru fiecare element, numără de câte ori apare
        cout << "\n=== FRECVENTA ELEMENTELOR ===" << endl;
    
        for(int i = 0; i < N; i++) {
            // Verificăm dacă am numărat deja acest element
            bool dejaNumarat = false;
    
            for(int j = 0; j < i; j++) {
                if(vector[j] == vector[i]) {
                    dejaNumarat = true;
                    break;
                }
            }
    
            // Dacă nu l-am numărat, îl numărăm acum
            if(!dejaNumarat) {
                int frecventa = 1;
    
                for(int j = i + 1; j < N; j++) {
                    if(vector[j] == vector[i]) {
                        frecventa++;
                    }
                }
    
                cout << "Elementul " << vector[i] << " apare de " << frecventa << " ori" << endl;
            }
        }
    
        return 0;
    }

    Problema 2: Ștergerea unui Element

    #include <iostream>
    using namespace std;
    
    int main() {
        const int MAX = 10;
        int vector[MAX] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int n = 10;  // Dimensiunea curentă
    
        cout << "Vector initial (" << n << " elemente): ";
        for(int i = 0; i < n; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        // Șterge elementul de pe poziția 3 (al 4-lea element, index 3)
        int pozitie = 3;
    
        if(pozitie >= 0 && pozitie < n) {
            // Mută toate elementele de după poziție cu un spațiu în stânga
            for(int i = pozitie; i < n - 1; i++) {
                vector[i] = vector[i + 1];
            }
            n--;  // Scade dimensiunea
    
            cout << "Dupa stergerea elementului de pe pozitia " << pozitie << ":" << endl;
            cout << "Vector (" << n << " elemente): ";
            for(int i = 0; i < n; i++) {
                cout << vector[i] << " ";
            }
            cout << endl;
        } else {
            cout << "Pozitie invalida!" << endl;
        }
    
        return 0;
    }

    Problema 3: Inserarea unui Element

    #include <iostream>
    using namespace std;
    
    int main() {
        const int MAX = 15;
        int vector[MAX] = {10, 20, 30, 40, 50, 60, 70};
        int n = 7;  // Dimensiunea curentă
    
        cout << "Vector initial (" << n << " elemente): ";
        for(int i = 0; i < n; i++) {
            cout << vector[i] << " ";
        }
        cout << endl;
    
        // Inserează valoarea 25 pe poziția 2 (al 3-lea element)
        int valoare = 25;
        int pozitie = 2;
    
        if(n < MAX && pozitie >= 0 && pozitie <= n) {
            // Mută toate elementele de la poziție încolo cu un spațiu la dreapta
            for(int i = n; i > pozitie; i--) {
                vector[i] = vector[i - 1];
            }
    
            // Pune noua valoare
            vector[pozitie] = valoare;
            n++;  // Crește dimensiunea
    
            cout << "Dupa inserarea lui " << valoare << " pe pozitia " << pozitie << ":" << endl;
            cout << "Vector (" << n << " elemente): ";
            for(int i = 0; i < n; i++) {
                cout << vector[i] << " ";
            }
            cout << endl;
        } else {
            cout << "Nu se poate insera!" << endl;
        }
    
        return 0;
    }

    10. Vectori ca Parametri ai Funcțiilor (Bonus Avansat)

    #include <iostream>
    using namespace std;
    
    // Funcție care primește un vector ca parametru
    void afiseazaVector(int v[], int n) {
        cout << "Vector: ";
        for(int i = 0; i < n; i++) {
            cout << v[i] << " ";
        }
        cout << endl;
    }
    
    // Funcție care calculează suma elementelor
    int calculeazaSuma(int v[], int n) {
        int suma = 0;
        for(int i = 0; i < n; i++) {
            suma += v[i];
        }
        return suma;
    }
    
    // Funcție care modifică vectorul (sortează)
    void sorteazaCrescator(int v[], int n) {
        for(int i = 0; i < n - 1; i++) {
            for(int j = 0; j < n - i - 1; j++) {
                if(v[j] > v[j + 1]) {
                    int temp = v[j];
                    v[j] = v[j + 1];
                    v[j + 1] = temp;
                }
            }
        }
    }
    
    int main() {
        const int N = 6;
        int vector[N] = {45, 12, 89, 3, 67, 23};
    
        cout << "=== OPERATII CU VECTORI PRIN FUNCTII ===" << endl;
    
        afiseazaVector(vector, N);
    
        int suma = calculeazaSuma(vector, N);
        cout << "Suma elementelor: " << suma << endl;
        cout << "Media: " << (double)suma / N << endl;
    
        sorteazaCrescator(vector, N);
        cout << "\nDupa sortare:" << endl;
        afiseazaVector(vector, N);
    
        return 0;
    }

    11. PROIECT INTEGRAT: Sistem de Note cu Vectori

    #include <iostream>
    using namespace std;
    
    int main() {
        const int MAX_STUDENTI = 100;
        const int MAX_MATERII = 10;
    
        double note[MAX_STUDENTI][MAX_MATERII];  // Matrice (vezi următoarea lecție)
        int numarStudenti, numarMaterii;
    
        cout << "=== SISTEM DE GESTIUNE NOTE ===\n\n";
    
        // Citire dimensiuni
        cout << "Cati studenti? (max " << MAX_STUDENTI << "): ";
        cin >> numarStudenti;
    
        cout << "Cate materii? (max " << MAX_MATERII << "): ";
        cin >> numarMaterii;
    
        // Validare
        if(numarStudenti <= 0 || numarStudenti > MAX_STUDENTI ||
           numarMaterii <= 0 || numarMaterii > MAX_MATERII) {
            cout << "Date invalide!" << endl;
            return 1;
        }
    
        // Citire note pentru fiecare student și materie
        for(int student = 0; student < numarStudenti; student++) {
            cout << "\n=== STUDENTUL " << student + 1 << " ===\n";
    
            for(int materie = 0; materie < numarMaterii; materie++) {
                cout << "Nota la materia " << materie + 1 << ": ";
                cin >> note[student][materie];
    
                // Validare nota
                while(note[student][materie] < 1 || note[student][materie] > 10) {
                    cout << "Nota trebuie sa fie intre 1 si 10! Introdu din nou: ";
                    cin >> note[student][materie];
                }
            }
        }
    
        // Calcul medii studenți
        cout << "\n\n=== MEDII STUDENTI ===\n";
        for(int student = 0; student < numarStudenti; student++) {
            double suma = 0;
    
            for(int materie = 0; materie < numarMaterii; materie++) {
                suma += note[student][materie];
            }
    
            double medie = suma / numarMaterii;
            cout << "Studentul " << student + 1 << ": Medie = " << medie;
    
            if(medie >= 5.0) {
                cout << " (Promovat)";
            } else {
                cout << " (Respins)";
            }
            cout << endl;
        }
    
        // Calcul medii pe materii
        cout << "\n=== MEDII MATERII ===\n";
        for(int materie = 0; materie < numarMaterii; materie++) {
            double suma = 0;
    
            for(int student = 0; student < numarStudenti; student++) {
                suma += note[student][materie];
            }
    
            double medieMaterie = suma / numarStudenti;
            cout << "Materia " << materie + 1 << ": Medie = " << medieMaterie << endl;
        }
    
        return 0;
    }

    În concluzie, să-ți spun ceva fundamental:

    Vectorii sunt fundamentul stocării datelor multiple în programare. Transformă problema “cum să țin 100 de numere” din “100 de variabile separate” în “o singură variabilă cu 100 de slot-uri”.

    Dar folosirea incorectă a vectorilor (accesarea în afara limitelor cu vector[100] când vectorul are doar 10 elemente) poate fi, paradoxal, o sursă de erori grave și crash-uri de program dacă nu ești atent la indici.

    Așa că ai grijă când lucrezi cu vectori. Cunoștințe-ti limitele: câte elemente ai? Unde începe indexarea (0!)? Unde se termină (n-1!)? Pentru că puterea de a stoca multe date într-o singură variabilă este goală fără înțelegerea cum să le accesezi în siguranță. Și această putere vine cu o responsabilitate: să fii precis cu indicii și dimensiunile.

    Stăpânirea vectorilor este o parte integrală și esențială a programării în C++. Ai grijă de ea cu aceeași seriozitate.

  • Subprograme în C++: Cum ÎmpArți un Program Mare în Bucăți Mici – Materie BAC

    Bun, hai să vorbim despre unul dintre cele mai puternice concepte din programare: SUBPROGRAMELE (Funcțiile). Nu e doar despre organizare (cuvânt plictisitor) și modularizare. E despre cum transformi un program lung și confuz într-o colecție de piese mici, clare și reutilizabile. E o tehnică atât de importantă încât dacă ar fi să scrii un program fără funcții, ar arăta ca un mur de text fără cap și coadă.

    1. Ce este un Subprogram? “Un Mic Robot Specializat”

    Gândește-te la un subprogram ca la un angajat specializat într-o fabrică: fiecare știe să facă o singură lucru perfect, primește materiale (parametri), le procesează și dă înapoi un rezultat.

    Definiția Subprogramului:
    Un subprogram este o secvență de instrucțiuni cu un nume, care poate fi apelată de diferite ori din program. Este ca o rețetă pe care o poți folosi de mai multe ori fără să o rescrii.

    Analogie cu o Fabrica de Mașini:

    Fără funcții: Un singur muncitor face TOATE etapele pentru FIECARE mașină
    Cu funcții:

    • Muncitorul A asamblează motorul (funcție asambleazaMotor())
    • Muncitorul B montează roțile (funcție monteazaRoti())
    • Muncitorul C instalează scaunele (funcție instaleazaScaune())

    Pentru fiecare mașină, apelezi aceiași muncitori în aceeași ordine!

    2. De ce avem nevoie de Subprograme? “Divide et Impera”

    FĂRĂ funcții:

    #include <iostream>
    using namespace std;
    
    int main() {
        // Calculează suma a 3 numere
        int a = 5, b = 3, c = 7;
        int suma1 = a + b + c;
        cout << "Suma 1: " << suma1 << endl;
    
        // Mai calculează o sumă
        int x = 10, y = 20, z = 30;
        int suma2 = x + y + z;  // COD DUPLICAT!
        cout << "Suma 2: " << suma2 << endl;
    
        // Și încă o sumă
        int p = 1, q = 2, r = 3;
        int suma3 = p + q + r;  // IARĂȘI COD DUPLICAT!
        cout << "Suma 3: " << suma3 << endl;
    
        return 0;
    }

    CU funcții:

    #include <iostream>
    using namespace std;
    
    // FUNCȚIE care calculează suma a 3 numere
    int calculeazaSuma(int a, int b, int c) {
        return a + b + c;
    }
    
    int main() {
        // Folosește aceeași funcție de 3 ori!
        cout << "Suma 1: " << calculeazaSuma(5, 3, 7) << endl;
        cout << "Suma 2: " << calculeazaSuma(10, 20, 30) << endl;
        cout << "Suma 3: " << calculeazaSuma(1, 2, 3) << endl;
    
        return 0;
    }

    BENEFICIILE funcțiilor:

    1. ELIMINĂ duplicarea de cod
    2. FACILITEAZĂ depanarea (bug-ul e într-un singur loc)
    3. SPOREȘTE reutilizarea (folosești aceeași funcție peste tot)
    4. ÎMBUNĂTĂȚEȘTE lizibilitatea (nume descriptive pentru acțiuni)
    5. PERMITE colaborarea (fiecare programator scrie funcții diferite)

    3. Cele Două Tipuri Fundamentale de Subprograme

    TIPUL 1: FUNCȚII care RETURNEAZĂ o valoare (cu int, double, etc.)

    // Acestea SUNT ca niște "calculatoare":
    // Primește numere → Calculează → Returnează rezultat
    
    int aduna(int a, int b) {
        int suma = a + b;
        return suma;  // RETURNEZĂ ceva!
    }
    
    double calculeazaMedie(double x, double y) {
        return (x + y) / 2;  // Returnează direct
    }

    TIPUL 2: PROCEDURI care NU returnează nimic (cu void)

    // Acestea SUNT ca niște "efectuatori de acțiuni":
    // Fac ceva → Nu returnează valoare
    
    void afiseazaMesaj() {
        cout << "Buna ziua!" << endl;
        // NU are return cu valoare!
    }
    
    void afiseazaSuma(int a, int b) {
        cout << "Suma este: " << (a + b) << endl;
        // Afișează dar nu returnează valoare
    }

    4. Anatomia unei Funcții: Toate Părțile Ei

    // 1. TIPUL de return (ce returnează funcția)
    // 2. NUMELE funcției (cum o chemi)
    // 3. PARAMETRII (ce primește funcția)
    // 4. CORPUL funcției (ce face ea)
    // 5. INSTRUCȚIUNEA return (ce dă înapoi)
    
          1       2        3
          ↓       ↓        ↓
    int calculeazaPatrat(int numar) {
        // 4. Corpul funcției
        int patrat = numar * numar;
    
        // 5. Return (dă rezultatul înapoi)
        return patrat;
        ↑
        5
    }
    
    // APELUL funcției:
    int rezultat = calculeazaPatrat(5);  // rezultat va fi 25

    5. Funcții care RETURNEAZĂ Valori (int, double, bool, etc.)

    Exemplul 1: Funcție care calculează puterea unui număr

    #include <iostream>
    using namespace std;
    
    // Funcție care CALCULEAZĂ și RETURNEAZĂ
    int ridicaLaPutere(int baza, int exponent) {
        int rezultat = 1;
    
        for(int i = 0; i < exponent; i++) {
            rezultat = rezultat * baza;
        }
    
        return rezultat;  // IMPORTANT: dă valoarea înapoi
    }
    
    int main() {
        // Folosirea funcției
        int patrat = ridicaLaPutere(5, 2);    // 5² = 25
        int cub = ridicaLaPutere(3, 3);       // 3³ = 27
        int putereMare = ridicaLaPutere(2, 10); // 2¹⁰ = 1024
    
        cout << "5 la puterea 2: " << patrat << endl;
        cout << "3 la puterea 3: " << cub << endl;
        cout << "2 la puterea 10: " << putereMare << endl;
    
        // Poți folosi rezultatul direct în calcule
        int suma = ridicaLaPutere(2, 3) + ridicaLaPutere(3, 2);
        cout << "2³ + 3² = " << suma << endl;  // 8 + 9 = 17
    
        return 0;
    }

    Exemplul 2: Funcție care verifică dacă un număr este prim

    #include <iostream>
    using namespace std;
    
    // Funcție care RETURNEAZĂ true/false (bool)
    bool esteNumarPrim(int n) {
        if (n <= 1) {
            return false;  // 0 și 1 nu sunt prime
        }
    
        // Verifică divizorii de la 2 până la n/2
        for(int i = 2; i <= n/2; i++) {
            if (n % i == 0) {
                return false;  // Am găsit un divizor
            }
        }
    
        return true;  // E număr prim
    }
    
    int main() {
        int numar;
    
        cout << "Introdu un numar: ";
        cin >> numar;
    
        // Folosim funcția în condiție
        if (esteNumarPrim(numar)) {
            cout << numar << " ESTE numar prim!" << endl;
        } else {
            cout << numar << " NU este numar prim!" << endl;
        }
    
        // Verifică mai multe numere într-o buclă
        cout << "\nPrimele 20 de numere prime: ";
        int gasite = 0;
        int i = 2;
    
        while(gasite < 20) {
            if (esteNumarPrim(i)) {
                cout << i << " ";
                gasite++;
            }
            i++;
        }
    
        return 0;
    }

    Exemplul 3: Funcție care calculează factorialul

    #include <iostream>
    using namespace std;
    
    // Funcție care CALCULEAZĂ factorial
    unsigned long long calculeazaFactorial(int n) {
        unsigned long long factorial = 1;
    
        for(int i = 1; i <= n; i++) {
            factorial = factorial * i;
        }
    
        return factorial;
    }
    
    int main() {
        for(int i = 0; i <= 10; i++) {
            cout << i << "! = " << calculeazaFactorial(i) << endl;
        }
    
        // Calcul combinat
        int n = 5, k = 3;
        // C(n,k) = n! / (k! * (n-k)!)
        unsigned long long combinari = calculeazaFactorial(n) / 
                                       (calculeazaFactorial(k) * calculeazaFactorial(n-k));
    
        cout << "\nCombinari de " << n << " luate cate " << k << " = " << combinari << endl;
    
        return 0;
    }

    6. Proceduri care NU returnează (void) – “Fă și uită”

    Exemplul 1: Procedură care afișează un mesaj

    #include <iostream>
    using namespace std;
    
    // Procedură VOID - nu returnează nimic
    void afiseazaLinieSeparatoare() {
        cout << "----------------------------------------" << endl;
    }
    
    void afiseazaHeader() {
        afiseazaLinieSeparatoare();
        cout << "         SISTEM DE GESTIUNE           " << endl;
        afiseazaLinieSeparatoare();
    }
    
    void afiseazaMeniu() {
        cout << "1. Adauga element" << endl;
        cout << "2. Sterge element" << endl;
        cout << "3. Afiseaza toate" << endl;
        cout << "4. Cauta element" << endl;
        cout << "0. Iesire" << endl;
    }
    
    int main() {
        afiseazaHeader();
        afiseazaMeniu();
        afiseazaLinieSeparatoare();
    
        return 0;
    }

    Exemplul 2: Procedură care modifică variabile prin referință

    #include <iostream>
    using namespace std;
    
    // Procedură care MODIFICĂ variabile primite
    void swap(int &a, int &b) {  // & = referință (modifică originalul)
        int temp = a;
        a = b;
        b = temp;
    }
    
    void sorteazaCrescator(int &x, int &y, int &z) {
        if (x > y) swap(x, y);
        if (x > z) swap(x, z);
        if (y > z) swap(y, z);
    }
    
    int main() {
        int a = 15, b = 3, c = 8;
    
        cout << "Inainte de sortare: " << a << ", " << b << ", " << c << endl;
    
        sorteazaCrescator(a, b, c);  // Modifică variabilele originale!
    
        cout << "Dupa sortare: " << a << ", " << b << ", " << c << endl;
    
        return 0;
    }

    7. Parametri: Cum Comunică Funcțiile cu Lumea

    TIPURI de parametri:

    1. Parametri FORMALI – ce scrii în definiția funcției
    2. Parametri ACTUALI – ce trimiți când apelezi funcția
    3. Transmisie prin VALOARE – primește o copie (nu modifică originalul)
    4. Transmisie prin REFERINȚĂ – primește originalul (îl poate modifica)
    #include <iostream>
    using namespace std;
    
    // Transmisie prin VALOARE (copie)
    void dubleazaValoare(int x) {  // x e copie
        x = x * 2;
        cout << "In functie: x = " << x << endl;
    }
    
    // Transmisie prin REFERINȚĂ (original)
    void dubleazaReferinta(int &x) {  // x e originalul
        x = x * 2;
        cout << "In functie: x = " << x << endl;
    }
    
    int main() {
        int numar = 5;
    
        cout << "INITIAL: numar = " << numar << endl;
    
        // Transmisie prin VALOARE
        dubleazaValoare(numar);  // Trimite o copie
        cout << "Dupa dubleazaValoare: numar = " << numar << endl;
        // numar rămâne 5! Funcția a lucrat cu o copie
    
        // Transmisie prin REFERINȚĂ
        dubleazaReferinta(numar);  // Trimite originalul
        cout << "Dupa dubleazaReferinta: numar = " << numar << endl;
        // numar devine 10! Funcția a modificat originalul
    
        return 0;
    }

    Când folosești fiecare?

    • VALOARE: Când funcția are nevoie doar să citească valoarea
    • REFERINȚĂ: Când funcția trebuie să modifice variabila originală
    • REFERINȚĂ CONSTANTĂ (const int &x): Când vrei să eviți copierea dar nu permiți modificarea

    8. Valori Implicite (Default) pentru Parametri

    #include <iostream>
    using namespace std;
    
    // Funcție cu parametri cu valori implicite
    void afiseazaMesaj(string mesaj = "Salut", int repetari = 1) {
        for(int i = 0; i < repetari; i++) {
            cout << mesaj << endl;
        }
    }
    
    int main() {
        // Poți apela în mai multe moduri:
        afiseazaMesaj();                    // Folosește ambele implicite
        afiseazaMesaj("Buna ziua");         // Doar mesaj, repetari implicit
        afiseazaMesaj("Hey", 3);            // Ambele specificate
    
        // Reguli pentru parametri default:
        // 1. Doar la sfârșitul listei de parametri
        // 2. Dinspre dreapta la stânga
    
        return 0;
    }

    9. Supraîncărcarea Funcțiilor (Function Overloading)

    #include <iostream>
    using namespace std;
    
    // Supraîncărcare: mai multe funcții cu ACELAȘI NUME dar parametri DIFERIȚI
    
    // Versiune pentru int
    int aduna(int a, int b) {
        cout << "Adunare int: ";
        return a + b;
    }
    
    // Versiune pentru double
    double aduna(double a, double b) {
        cout << "Adunare double: ";
        return a + b;
    }
    
    // Versiune pentru 3 numere
    int aduna(int a, int b, int c) {
        cout << "Adunare 3 numere: ";
        return a + b + c;
    }
    
    // Versiune pentru string-uri (concatenare)
    string aduna(string a, string b) {
        cout << "Concatenare string: ";
        return a + b;
    }
    
    int main() {
        // Compilatorul alege automat funcția corectă în funcție de parametri!
        cout << aduna(5, 3) << endl;           // Apelează aduna(int, int)
        cout << aduna(5.2, 3.1) << endl;       // Apelează aduna(double, double)
        cout << aduna(1, 2, 3) << endl;        // Apelează aduna(int, int, int)
        cout << aduna("Hello", " World") << endl; // Apelează aduna(string, string)
    
        return 0;
    }

    10. PROIECT INTEGRAT: Sistem Bancar cu Funcții

    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    // ========== DECLARAȚII FUNCȚII ==========
    void afiseazaMeniu();
    double citesteSuma(string mesaj);
    void depuneBani(double &sold);
    void retrageBani(double &sold);
    void afiseazaSold(double sold);
    void aplicaDobanda(double &sold, double rata);
    void conversieValuta(double sold);
    
    // ========== FUNCȚIA PRINCIPALĂ ==========
    int main() {
        double sold = 0.0;
        int optiune;
        bool ruleaza = true;
    
        cout << fixed << setprecision(2);
        cout << "=== BANCA NOASTRA ===\n";
    
        do {
            afiseazaMeniu();
            cout << "Alege optiunea: ";
            cin >> optiune;
    
            switch(optiune) {
                case 1:
                    depuneBani(sold);
                    break;
                case 2:
                    retrageBani(sold);
                    break;
                case 3:
                    afiseazaSold(sold);
                    break;
                case 4:
                    aplicaDobanda(sold, 5.0);  // 5% dobândă
                    break;
                case 5:
                    conversieValuta(sold);
                    break;
                case 0:
                    cout << "La revedere! Multumim ca folositi Banca Noastra!\n";
                    ruleaza = false;
                    break;
                default:
                    cout << "Optiune invalida!\n";
            }
    
            cout << endl;
        } while(ruleaza);
    
        return 0;
    }
    
    // ========== IMPLEMENTĂRI FUNCȚII ==========
    
    void afiseazaMeniu() {
        cout << "\n=== MENIU PRINCIPAL ===\n";
        cout << "1. Depune bani\n";
        cout << "2. Retrage bani\n";
        cout << "3. Vezi sold\n";
        cout << "4. Aplica dobanda (5%)\n";
        cout << "5. Conversie valuta\n";
        cout << "0. Iesire\n";
    }
    
    double citesteSuma(string mesaj) {
        double suma;
        cout << mesaj;
        cin >> suma;
    
        while(suma < 0) {
            cout << "Suma nu poate fi negativa! Introdu din nou: ";
            cin >> suma;
        }
    
        return suma;
    }
    
    void depuneBani(double &sold) {
        double suma = citesteSuma("Suma de depus: ");
        sold += suma;
        cout << "Ai depus " << suma << " RON. Sold nou: " << sold << " RON\n";
    }
    
    void retrageBani(double &sold) {
        double suma = citesteSuma("Suma de retras: ");
    
        if(suma <= sold) {
            sold -= suma;
            cout << "Ai retras " << suma << " RON. Sold ramas: " << sold << " RON\n";
        } else {
            cout << "Fonduri insuficiente! Sold disponibil: " << sold << " RON\n";
        }
    }
    
    void afiseazaSold(double sold) {
        cout << "Sold curent: " << sold << " RON\n";
    }
    
    void aplicaDobanda(double &sold, double rata) {
        if(sold > 0) {
            double dobanda = sold * (rata / 100);
            sold += dobanda;
            cout << "Dobanda (" << rata << "%): +" << dobanda << " RON\n";
            cout << "Sold nou: " << sold << " RON\n";
        } else {
            cout << "Nu poti primi dobanda pe sold negativ sau zero!\n";
        }
    }
    
    void conversieValuta(double sold) {
        const double cursEuro = 4.97;
        const double cursDolar = 4.58;
    
        cout << "\n=== CONVERSIE VALUTA ===\n";
        cout << "Sold in RON: " << sold << endl;
        cout << "Sold in EUR: " << sold / cursEuro << endl;
        cout << "Sold in USD: " << sold / cursDolar << endl;
    }

    11. Recursivitate: Funcții care se Apelează pe Ele Însele

    #include <iostream>
    using namespace std;
    
    // FUNCȚIE RECURSIVĂ - se apelează pe ea însăși
    int factorialRecursiv(int n) {
        // Caz de bază (oprește recursivitatea)
        if (n <= 1) {
            return 1;
        }
    
        // Pas recursiv (se apelează pe ea însăși)
        return n * factorialRecursiv(n - 1);
    }
    
    void numaraInvers(int n) {
        // Caz de bază
        if (n <= 0) {
            return;
        }
    
        // Acțiune
        cout << n << " ";
    
        // Apel recursiv
        numaraInvers(n - 1);
    }
    
    int main() {
        cout << "Factorial recursiv:\n";
        for(int i = 0; i <= 5; i++) {
            cout << i << "! = " << factorialRecursiv(i) << endl;
        }
    
        cout << "\nNumarare inversa: ";
        numaraInvers(10);
    
        return 0;
    }

    12. Best Practices pentru Funcții

    #include <iostream>
    using namespace std;
    
    // 1. DENUMEȘTE funcțiile VERB + SUBSTANTIV
    // PROST: int f(int x, int y)
    // BINE: int calculeazaSuma(int a, int b)
    
    // 2. O FUNCȚIE = O SINGURĂ RESPONSABILITATE
    // PROST: void proceseazaSiAfiseaza()  // Face prea multe!
    // BINE: void proceseazaDate() și void afiseazaRezultate()
    
    // 3. DOCUMENTEAZĂ cu comentarii
    /**
     * Calculează media aritmetică a două numere
     * @param a Primul număr
     * @param b Al doilea număr
     * @return Media aritmetică a celor două numere
     */
    double calculeazaMedia(double a, double b) {
        return (a + b) / 2;
    }
    
    // 4. FOLOSEȘTE parametri const când nu modifici datele
    void afiseazaVector(const int v[], int n) {  // const = doar citire
        for(int i = 0; i < n; i++) {
            cout << v[i] << " ";
        }
    }
    
    int main() {
        // 5. TESTEAZĂ funcțiile individual!
        // Nu aștepta până scrii tot programul
    
        cout << "Media lui 5 si 7: " << calculeazaMedia(5, 7) << endl;
    
        int vector[] = {1, 2, 3, 4, 5};
        afiseazaVector(vector, 5);
    
        return 0;
    }

    În concluzie, să-ți spun ceva fundamental:

    Subprogramele sunt cel mai important instrument pentru a scrie cod curat, modular și reutilizabil. Transformă programarea din “scris linii lungi” în “asamblare de componente”.

    Dar împărțirea excesivă în funcții prea mici poate fi, paradoxal, o sursă de confuzie dacă fiecare funcție face doar o linie de cod și trebuie să urmărești 20 de apeluri pentru o operație simplă.

    Așa că ai grijă cum împărți codul. Cunoștințe-ti logica: ce grup de instrucțiuni are sens să fie împreună? Ce poți refolosi? Ce e suficient de complex pentru a merita propria funcție? Pentru că puterea de a modulariza este goală fără înțelegerea când are sens să o faci. Și această putere vine cu o responsabilitate: să fii strategic, nu dogmatic.

    Folosirea inteligentă a subprogramelor este o parte integrală a programării profesioniste. Ai grijă de ea cu aceeași seriozitate.

  • Schimbări ale Structurilor Repetitive: Transformarea Din “Cât Timp” În “Repetă Până Când” (și Înapoi!) – Materie BAC

    Bun, hai să vorbim despre unul dintre cele mai practice și mai puțin înțelese transformări în programare: Cum schimbi o structură repetitivă într-o alta. Nu e doar despre rescriere (cuvânt plictisitor) și echivalențe. E despre cum vezi aceeași problemă din două perspective diferite, cum un algoritm poate fi scris în două moduri diferite care duc la același rezultat. E o abilitate atât de importantă încât dacă ai stăpâni-o, ai putea rescrie orice buclă în orice altă buclă!

    1. De Ce Să Schimbi Structurile Repetitive? “Aceeași Mașină, Două Butoane Diferite”
    Gândește-te la structurile repetitive ca la același călător care poate lua două rute diferite spre aceeași destinație:

    • Ruta 1 (cât timp): “Merg cât timp drumul nu e blocat, dacă e blocat de la început, mă întorc”
    • Ruta 2 (repetă până când): “Merg o dată sigur, apoi continui până când drumul e blocat”

    Ambele ajung în același loc, dar:

    1. Pornesc diferit
    2. Verifică condiția în momente diferite
    3. Au riscuri diferite

    De ce să înveți să le schimbi?

    • Pentru că uneori cerința specifică un anumit tip de buclă
    • Pentru că altă dată vezi mai clar soluția într-o formă
    • Pentru că vrei să demonstrezi că înțelegi logica din spate
    • Pentru că la examen te pot întreba să transformi una în alta!

    2. Cele Două “Frați” Opuși: WHILE vs REPEAT-UNTIL

    WHILE (cât timp) – “Verifică înainte să intri”

    cât timp (condiție ADEVĂRATĂ) execută
        instrucțiuni
    sfârșit cât timp

    REPEAT-UNTIL (repetă până când) – “Intră sigur o dată, verifică după”

    repetă
        instrucțiuni
    până când (condiție ADEVĂRATĂ)

    OBSERVAȚIE CRUCIALĂ:

    • WHILE: Continuă CÂT TIMP condiția e adevărată
    • REPEAT-UNTIL: Continuă PÂNĂ CÂND condiția devine adevărată
    • SUNT OPUSE LOGIC!
    • while(x < 5) = repetă cât timp x este mai mic decât 5
    • repeat ... until x >= 5 = repetă până când x devine mai mare sau egal cu 5

    3. Transformarea de BAZĂ: Cum Schimbi WHILE în REPEAT-UNTIL

    REGULA de AUR:
    Pentru a transforma un while într-un repeat-until:

    1. Inversează condiția (neg-o!)
    2. Asigură-te că instrucțiunile se execută cel puțin o dată
    3. Pune bucla într-un if dacă nu vrei execuție garantată

    Exemplul 1: Numărătoare descrescătoare

    // WHILE - versiunea originală
    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 10;
    
        cout << "Lansare in: ";
        while (numar > 0) {  // Cât timp numar > 0
            cout << numar << "... ";
            numar--;
        }
        cout << "POC! Lansat!\n";
    
        return 0;
    }
    // REPEAT-UNTIL - versiunea transformată
    #include <iostream>
    using namespace std;
    
    int main() {
        int numar = 10;
    
        cout << "Lansare in: ";
    
        // TRANSFORMARE:
        // while (numar > 0) devine:
        // do { ... } while (!(numar <= 0)) care e echivalent cu
        // do { ... } while (numar > 0) - STAI, NU! 
        // Urmărește cu atenție...
    
        // CORECT: while(numar > 0) → do-while cu condiția opusă
        if (numar > 0) {  // Verifică dacă ar intra în while
            do {
                cout << numar << "... ";
                numar--;
            } while (numar > 0);  // ATENȚIE: condiția rămâne aceeași pentru do-while
            // Dar pentru repeat-until în Pascal ar fi: until numar <= 0
        }
    
        cout << "POC! Lansat!\n";
    
        return 0;
    }

    Să explicăm transformarea pentru PSEUDOCOD (Pascal-like):

    // WHILE original
    numar ← 10
    scrie "Lansare in: "
    cât timp numar > 0 execută
        scrie numar, "... "
        numar ← numar - 1
    sfârșit cât timp
    scrie "POC! Lansat!"
    // REPEAT-UNTIL transformat
    numar ← 10
    scrie "Lansare in: "
    
    // TRUC: Mai întâi verificăm dacă ar intra în while
    dacă numar > 0 atunci
        repetă
            scrie numar, "... "
            numar ← numar - 1
        până când numar <= 0  // CONDIȚIA OPUSĂ!
    sfârșit dacă
    
    scrie "POC! Lansat!"

    Regula de transformare clară:

    CÂT TIMP (condiție) execută
        instrucțiuni
    SFÂRȘIT CÂT TIMP
    
    DEVINE
    
    dacă (condiție) atunci
        repetă
            instrucțiuni
        până când NOT(condiție)
    sfârșit dacă

    4. Transformarea INVERSĂ: REPEAT-UNTIL în WHILE

    REGULA de AUR inversă:
    Pentru a transforma un repeat-until într-un while:

    1. Scrii instrucțiunile o dată înainte de while
    2. Pui aceleași instrucțiuni în while
    3. Condiția rămâne aceeași (pentru do-while în C++)
      sau se inversează (pentru repeat-until în Pascal)

    Exemplul 2: Meniu interactiv

    // REPEAT-UNTIL (do-while) - versiunea originală
    #include <iostream>
    using namespace std;
    
    int main() {
        char raspuns;
    
        do {
            cout << "Vrei sa joci? (d/n): ";
            cin >> raspuns;
    
            if (raspuns == 'd' || raspuns == 'D') {
                cout << "Super! Hai sa jucam...\n";
                // ... cod joc ...
            }
        } while (raspuns == 'd' || raspuns == 'D');  // Cât timp răspuns e 'd'
    
        cout << "Ok, pa pa!\n";
    
        return 0;
    }
    // WHILE - versiunea transformată
    #include <iostream>
    using namespace std;
    
    int main() {
        char raspuns;
    
        // TRANSFORMARE din do-while în while:
        // 1. Execută instrucțiunile o dată înainte
        cout << "Vrei sa joci? (d/n): ";
        cin >> raspuns;
    
        if (raspuns == 'd' || raspuns == 'D') {
            cout << "Super! Hai sa jucam...\n";
            // ... cod joc ...
        }
    
        // 2. Pui while cu aceleași instrucțiuni
        while (raspuns == 'd' || raspuns == 'D') {
            cout << "Vrei sa joci? (d/n): ";
            cin >> raspuns;
    
            if (raspuns == 'd' || raspuns == 'D') {
                cout << "Super! Hai sa jucam...\n";
                // ... cod joc ...
            }
        }
    
        cout << "Ok, pa pa!\n";
    
        return 0;
    }

    DAR! Există o problemă: COD DUPLICAT!
    Am scris aceleași instrucțiuni de 2 ori. Iată soluția elegantă:

    // WHILE - versiunea transformată CORECTĂ
    #include <iostream>
    using namespace std;
    
    int main() {
        char raspuns = 'd';  // FORȚĂM prima intrare în buclă
    
        // Folosim o variabilă care ne forțează să intrăm măcar o dată
        while (raspuns == 'd' || raspuns == 'D') {
            cout << "Vrei sa joci? (d/n): ";
            cin >> raspuns;
    
            if (raspuns == 'd' || raspuns == 'D') {
                cout << "Super! Hai sa jucam...\n";
                // ... cod joc ...
            }
        }
    
        cout << "Ok, pa pa!\n";
    
        return 0;
    }

    Sau pentru PSEUDOCOD (Pascal):

    // REPEAT-UNTIL original
    repetă
        scrie "Vrei sa joci? (d/n): "
        citește raspuns
    
        dacă raspuns = 'd' sau raspuns = 'D' atunci
            scrie "Super! Hai sa jucam..."
        sfârșit dacă
    până când raspuns <> 'd' și raspuns <> 'D'
    
    scrie "Ok, pa pa!"
    // WHILE transformat
    raspuns ← 'd'  // Inițializare forțată
    
    cât timp raspuns = 'd' sau raspuns = 'D' execută
        scrie "Vrei sa joci? (d/n): "
        citește raspuns
    
        dacă raspuns = 'd' sau raspuns = 'D' atunci
            scrie "Super! Hai sa jucam..."
        sfârșit dacă
    sfârșit cât timp
    
    scrie "Ok, pa pa!"

    5. Transformări Complexe: Cu Break și Continue

    Exemplul 3: Căutare cu break

    // WHILE cu break - original
    #include <iostream>
    using namespace std;
    
    int main() {
        int numar;
        bool gasit = false;
    
        cout << "Ghiceste numarul magic (1-100): ";
    
        while (!gasit) {  // Cât timp NU e gasit
            cin >> numar;
    
            if (numar == 42) {
                cout << "BRAVO! Ai ghicit!\n";
                gasit = true;  // Sau break;
            } else if (numar < 42) {
                cout << "Prea mic! Mai incearca: ";
            } else {
                cout << "Prea mare! Mai incearca: ";
            }
        }
    
        return 0;
    }
    // REPEAT-UNTIL transformat cu flag
    #include <iostream>
    using namespace std;
    
    int main() {
        int numar;
        bool gasit = false;
    
        cout << "Ghiceste numarul magic (1-100): ";
    
        if (!gasit) {  // Echivalentul verificării inițiale din while
            do {
                cin >> numar;
    
                if (numar == 42) {
                    cout << "BRAVO! Ai ghicit!\n";
                    gasit = true;
                } else if (numar < 42) {
                    cout << "Prea mic! Mai incearca: ";
                } else {
                    cout << "Prea mare! Mai incearca: ";
                }
            } while (!gasit);  // Continuă până când e găsit
        }
    
        return 0;
    }

    6. Cazuri Speciale: Transformări cu FOR

    FOR poate fi transformat în WHILE și invers!

    // FOR original
    #include <iostream>
    using namespace std;
    
    int main() {
        for (int i = 1; i <= 10; i++) {
            cout << i << " ";
        }
    
        return 0;
    }
    // WHILE transformat
    #include <iostream>
    using namespace std;
    
    int main() {
        int i = 1;  // Inițializare
    
        while (i <= 10) {  // Condiție
            cout << i << " ";
            i++;           // Incrementare
        }
    
        return 0;
    }
    // REPEAT-UNTIL transformat (cu atenție!)
    #include <iostream>
    using namespace std;
    
    int main() {
        int i = 1;
    
        if (i <= 10) {  // Verifică dacă s-ar executa măcar o dată
            do {
                cout << i << " ";
                i++;
            } while (i <= 10);
        }
    
        return 0;
    }

    7. Tabel de Transformare COMPLET

    Structura OriginalăStructura TransformatăObservații
    while(cond) { instr; }if(cond) { do { instr; } while(cond); }Atenție la duplicarea condiției!
    do { instr; } while(cond);instr; while(cond) { instr; }Duplicare de cod! Mai bine: inițializezi variabilele să forțeze prima intrare
    for(init; cond; inc) { instr; }init; while(cond) { instr; inc; }Transformare directă
    repeat instr until cond; (Pascal)instr; while(!cond) { instr; }Condiția se inversează!

    8. EXERCIȚII Practice de Transformare

    Exercițiul 1: Transformă WHILE în REPEAT-UNTIL

    // EXERCIȚIU: Transformă acest while în repeat-until
    #include <iostream>
    using namespace std;
    
    int main() {
        int suma = 0;
        int numar;
    
        cout << "Introdu numere (0 pentru stop): ";
        cin >> numar;
    
        while (numar != 0) {
            suma += numar;
            cin >> numar;
        }
    
        cout << "Suma este: " << suma << endl;
    
        return 0;
    }
    // SOLUȚIE: Transformarea corectă
    #include <iostream>
    using namespace std;
    
    int main() {
        int suma = 0;
        int numar;
    
        cout << "Introdu numere (0 pentru stop): ";
        cin >> numar;
    
        // WHILE devine:
        if (numar != 0) {  // Verifică condiția inițială
            do {
                suma += numar;
                cin >> numar;
            } while (numar != 0);  // Condiția rămâne aceeași
        }
    
        cout << "Suma este: " << suma << endl;
    
        return 0;
    }

    Exercițiul 2: Transformă REPEAT-UNTIL în WHILE

    // EXERCIȚIU în pseudocod (Pascal-style)
    repetă
        scrie "Introdu parola: "
        citește parola
    
        dacă parola <> "secret" atunci
            scrie "Parola gresita!"
        sfârșit dacă
    până când parola = "secret"
    
    scrie "Acces permis!"
    // SOLUȚIE: Transformarea în WHILE
    parola ← ""  // Inițializezi cu o valoare care să forțeze intrarea
    
    cât timp parola <> "secret" execută
        scrie "Introdu parola: "
        citește parola
    
        dacă parola <> "secret" atunci
            scrie "Parola gresita!"
        sfârșit dacă
    sfârșit cât timp
    
    scrie "Acces permis!"

    9. Când Să Folosești Care? “Arta Alegerei”

    FOLOSEȘTE WHILE (cât timp) când:

    1. Poți să NU execuți deloc (condiția falsă de la început)
    2. Citești din fișier până la sfârșit
    3. Aștepți o condiție externă (buton apăsat, mesaj primit)
    4. Numărul de repetări e necunoscut

    Exemplu perfect pentru WHILE:

    // Verifică conexiunea la internet
    while (!esteConectatLaInternet()) {
        cout << "Astept conexiune...\n";
        asteapta(1000);  // Așteaptă 1 secundă
    }
    cout << "Conectat!";

    FOLOSEȘTE REPEAT-UNTIL (do-while) când:

    1. Vrei să execuți cel puțin o dată
    2. Meniu interactiv (“Vrei să continui?”)
    3. Validare input (cere până primești ceva valid)
    4. Simulări/jocuri (“Mai joci o rundă?”)

    Exemplu perfect pentru REPEAT-UNTIL:

    // Meniu interactiv
    do {
        afiseazaMeniu();
        citesteOptiunea();
        executaOptiunea();
    } while (optiunea != 'q');  // Până când utilizatorul apasă 'q' pentru quit

    FOLOSEȘTE FOR când:

    1. Știi exact de câte ori trebuie să repeți
    2. Parcurgi un vector/matrice (îți știi dimensiunea)
    3. Generezi serii de numere
    4. Simulezi ceva cu un număr fix de iterații

    10. PROIECT INTEGRAT: Calculator cu Transformări

    #include <iostream>
    using namespace std;
    
    int main() {
        int optiune;
        double a, b, rezultat;
        char continuare;
    
        cout << "=== CALCULATOR CU TRANSFORMARI ===\n\n";
    
        // Folosim do-while pentru că vrem cel puțin o execuție
        do {
            cout << "\nMeniu operatii:\n";
            cout << "1. Adunare (+)\n";
            cout << "2. Scadere (-)\n";
            cout << "3. Inmultire (*)\n";
            cout << "4. Impartire (/)\n";
            cout << "Alege operatia: ";
            cin >> optiune;
    
            cout << "Introdu primul numar: ";
            cin >> a;
            cout << "Introdu al doilea numar: ";
            cin >> b;
    
            // WHILE pentru validare impartire la 0
            while (optiune == 4 && b == 0) {
                cout << "EROARE: Impartire la 0! Introdu alt numar: ";
                cin >> b;
            }
    
            switch(optiune) {
                case 1: rezultat = a + b; break;
                case 2: rezultat = a - b; break;
                case 3: rezultat = a * b; break;
                case 4: rezultat = a / b; break;
                default: cout << "Optiune invalida!\n"; continue;
            }
    
            cout << "Rezultat: " << rezultat << endl;
    
            cout << "\nMai faci un calcul? (d/n): ";
            cin >> continuare;
    
        } while (continuare == 'd' || continuare == 'D');
    
        cout << "\nLa revedere!\n";
    
        // ACUM transformă acest do-while în while!
        // TEMA: Rescrie același program folosind while în loc de do-while
        // Hint: Va trebui să inițializezi 'continuare' cu 'd' 
        // și să modifici condiția while-ului
    
        return 0;
    }

    SOLUȚIE transformare do-while → while:

    // Versiunea cu WHILE (transformată)
    #include <iostream>
    using namespace std;
    
    int main() {
        int optiune;
        double a, b, rezultat;
        char continuare = 'd';  // Inițializare forțată pentru prima intrare
    
        cout << "=== CALCULATOR CU WHILE ===\n\n";
    
        // Transformarea: do-while → while
        while (continuare == 'd' || continuare == 'D') {
            // ... același cod ca mai sus ...
    
            cout << "\nMai faci un calcul? (d/n): ";
            cin >> continuare;
        }
    
        cout << "\nLa revedere!\n";
    
        return 0;
    }

    În concluzie, să-ți spun ceva fundamental:
    Transformarea structurilor repetitive nu e un truc intelectual gol. E o abilitate practică care îți arată că înțelegi cu adevărat logica din spatele buclelor. Dacă poți transforma un while într-un repeat-until și invers, demonstrezi că înțelegi diferența subtilă dintre “verifică înainte să execuți” și “execută înainte să verifici”.

    Dar transformarea mecanică fără înțelegerea logicii poate fi, paradoxal, o sursă de bug-uri subtile dacă nu realizezi că while(x > 0) și repeat ... until(x <= 0) folosesc condiții opuse.

    Așa că ai grijă când transformi. Cunoștințe-ti logica: ce vrei să facă bucla? Când vrei să se oprească? Execută mereu cel puțin o dată sau poate să nu se execute deloc? Pentru că puterea de a rescrie un algoritm în formă diferită este goală fără înțelegerea de ce și cum funcționează fiecare formă. Și această putere vine cu o responsabilitate: să fii precis și atent la detalii logice.

    Stăpânirea transformărilor între structuri repetitive este o parte integrală a flexibilității în programare. Ai grijă de ea cu aceeași seriozitate.

  • Ce este Pseudocodul? Limbajul Secret Dintre Om și Calculator – Materie BAC

    Bun, hai să vorbim despre cel mai important “tradutor” din programare: PSEUDOCODUL. Nu e doar despre scris (cuvânt generic) și planificare. E despre cum traduci gândirea umană într-o formă pe care o poate înțelege atât omul, cât și mașina (mai târziu). E un proces atât de natural încât dacă ai vedea pe cine care își planifică algoritmul direct în C++, ai crede că e magician. Dar aici intervine și partea strategică: cum să formulezi ideile clar, fără să te blocheze sintaxa unui limbaj anume.

    1. Ce este Pseudocodul? “Limba Română a Programatorului”

    Gândește-te la el ca la un scenariu de film scris pentru actori care nu știu să vorbească (calculatoarele): descrii acțiunile, dialogurile, mișcările, dar într-un limbaj pe care îl înțeleg toți oamenii din echipă.

    Definiția Pseudocodului:
    Pseudocodul este o descriere informală, în limbaj natural, a unui algoritm. Folosește structurile de control ale programării (dacă, atunci, repetă, cât timp), dar fără sintaxa strictă a unui limbaj de programare.

    Analogie cu O Rețetă de Bucătărie Simplificată:

    În limbaj natural (prea vag):
    “Fă niște omletă bună”

    În C++ (prea tehnic):

    #include <iostream>
    using namespace std;
    int main() {
        int oua = 3;
        double sare = 0.005;
        // ... și așa mai departe
    }

    ÎN PSEUDOCOD (perfect):

    1. Ia 3 ouă din frigider
    2. Sparge ouăle într-un castron
    3. Adaugă o vârf de cuțit de sare
    4. Bată amestecul timp de 30 de secunde
    5. Încălzește tigaia la foc mediu
    6. Toarnă amestecul în tigaie
    7. Gătește 2 minute
    8. Întoarce omleta
    9. Gătește încă 1 minut
    10. Serveste pe farfurie

    DE CE avem nevoie de pseudocod?
    Pentru că programatorii sunt mai întâi OAMENI, apoi traducători pentru calculatoare:

    1. Omul gândește în română/engleză – nu în if (x > 0) { cout << "Pozitiv"; }
    2. Pseudocodul e puntea dintre gândirea umană și programare
    3. Ajută la planificare înainte să te încurci în detalii tehnice

    2. Caracteristicile Pseudocodului Bun – “Cum Să Fii Înțeles de Toată Lumea”

    1. SIMPLICITATE – Fără termeni tehnici inutili

    // PROST (prea tehnic):
    INIT x = 5
    WHILE x > 0 DO
        DECREMENT x
    END WHILE
    
    // BUN (clar pentru toată lumea):
    x ← 5
    cât timp x > 0 execută
        x ← x - 1
    sfârșit cât timp

    2. CLARITATE – Fiecare pas e neambiguu

    // PROST (ambiguu):
    Înmulțește numerele și afișează rezultatul
    
    // BUN (clar):
    produs ← număr1 × număr2
    scrie produs

    3. STRUCTURARE – Folosește indentarea

    // PROST (toate pe același rând):
    dacă vârsta >= 18 atunci scrie "Major" altfel scrie "Minor"
    
    // BUN (structurat):
    dacă vârsta >= 18 atunci
        scrie "Major"
    altfel
        scrie "Minor"
    sfârșit dacă

    3. Elementele de Bază ale Pseudocodului – “Vocabularul” Nostru

    1. ATRIBUIREA (Punem valori în variabile)

    // Simbolul ← (săgeată) sau =
    vârsta ← 18
    nume ← "Ana"
    suma ← 0

    2. CITIREA și SCRIEREA (Comunicarea cu utilizatorul)

    // Citire de la tastatură
    citește nume
    citește vârsta
    citește nota1, nota2, nota3
    
    // Scriere pe ecran
    scrie "Bună ziua!"
    scrie "Numele tău este: ", nume
    scrie "Suma este: ", suma

    3. DECIZIA (Structura dacă – atunci)

    // Forma simplă
    dacă condiție atunci
        acțiuni
    sfârșit dacă
    
    // Exemplu concret
    dacă temperatura > 30 atunci
        scrie "E foarte cald!"
    sfârșit dacă
    
    // Cu alternativă
    dacă nota >= 5 atunci
        scrie "Promovat"
    altfel
        scrie "Respins"
    sfârșit dacă
    
    // Cu mai multe alternative
    dacă nota >= 9 atunci
        scrie "Excelent"
    altfel dacă nota >= 7 atunci
        scrie "Bine"
    altfel dacă nota >= 5 atunci
        scrie "Suficient"
    altfel
        scrie "Insuficient"
    sfârșit dacă

    4. REPETIȚIA (Buclele)

    // BUCLE cu NUMĂR CUNOSCUT de repetări (pentru)
    pentru i de la 1 la 10 execută
        scrie i
    sfârșit pentru
    
    // BUCLE cu TEST INIȚIAL (cât timp)
    i ← 1
    cât timp i <= 10 execută
        scrie i
        i ← i + 1
    sfârșit cât timp
    
    // BUCLE cu TEST FINAL (repetă până)
    i ← 1
    repetă
        scrie i
        i ← i + 1
    până când i > 10

    4. Exemple Complete de Pseudocod vs C++

    EXEMPLU 1: Calculul sumei primelor N numere

    // PSEUDOCOD ROMÂNESC
    început
        // Declarare variabile
        n, i, suma: numere întregi
    
        // Citire date
        scrie "Introdu N: "
        citește n
    
        // Inițializare
        suma ← 0
    
        // Calcul sumă
        pentru i de la 1 la n execută
            suma ← suma + i
        sfârșit pentru
    
        // Afișare rezultat
        scrie "Suma primelor ", n, " numere este: ", suma
    sfârșit
    // C++ ECHIVALENT
    #include <iostream>
    using namespace std;
    
    int main() {
        int n, i, suma;
    
        cout << "Introdu N: ";
        cin >> n;
    
        suma = 0;
    
        for(i = 1; i <= n; i++) {
            suma = suma + i;
        }
    
        cout << "Suma primelor " << n << " numere este: " << suma;
    
        return 0;
    }

    EXEMPLU 2: Verificarea numărului prim

    // PSEUDOCOD
    început
        n, i: numere întregi
        estePrim: adevărat/fals
    
        scrie "Introdu un număr: "
        citește n
    
        // Presupunem că numărul este prim (decât dovedim contrariul)
        estePrim ← Adevărat
    
        // Verifică divizorii de la 2 până la n-1
        pentru i de la 2 la n-1 execută
            dacă n se împarte exact la i atunci
                estePrim ← Fals
                oprește bucla  // break
            sfârșit dacă
        sfârșit pentru
    
        // Afișează rezultatul
        dacă estePrim = Adevărat atunci
            scrie n, " este număr prim"
        altfel
            scrie n, " NU este număr prim"
        sfârșit dacă
    sfârșit
    // C++ ECHIVALENT
    #include <iostream>
    using namespace std;
    
    int main() {
        int n, i;
        bool estePrim;
    
        cout << "Introdu un număr: ";
        cin >> n;
    
        estePrim = true;
    
        for(i = 2; i < n; i++) {
            if(n % i == 0) {
                estePrim = false;
                break;
            }
        }
    
        if(estePrim == true) {
            cout << n << " este număr prim";
        } else {
            cout << n << " NU este număr prim";
        }
    
        return 0;
    }

    5. Cum Scrii Pseudocod Eficient – “Arta de a Fi Clar”

    TEHNICA 1: Folosește comentarii GENEROASE

    // PROST (fără comentarii):
    s ← 0
    pentru i de la 1 la n execută
        s ← s + i
    scrie s
    
    // BUN (cu comentarii):
    // Calculăm suma numerelor de la 1 la N
    suma ← 0
    
    pentru contor de la 1 la n execută
        // Adună numărul curent la sumă
        suma ← suma + contor
    sfârșit pentru
    
    // Afișează rezultatul
    scrie "Suma este: ", suma

    TEHNICA 2: Denumește variabilele SUGESTIV

    // PROST (variabile obscure):
    a ← 20
    b ← a * 1.19
    
    // BUN (variabile clare):
    pretFaraTVA ← 20
    pretCuTVA ← pretFaraTVA * 1.19

    TEHNICA 3: Grupează pașii logic

    // PROST (amestecat):
    scrie "Introdu date:"
    citește n
    s ← 0
    pentru i... (calcule)
    scrie s
    
    // BUN (grupat):
    // 1. CITIRE DATE
    scrie "Introdu N: "
    citește n
    
    // 2. PROCESARE
    suma ← 0
    pentru i de la 1 la n execută
        suma ← suma + i
    sfârșit pentru
    
    // 3. AFIȘARE REZULTATE
    scrie "Suma este: ", suma

    6. Pseudocod pentru Probleme Complexe

    EXEMPLU: Sistem simplu de gestiune studenți

    început program GestiuneStudenti
    
        // Definire tip de date
        tip Student
            nume: text
            prenume: text
            varsta: număr întreg
            medie: număr real
        sfârșit tip
    
        // Variabile
        listaStudenti: vector de Student
        numarStudenti, i: număr întreg
        optiune: caracter
    
        // Inițializare
        numarStudenti ← 0
    
        repetă
            // Afișare meniu
            scrie "=== MENIU ==="
            scrie "1. Adaugă student"
            scrie "2. Afișează toți studenții"
            scrie "3. Calculează media grupei"
            scrie "4. Găsește student cu cea mai mare medie"
            scrie "0. Ieșire"
            scrie "Alege opțiunea: "
            citește optiune
    
            în funcție de optiune execută
                caz '1':
                    dacă numarStudenti < 100 atunci
                        scrie "Nume: "
                        citește listaStudenti[numarStudenti].nume
                        scrie "Prenume: "
                        citește listaStudenti[numarStudenti].prenume
                        scrie "Vârsta: "
                        citește listaStudenti[numarStudenti].varsta
                        scrie "Medie: "
                        citește listaStudenti[numarStudenti].medie
    
                        numarStudenti ← numarStudenti + 1
                        scrie "Student adăugat cu succes!"
                    altfel
                        scrie "Lista este plină!"
                    sfârșit dacă
    
                caz '2':
                    dacă numarStudenti = 0 atunci
                        scrie "Nu există studenți în listă!"
                    altfel
                        scrie "=== LISTA STUDENȚILOR ==="
                        pentru i de la 0 la numarStudenti-1 execută
                            scrie i+1, ". ", listaStudenti[i].nume, " ", 
                                  listaStudenti[i].prenume, " - Vârsta: ", 
                                  listaStudenti[i].varsta, " - Media: ", 
                                  listaStudenti[i].medie
                        sfârșit pentru
                    sfârșit dacă
    
                caz '3':
                    dacă numarStudenti > 0 atunci
                        sumaMedii ← 0
                        pentru i de la 0 la numarStudenti-1 execută
                            sumaMedii ← sumaMedii + listaStudenti[i].medie
                        sfârșit pentru
    
                        mediaGrupei ← sumaMedii / numarStudenti
                        scrie "Media grupei este: ", mediaGrupei
                    altfel
                        scrie "Nu există studenți în listă!"
                    sfârșit dacă
    
                caz '4':
                    dacă numarStudenti > 0 atunci
                        indexMax ← 0
                        pentru i de la 1 la numarStudenti-1 execută
                            dacă listaStudenti[i].medie > listaStudenti[indexMax].medie atunci
                                indexMax ← i
                            sfârșit dacă
                        sfârșit pentru
    
                        scrie "Studentul cu cea mai mare medie este: "
                        scrie listaStudenti[indexMax].nume, " ", 
                              listaStudenti[indexMax].prenume, " cu media ", 
                              listaStudenti[indexMax].medie
                    altfel
                        scrie "Nu există studenți în listă!"
                    sfârșit dacă
    
                caz '0':
                    scrie "La revedere!"
    
                altfel:
                    scrie "Opțiune invalidă!"
    
            sfârșit în funcție de
    
        până când optiune = '0'
    
    sfârșit program

    7. Cum Transformi Pseudocodul în C++ (și invers)

    METODA PAS-CU-PAS:

    // PASUL 1: Scriu pseudocodul (gândirea)
    început
        a, b, suma: numere întregi
    
        scrie "Introdu primul număr: "
        citește a
    
        scrie "Introdu al doilea număr: "
        citește b
    
        suma ← a + b
    
        scrie "Suma este: ", suma
    sfârșit
    // PASUL 2: Traduc în schelet C++
    #include <iostream>
    using namespace std;
    
    int main() {
        // a, b, suma: numere întregi
        int a, b, suma;
    
        // scrie "Introdu primul număr: "
        cout << "Introdu primul număr: ";
    
        // citește a
        cin >> a;
    
        // scrie "Introdu al doilea număr: "
        cout << "Introdu al doilea număr: ";
    
        // citește b
        cin >> b;
    
        // suma ← a + b
        suma = a + b;
    
        // scrie "Suma este: ", suma
        cout << "Suma este: " << suma;
    
        return 0;
    }

    8. Exercițiu Practic: Transformă din C++ în Pseudocod

    // C++ DAT
    #include <iostream>
    using namespace std;
    
    int main() {
        int n, factorial = 1;
    
        cout << "Introdu un numar: ";
        cin >> n;
    
        if(n < 0) {
            cout << "Factorialul nu exista pentru numere negative!";
        } else {
            for(int i = 1; i <= n; i++) {
                factorial = factorial * i;
            }
            cout << "Factorialul lui " << n << " este " << factorial;
        }
    
        return 0;
    }
    // PSEUDOCOD CORESPUNZĂTOR (SOLUȚIE)
    început
        n, factorial, i: numere întregi
    
        factorial ← 1
    
        scrie "Introdu un număr: "
        citește n
    
        dacă n < 0 atunci
            scrie "Factorialul nu există pentru numere negative!"
        altfel
            pentru i de la 1 la n execută
                factorial ← factorial × i
            sfârșit pentru
    
            scrie "Factorialul lui ", n, " este ", factorial
        sfârșit dacă
    sfârșit

    9. Beneficiile Pseudocodului – “De Ce Să Ne Mai Chinuim?”

    1. PLANIFICARE mai bună

    Fără pseudocod: Începi să scrii cod → te blochezi la jumătate → renunți
    Cu pseudocod: Planifici tot algoritmul → știi exact ce scrii → codul curge

    2. COMUNICARE cu non-programatori

    Clientul: “Vreau să afișezi produsele în ordinea celor mai vândute”
    Tu (cu pseudocod): “Ah, deci trebuie să sortez descrescător după cantitate_vândută”
    Clientul: “Da, exact!”

    3. REUTILIZARE între limbaje

    Același pseudocod poate deveni:

    • C++ pentru aplicație desktop
    • Python pentru script
    • JavaScript pentru website
      Toate din ACEAȘI sursă!

    4. DETECTAREA erorilor logice DEVREME

    În pseudocod vezi imediat dacă:

    • Ai uitat o condiție
    • Bucla nu se termină niciodată
    • Calculul e greșit logic

    10. Cum Exersezi Pseudocodul – “Antrenamentul Zilnic”

    // EXERCIȚIU 1: Scrie pseudocod pentru calculul mediei a 3 note
    început
        // TEMA: Completează tu!
    sfârșit
    
    // EXERCIȚIU 2: Scrie pseudocod care verifică dacă un an este bisect
    început
        // TEMA: Completează tu!
    sfârșit
    
    // EXERCIȚIU 3: Scrie pseudocod pentru un calculator simplu (+,-,*,/)
    început
        // TEMA: Completează tu!
    sfârșit

    În concluzie, să-ți spun ceva fundamental:

    Pseudocodul nu e un pas opțional sau o pierdere de timp. E cel mai important instrument al programatorului pentru a-și organiza gândirea. E diferența dintre a construi o casă cu un plan și a construi la întâmplare, sperând că va ieși bine.

    Dar folosirea excesivă a pseudocodului pentru probleme banale poate fi, paradoxal, o pierdere de timp. Nu ai nevoie de pseudocod pentru cout << "Hello World!";.

    Așa că ai grijă când folosești pseudocod. Cunoștințe-ti nevoile: problemă complexă care necesită planificare? Atunci pseudocodul e PRIETENUL tău. Problemă simplă pe care o știi să o scrii direct? Atunci scrie codul direct. Pentru că puterea de a planifica este goală fără înțelegerea când are sens să o folosești. Și această putere vine cu o responsabilitate: să fii pragmatic, nu dogmatic.

    Folosirea inteligentă a pseudocodului este o parte integrală a gândirii algoritmice structurate. Ai grijă de ea cu aceeași seriozitate.