Cum Gândește Calculatorul? Partea a 10-a: Programe Complete în C/C++

Salut! Acum ajungem la nivelul cel mai avansat: programe complete pentru Bacalaureat. Aceste probleme valorează 10 puncte fiecare și testează toate competențele tale. Hai să le abordăm sistematic!

🎯 Strategia pentru Probleme de Programare Completă

  1. Citește cerința 3 ori – Înțelege exact ce se cere
  2. Analizează exemplul – Exemplele sunt cheia pentru înțelegere
  3. Împarte în subprobleme – Rezolvă bucată cu bucată
  4. Scrie pseudocod – Pe hârtie, în română
  5. Implementează – Tradu în C/C++
  6. Testează – Cu datele din exemplu

📚 Rezolvări Complete pentru Fiecare Problemă

Problema 1: Eliminarea Diagonalei Secundare și Shiftare

Cerința: Elimină elementele de pe diagonala secundară și mută celelalte spre stânga.

Exemplu pentru n=4:

Initial:     Dupa eliminare:
1  2  3  4    X  X  X  X
5  6  7  8    5  6  7  X
9  10 11 12   9  10 X  12
13 14 15 16   13 X  15 16

Dupa shiftare:
1  2  3  4    X  X  X  X
5  6  7  X    5  6  7  X  
9  10 X  12   9  10 12 X
13 X  15 16   13 15 16 X

Soluție:

#include <iostream>
using namespace std;

int main() {
    int n, a[101][101];

    // Citire
    cin >> n;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            cin >> a[i][j];

    // Pas 1: Marcam elementele de pe diagonala secundara cu -1
    for(int i = 0; i < n; i++) {
        a[i][n-1-i] = -1;  // -1 = pozitie libera
    }

    // Pas 2: Shiftare spre stanga pentru fiecare linie
    for(int i = 0; i < n; i++) {
        // Parcurgem de la stanga la dreapta si mutam elemente peste -1
        for(int j = 0; j < n-1; j++) {
            if(a[i][j] == -1) {
                // Mutam urmatorul element in locul acesta
                a[i][j] = a[i][j+1];
                a[i][j+1] = -1;
            }
        }
    }

    // Pas 3: Afisare (inlocuim -1 cu 0 sau lasam spatiu)
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(a[i][j] == -1) cout << " ";
            else cout << a[i][j];
            if(j < n-1) cout << " ";
        }
        cout << endl;
    }

    return 0;
}

Varianta mai simplă cu tabloul auxiliar:

#include <iostream>
using namespace std;

int main() {
    int n, a[101][101], b[101][101] = {0};

    cin >> n;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            cin >> a[i][j];

    // Construim noul tablou
    for(int i = 0; i < n; i++) {
        int col = 0;
        for(int j = 0; j < n; j++) {
            // Daca NU e pe diagonala secundara, il punem
            if(j != n-1-i) {
                b[i][col] = a[i][j];
                col++;
            }
        }
        // Restul pozitiilor raman 0
    }

    // Afisare
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            cout << b[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

Problema 2: Înlocuirea Coloanei cu Numărul Minim

Cerința: Găsește coloana cu elementul minim și înlocuiește toate elementele ei cu elementul din dreapta-jos.

Exemplu:

Initial:
17 10 11
12 16 21
5  2  8
19 4  9

Minim = 2 (pe linia 2, coloana 1)
Elementul dreapta-jos = 9

Dupa inlocuire:
17 10 11
12 16 21
9  9  9  <- toata coloana 1 devine 9
19 4  9

Soluție:

#include <iostream>
using namespace std;

int main() {
    int m, n, a[101][101];

    cin >> m >> n;
    for(int i = 0; i < m; i++)
        for(int j = 0; j < n; j++)
            cin >> a[i][j];

    // 1. Gasim minimul si coloana lui
    int minim = a[0][0];
    int coloanaMinim = 0;

    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            if(a[i][j] < minim) {
                minim = a[i][j];
                coloanaMinim = j;
            }
        }
    }

    // 2. Elementul din dreapta-jos
    int dreaptaJos = a[m-1][n-1];

    // 3. Inlocuim toata coloana
    for(int i = 0; i < m; i++) {
        a[i][coloanaMinim] = dreaptaJos;
    }

    // 4. Afisare
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

Problema 3: Transformarea Textului cu Cratime

Cerința: Transformă spații multiple între cuvinte în ” – “.

Exemplu: "anul acesta devin student""anul - acesta - devin - student"

Soluție:

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char text[101], rezultat[201] = "";

    cin.getline(text, 101);

    int i = 0, j = 0;
    int inCuvant = 0;  // 0 = in spatiu, 1 = in cuvant

    while(text[i] != '\0') {
        if(text[i] != ' ') {
            // Suntem intr-un cuvant
            if(inCuvant == 0 && j > 0) {
                // S-a terminat spatiul dintre cuvinte
                rezultat[j++] = ' ';
                rezultat[j++] = '-';
                rezultat[j++] = ' ';
            }
            rezultat[j++] = text[i];
            inCuvant = 1;
        } else {
            // Suntem in spatiu
            inCuvant = 0;
        }
        i++;
    }
    rezultat[j] = '\0';

    cout << rezultat;

    return 0;
}

Varianta cu strtok (mai simplă):

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char text[101], cuvant[101];
    char *p;
    char rezultat[201] = "";
    int primulCuvant = 1;

    cin.getline(text, 101);

    p = strtok(text, " ");
    while(p != NULL) {
        if(!primulCuvant) {
            strcat(rezultat, " - ");
        }
        strcat(rezultat, p);
        primulCuvant = 0;
        p = strtok(NULL, " ");
    }

    cout << rezultat;

    return 0;
}

Problema 4: Grădina cu Flori și Gazon

Cerința: Parcelele cu flori trebuie să fie cu cel puțin 1 decimetru mai înalte decât gazonul de pe rândul anterior. Gazonul prea înalt se taie.

Analiză exemplu:

Initial (m=4, n=6):
Linia 1 (gazon): 6 7 8 8 7 6
Linia 2 (flori): 2 3 5 7 2 5  
Linia 3 (gazon): 7 9 9 6 5 9
Linia 4 (flori): 4 8 2 9 3 8

Regula: Florile de pe linia i trebuie sa fie > gazonul de pe linia i-1 cu cel putin 1
Dar florile nu se modifica, doar gazonul se taie!

Soluție:

#include <iostream>
using namespace std;

int main() {
    int m, n, a[101][101];

    cin >> m >> n;
    for(int i = 0; i < m; i++)
        for(int j = 0; j < n; j++)
            cin >> a[i][j];

    // Parcurgem liniile cu gazon (liniile impare: 0, 2, 4... index 0-based)
    for(int i = 0; i < m; i += 2) {  // i = linia cu gazon
        // Daca exista o linie cu flori dupa (i+1 < m)
        if(i + 1 < m) {
            for(int j = 0; j < n; j++) {
                // Daca gazonul este prea inalt fata de florile de sub el
                // Florile trebuie sa fie > gazon cu cel putin 1
                // Deci gazonul trebuie sa fie <= flori - 1
                if(a[i][j] >= a[i+1][j]) {
                    a[i][j] = a[i+1][j] - 1;
                    if(a[i][j] < 2) a[i][j] = 2;  // limita inferioara
                }
            }
        }
    }

    // Parcurgem liniile cu gazon (cele pare: 1, 3, 5... index 0-based)
    for(int i = 1; i < m; i += 2) {  // i = linia cu gazon
        // Daca exista o linie cu flori inainte (i-1 >= 0)
        for(int j = 0; j < n; j++) {
            // Gazonul de pe linia i trebuie verificat cu florile de pe linia i-1
            if(a[i][j] >= a[i-1][j]) {
                a[i][j] = a[i-1][j] - 1;
                if(a[i][j] < 2) a[i][j] = 2;
            }
        }
    }

    // Afisare
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

Problema 5: Pătrat de Valoare Maximă (2×2)

Cerința: Găsește submatricea 2×2 cu suma maximă.

Soluție:

#include <iostream>
using namespace std;

int main() {
    int m, n, a[21][21];

    cin >> m >> n;
    for(int i = 0; i < m; i++)
        for(int j = 0; j < n; j++)
            cin >> a[i][j];

    int maxSum = -1;

    // Parcurgem toate submatricele 2x2
    for(int i = 0; i < m-1; i++) {
        for(int j = 0; j < n-1; j++) {
            int suma = a[i][j] + a[i][j+1] + a[i+1][j] + a[i+1][j+1];
            if(suma > maxSum) {
                maxSum = suma;
            }
        }
    }

    cout << maxSum;

    return 0;
}

Problema 6: Vocală Prietenă pentru Consoane

Cerința: Fiecare consoană se înlocuiește cu vocala care o precede fără alte vocale între ele.

Analiză:

  • Alfabet: a b c d e f g h i j k l m n o p q r s t u v w x y z
  • Vocale: a, e, i, o, u
  • Pentru ‘m’: vocalele care îl preced: i (are ‘j’, ‘k’, ‘l’ între), o (nu, are doar consoane)
  • Regula: Ultima vocală înainte de consoană, fără alte vocale între

Soluție simplificată: Pentru fiecare consoană, o înlocuim cu vocala anterioară:

  • b → a, c → a, d → a, f → e, g → e, h → e, j → i, k → i, l → i, m → i, n → i, p → o, q → o, r → o, s → o, t → o, v → u, w → u, x → u, y → u, z → u

Soluție:

#include <iostream>
#include <cstring>
using namespace std;

int esteVocala(char c) {
    return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
}

char vocalaPrietenie(char consoana) {
    // Pentru fiecare consoana, returnam vocala corespunzatoare
    if(consoana >= 'b' && consoana <= 'd') return 'a';
    if(consoana >= 'f' && consoana <= 'h') return 'e';
    if(consoana >= 'j' && consoana <= 'n') return 'i';
    if(consoana >= 'p' && consoana <= 't') return 'o';
    if(consoana >= 'v' && consoana <= 'z') return 'u';
    return consoana;  // daca nu e consoana
}

int main() {
    char parola[51], codificata[51];

    cin >> parola;

    for(int i = 0; parola[i] != '\0'; i++) {
        if(esteVocala(parola[i])) {
            codificata[i] = parola[i];  // vocalele raman asa
        } else {
            codificata[i] = vocalaPrietenie(parola[i]);
        }
    }
    codificata[strlen(parola)] = '\0';

    cout << codificata;

    return 0;
}

Problema 7: Cuvinte Asemenea

Cerința: Găsește toate cuvintele cu același număr de vocale ca ultimul cuvânt.

Soluție:

#include <iostream>
#include <cstring>
using namespace std;

int numarVocale(char cuvant[]) {
    int count = 0;
    for(int i = 0; cuvant[i] != '\0'; i++) {
        char c = cuvant[i];
        if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')
            count++;
    }
    return count;
}

int main() {
    int n;
    char cuvinte[11][21];  // maxim 10 cuvinte a cate 20 caractere

    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> cuvinte[i];
    }

    int vocaleUltim = numarVocale(cuvinte[n-1]);
    int exista = 0;

    // Parcurgem toate cuvintele in afara de ultimul
    for(int i = 0; i < n-1; i++) {
        if(strcmp(cuvinte[i], cuvinte[n-1]) != 0) {  // distincte
            if(numarVocale(cuvinte[i]) == vocaleUltim) {
                if(exista) cout << " ";
                cout << cuvinte[i];
                exista = 1;
            }
        }
    }

    if(!exista) {
        cout << "nu exista";
    }

    return 0;
}

🎯 Sfaturi pentru Probleme Complexe

  1. Citește cu atenție – Subliniază condițiile importante
  2. Folosește exemplele – Sunt cele mai bune ghiduri
  3. Împarte problema – Rezolvă bucată cu bucată
  4. Testează incremental – După fiecare pas, testează
  5. Gestionează memoria – Folosește dimensiuni suficiente
  6. Verifică cazurile limită – n=1, m=1, sir vid, etc.

💪 Exercițiu de Practică

Încearcă să rezolvi singur următoarea problemă:

Cerință: Scrie un program care citește n numere și afișează cele care au suma cifrelor egală cu produsul cifrelor.

Soluție:

#include <iostream>
using namespace std;

int main() {
    int n, numar;
    cin >> n;

    for(int i = 0; i < n; i++) {
        cin >> numar;
        int suma = 0, produs = 1, temp = numar;

        while(temp > 0) {
            int cifra = temp % 10;
            suma += cifra;
            produs *= cifra;
            temp /= 10;
        }

        if(suma == produs) {
            cout << numar << " ";
        }
    }

    return 0;
}

✨ Motivare Finală

Uite ce uimitor! Acum poți să rezolvi aproape orice problemă de la Bacalaureat. Ai parcurs o cale lungă: de la bazele gândirii algoritmice până la programe complexe.

Cel mai important lucru pe care l-ai învățat: Orice problemă complexă este doar o colecție de probleme simple puse împreună.

La examen:

  1. Răspunde la ce știi – Nu lăsa nimic necompletat
  2. Gestionează-ți timpul – Alocă timp proporțional cu punctajul
  3. Ai încredere în tine – Ai practicat suficient!

Succes la Bacalaureat! Tu poți să iei nota maximă! 🚀🎯

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *