www.agora.ro

Al doilea bacalaureat în informatică

BACALAUREAT 2000

Primul 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

  • - Ambele structuri sunt repetitive, cu număr necunoscut de pași.
  • - În ambele structuri, cel puțin una din variabilele ce apar în expresia logică (în condiție) trebuie să se modifice în corpul ciclului, altfel se generează un ciclu infinit.
  • - Dacă valoarea de adevăr a condiției de ciclare din structura repetitivă cu test inițial este falsă la prima evaluare a ei, corpul acestuia nu se va executa nici măcar o dată, în timp ce corpul structurii repetitive cu test final, se execută cel puțin o dată, indiferent de valoarea de adevăr a condiției de ciclare.

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:

  • - se salvează adresa instrucțiunii care se va executa după terminarea execuției subprogramului; astfel va fi posibilă revenirea la instrucțiunea de după "locul apelului";
  • - se alocă spațiu pentru parametrii formali;
  • - se copiază valorile parametrilor actuali transmiși prin valoare în spațiul alocat parametrilor formali corespunzători;
  • - se copiază adresele parametrilor actuali transmiși prin referință în spațiul alocat parametrilor formali corespunzători;
  • - se alocă spațiu pentru variabilele locale.

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]