Al doilea bacalaureat în informatică BACALAUREAT 2000Primul examen de Bacalaureat care prevede pentru absolvenții claselor de informatică și o probă scrisă la disciplina de specialitate pune multe întrebări în fața elevilor și profesorilor. Ce fel de subiecte se pot formula pentru acest examen? Cum poate arăta o lucrare scrisă la informatică? GInfo este iar alături de voi! Vă prezentăm un posibil subiect de Bac și rezolvarea corespunzătoare.
Subiectul 1.Scrieți pseudocodul algormitmului care simulează împărțirea a două numere naturale astfel încât câtul și restul să fie numere întregi. Soluție Dacă există posibilitatea ca numerele să fie egale cu 0, pseudocodul trebuie să conțină două structuri alternative care să afișeze câtul 0 și restul 0 dacă m=0, respectiv mesajul Nu putem imparti cu 0, dacă n=0. Pentru numere strict pozitive, împărțirea celor două numere se poate simula repetând operația de scădere în felul următor:
citește m,n (m,n>0) dacă m = 0 atunci scrie 0, 0 altfel dacă n = 0 atunci scrie Nu putem imparti cu 0 altfel d Ź 0 cât timp m č n execută m Ź m - n d Ź d + 1 sfârșit cât timp scrie d, m
sfârșit dacă sfârșit dacă
Subiectul 2.Secvența următoare reprezintă pseudocodul problemei determinării minimului dintr-un șir de numere întregi. Găsiți greșeala și corectați algoritmul!
citește n pentru i=1,n execută citește a[i] pentru i=1,n execută dacă a[i] < min atunci min Ź a[i]
sfârșit dacă sfârșit pentru Soluție Greșeala care trebuie observată este lipsa instrucțiunii de inițializare a variabilei min. Corectarea este simplă: fie se inițializează min cu a[1], fie cu o valoare suficient de mare, față de care în mod sigur vom avea elemente având valori mai mici în șir, astfel oferind posibilitatea înlocuirii sale cu o valoare din șir. Subiectul 3.Prezentați comparativ structura repetitivă cu test inițial și cea cu test final. Transcrieți structura repetitivă cu test final în forma unei structuri repetitive cu test inițial. Soluție
Structură repetitivă cu test inițial
cât timp condiție execută corp sfârșit cât timp
Structură repetitivă cu test final
execută corp până când condiție Transcrierea structurii repetitive cu test final în structură repetitivă cu test inițial corp cât timp not condiție execută corp
sfârșit cât timp
Subiectul 4.Explicați rolul stivei în contextul executării subprogramelor. Soluție Dacă într-un program există subprograme, în momentul apelului acestora mediul efectuează următoarele operații, alocând spațiu pe stiva de execuție pentru diferite informații din care se compune contextul apelului:
1. Scrieți un subprogram care returnează o valoare logică, reprezentând valoarea de adevăr a proprietății: tabloul bidimensional pătratic, transmis ca parametru are pe cele două diagonale (principală și secundară) elemente distincte. Soluție Știind că elementele de pe diagonala principală au expresiile de indice egali, de exemplu tab[i,i] iar cele pe diagonala secundară au forma tab[i,dim-i+1] (dacă indiicii pornesc de la 1 - limbajul Pascal), respectiv tab[i,dim-i-1] (dacă indiicii pornesc de la 0 - limbajul C) funcția se implementează în felul următor.
Varianta Pascal: Function distincte(tab:matrice; dim:Byte):Boolean; var i,j:Byte; dist:Boolean; begin dist:=true; i:=1; while dist and (i<dim) do begin j:=i+1; while dist and (j<=dim) do begin { distincte pe diag. princ.? } dist:=dist and (tab[i,i]<>tab[j,j]); { distincte pe diag. sec.? } dist:=dist and (tab[i,dim-i+1]<>tab[j,dim-j+1]); { distincte pe diag. princ. si sec.? } dist:=dist and (tab[i,i]<>tab[j,dim-j+1]); Inc(j) end; Inc(i) end; distincte:=dist end;
Varianta C: int distincte(int tab[][],int dim){ int dist=1; for (int i=0;i<dim-1 && dist;i++){ for (int j=i;j<dim && dist;j++){ // distincte pe diag. princ.? dist&=(tab[i,i]!=tab[j,j]); // distincte pe diag. sec.? dist&=(tab[i,dim-i-1]!=tab[j,dim-j-1]); // distincte pe diag. princ. si sec.? dist&=(tab[i,i]!=tab[j,dim-j-1]); } } return dist; } Deoarece nu am dorit să scriem o funcție recursivă, am folosit o variabilă auxiliară dist, pentru a putea folosi valoarea curentă a acesteia (având semnificația "distincte"). Datorită modului în care această variabilă conține în valoarea ei informația despre proprietatea căutată, putem părăsi ciclurile imediat ce s-au găsit două elemente egale.
2. Scrieți un subprogram recursiv pentru calcularea sumei primelor n numere naturale. Soluție Din moment ce subprogramul trebuie să returneze o singură valoare (suma), vom scrie o funcție. Formula pe care o vom implementa este următoarea: Suma(1)=1, Suma(n)=n+Suma(n-1)
Varianta Pascal: Function suma(n:Byte):Longint; begin if n=1 then suma:=1 else suma:=n+suma(n-1) end;
Varianta C: long suma(int n){ if (n=1) return 1; else return n+suma(n-1); }
La o benzinărie sosesc n mașini. Proprietarul dorește să minimizeze timpul total de așteptare a celor care doresc să cumpere benzină. Scrieți un program comentat, care stabilește ordinea în care se vor servi mașinile știind că timpul de servire a fiecărei mașini este direct proporțional cu cantitatea de benzină cumpărată. Afișați ordinea servirii și timpul total de așteptare. Exemplu Intrare Ieșire n=5 Ordinea: m1=2 m2 m2=1 m1 m3=4 m4 m4=3 m3 m5=5 m5 Timpul total minim de asteptare: 20 Soluție Problema se va rezolva cu metoda greedy, deoarece timpul total de așteptare se minimizează dacă mașinile se vor alimenta în ordinea crescătoare a cantității de benzină cumpărată. Pentru ordonare s-a folosit o metodă conform căreia se stabilește maximul șirului și se așează pe ultima poziție, după care dimensiunea șirului se micșorează (temporar), pentru a putea alege următorul cel mai mare element, așezându-l și pe acesta pe poziția sa în șirul ordonat, și așa mai departe. Pentru a putea afișa ordinea servirii mașinilor folosind numărul lor de ordine în șirul inițial (neordonat), păstrăm numărul de ordine inițial într-un câmp nr a articolelor de tip masina. Implementarea Pascal este următoarea: Listing BENZINARIE.PAS Program benzinarie; const MaxNr=50; {numar max. de masini} type masina=record cant_benz:Integer; {cantitatea de benzina} nr:Byte end; var n,i,j:Byte; {nr = numar de masini} m:array[1..MaxNr] of masina; timp:array[1..MaxNr] of Integer; {timpul de asteptare al masinilor} timp_total:Longint; {timpul total de asteptare}
procedure ordonare(dim:Byte); var max,aux:masina; i,poz:Byte; begin while dim>0 do begin max:=m[1]; poz:=1; { pozitia maximului } for i:=1 to dim do if m[i].cant_benz>max.cant_benz then begin max:=m[i]; poz:=i end; aux:=m[poz]; m[poz]:=m[dim]; m[dim]:=aux; Dec(dim) {vom cauta intr-un sir mai scurt} end end;
Begin Write('n='); Readln(n); Write('Cantitatile de benzina care'); Writeln(' se cumpara:'); for i:=1 to n do begin Read(m[i].cant_benz); m[i].nr:=i end; ordonare(n); Writeln('Ordinea:'); for i:=1 to n do Writeln('m',m[i].nr); timp[1]:=0; timp_total:=0; for i:=2 to n do begin timp[i]:=timp[i-1]+m[i-1].cant_benz; Inc(timp_total,timp[i]) end; Write('Timpul total minim de '); Writeln('asteptare: ',timp[n]) End. Versiunea C este prezentată în continuare: Listing BENZINARIE.CPP include <stdio.h> #define MaxNr 50 //numarul maxim de masini
struct masina{ int cant_benz; //cantitatea de benzina int nr; } m[MaxNr]; int n,timp[MaxNr]; int timp_total; //timpul total de asteptare
void ordonare(int dim){ masina max,aux; int poz; //pozitia maximului while (dim){ max=m[poz=0]; for (int i=1;i<dim;i++) if (m[i].cant_benz>max.cant_benz) max=m[i], poz=i; aux=m[poz]; m[poz]=m[dim-1]; m[dim---1]=aux; } }
void main(void){ printf("n="); scanf("%d",&n); printf("Cantitatile de benzina "); printf("care se cumpara:\n"); for (int i=0;i<n;i++){ scanf("%d",&m[i].cant_benz); m[i].nr=i; } ordonare(n); puts("Ordinea:"); for (i=0;i<n;i++) printf("m%d\n",m[i].nr+1); timp[0]=timp_total=0; for (i=1;i<n;i++) timp[i]=timp[i-1]+m[i-1].cant_benz, timp_total+=timp[i]; printf("Timpul total minim de"); printf("asteptare: %d\n", timp_total); }
Gigel vine acasă de la școală și își despachetează rucsacul. Își așează cărțile pe birou într-o stivă. Scrieți un subprogram comentat care simulează operația de creare a stivei de cărți. Subprogramul trebuie să returneze pointerul q care indică stiva creată. Pentru fiecare carte se va citi titlul. Numărul cărților nu se cunoaște. Soluție Deoarece numărul cărților nu se cunoaște, vom răspunde în program la întrebarea: Mai sunt carti in rucsac? (variabila raspuns). Condiția din instrucțiunea repetitivă while verifică dacă răspunsul la întrebare este 'D' (DA), sau 'N' (NU) pentru a avea posibilitatea de a continua, după caz cu inserarea unui element nou în stiva de cărți, sau pentru a încheia crearea. Pentru a asigura acceptarea răspunsului atât cu litere mari cât și mici, acesta se transformă în literă mare cu ajutorul funcției Upcase (pentru Pascal), respectiv toupper() (pentru C). Deoarece crearea stivei se realizează în subprogram, inițializarea pointerului care va indica capul ei după creare, poate fi realizat fie în subprogram, fie în programul principal.
Varianta Pascal: Presupunem că stiva are următorul tip: type carti=^carte; carte=record titlu:string[10]; urm:carti end;
Parametrul formal q se transmite prin referință, pentru a asigura accesul la stivă în afara subprogramului. Subprogramul de creare poate fi scris în felul următor:
Procedure creare(var q:carti); var raspuns:Char; p:carti; begin q:=nil; Write('Exista cel putin o carte? '); Readln(raspuns); while Upcase(raspuns)='D' do begin New(p); Write('Titlul: '); Readln(p^.titlu); p^.urm:=q; q:=p; Write('Mai exista carti in rucsac? '); Readln(raspuns) end end;
Varianta C: Presupunem că stiva are următorul tip: struct carti{ char titlu[10]; urm *carti; }
Vom scrie o funcție care va returna o referință spre capul stivei. Suprogramul de creare poate fi scris în felul următor:
carti* creare(void){ char raspuns; carti *p, *q=NULL; printf("Exista cel putin o carte? "); fscanf("%c\n",&raspuns); while (toupper(raspuns)=='D'){ p=new carti; printf("Titlul:"); scanf("%s",p->titlu); p->urm=q; q=p; printf("Mai exista carti in rucsac? "); fscanf("%c\n",&raspuns); } return q; } Subiectul 1: 30 puncte
1) 7,5 puncte 2) 7,5 puncte 3) 7,5 puncte 4) 7,5 puncte Subiectul 2: 20 puncte 1) 10 puncte 2) 10 puncte Subiectul 3: 20 puncte Subiectul 4: 20 puncte Se acordă 10 puncte din oficiu. TOTAL: 100 puncte [cuprins] |