Sunteți pe pagina 1din 138

ALGORITMI.

DESCRIEREA ALGORITMILOR

Algoritmi
Orice activitate umană se desfăşoară, în general, pa baza unor principii
logice sau, altfel spus, a unui algoritm bine definit. Deşi nu se conştientizează acest
lucru, omul acţionează conform unor algoritmi, care reprezintă expresia regulilor
impuse de parcurgerea logică a etapelor necesare pentru a ajunge de la o situaţie
iniţială la un anumit rezultat.
Funcţionarea calculatoarelor se aseamănă în mare măsură cu activitatea
umană. În cazul acestora, este obligatorie conştientizarea faptului că întreaga
activitate a echipamentului de calcul se bazează pe respectarea unor algoritmi,
algoritmi ce sunt elaboraţi de factorul uman dotat cu raţiune şi capacitate de
analiză. Calculatorul nu dispune de calităţile omului, ca atare, în procesul de
rezolvare a unei probleme cu ajutorul echipamentului electronic de calcul este
obligatorie parcurgerea unei etape importante, şi anume elaborarea algoritmului de
calcul. Succesul rezolvării problemei depinde de calitatea algoritmului întocmit de
către utilizator şi aplicat de echipamentul de calcul prin intermediul unui program.
Calculatoarele numerice prelucrează informaţiile prin executarea unor
operaţii simple. Deşi operaţiile sunt elementare, prin înlănţuirea unei mulţimi de
operaţii se poate ajunge la prelucrări deosebit de complexe. Combinarea operaţiilor
nu se face la întâmplare, ea supunându-se unor reguli bine precizate. Studiul
acestor reguli are la bază noţiunea de algoritm. Noţiunea de algoritm este strâns
legată de noţiunea de calcul.
Intuitiv un algoritm de calcul este o mulţime finită de operaţiuni cunoscute
care executate într-o ordine bine stabilită, pornind de la un set de valori, numite
date de intrare, conduc într-un timp finit la un set de valori, numite date de ieşire.
Algoritmul reprezintă o mulţime de asemenea calcule. Altfel spus, prin
algoritm se înţelege metoda de rezolvare a unei probleme într-un număr finit de
paşi. Metoda de rezolvare este în esenţă un şir de operaţii precise, care dacă sunt
îndeplinite conduc la rezultatul dorit într-un număr finit de paşi.
Se poate spune că un algoritm constituie un sistem de reguli care, aplicat la
o clasă de probleme de acelaşi tip, conduce de la o situaţie iniţială la un rezultat
final prin intermediul unor operaţii succesiv ordonate, unic determinate.
O informaţie iniţială pentru care un algoritm de calcul este aplicabil, se
numeşte informaţie admisibilă. Totalitatea informaţiilor de acest gen constituie
domeniul algoritmului.
Cunoscând faptul că orice algoritm conţine un anumit număr de etape
numite şi paşii algoritmului, se poate afirma că regulile algoritmului f aplicate
asupra informaţiei iniţiale, care aparţine domeniului D, determină întotdeauna
obţinerea informaţiei finale corespunzătoare. Ca urmare, un algoritm poate fi
definit ca o funcţie:

1
f = D F unde: D= domeniul algoritmului (informaţiile iniţiale);
F= soluţia finală (informaţiile finale).
În general, un algoritm se caracterizează prin:
 unicitatea. regulile algoritmului determinând unicitatea ordinii în care au
loc toate transformările intermediare, dar şi obţinerea informaţiei finale,
după care activitatea algoritmului se opreşte.
 finalitate. Orice pas al algoritmului trebuie să se termine după un număr
finit de paşi, şi anume atunci când este obţinut rezultatul final, nu cel
intermediar. Această proprietate se mai numeşte şi realizabilitate
potenţială.
 claritate (să fie definit). Fiecare pas al algoritmului trebuie să fie precis
definit. Operaţiile ce trebuie efectuate în cadrul fiecărui pas trebuie să
fie specificate în mod riguros, precis, astfel încât să nu apară ambiguităţi
în interpretare lui de către cel care îl execută. Totodată, trebuie riguros
precizate toate etapele de calcul ce trebuie urmate pentru a obţine soluţia
finală;
 eficacitate. Orice algoritm trebuie să fie eficace. Aceasta înseamnă că
toate operaţiile algoritmului să poată fi efectuate de un individ cu creion
şi hârtie într-un interval de timp finit.
 generalitate (universal) - adică să permită rezolvarea oricărei probleme
dintr-o anumită clasă de probleme pentru care a fost stabilit.
Ca exemple de algoritmi cunoscuţi din matematică amintim: algoritmul lui
Newton pentru aflarea rădăcinii pătrate aritmetice a unui număr, algoritmul lui
Euclid pentru aflarea celui mai mare divizor comun a două numere etc .

Descrierea algoritmilor.
Transcrierea algoritmului într-un limbaj de programare, în vederea rezolvării
lui cu ajutorul calculatorului numeric poartă numele de program. Programele
transmise calculatorului, ca o reprezentare fidelă a algoritmului de calcul sunt
transcrise într-un limbaj “înţeles” de calculator, nu conţine ambiguităţi şi specifică
precis şi clar doar operaţiile pe care calculatorul le poate executa.
Scrierea unui algoritm poate fi făcută rareori direct într-un limbaj de
programare. Ca atare realizarea unui program comportă, uzual nişte etape
intermediare.
În vederea întocmirii unui algoritm de calcul şi utilizării acestuia la
calculator, este necesară realizarea următoarelor activităţi:
 definirea problemei;
 formularea modelului matematic al problemei;
 stabilirea algoritmului de rezolvare a problemei;
 reprezentarea algoritmului;
 scrierea programului corespunzător algoritmului, prin utilizarea unui
limbaj de programare adecvat;
 transpunerea programului pe un suport tehnic de memorie;
2
 testarea, depanarea şi execuţia programului;
 întreţinerea programului.
Calitatea programelor şi succesul execuţiei acestora depinde de calitatea
algoritmilor utilizaţi, de respectarea caracteristicilor specifice pentru orice
algoritm, cât şi de mărimile şi operaţiile utilizate în descrierea algoritmilor.
Mărimile utilizate în cadrul algoritmilor pot fi clasificate astfel:
 după tipul datelor, respectiv din ce mulţime poate lua valori mărimea
respectivă:
 date numerice;
 date alfanumerice;
 date logice;
 date calendaristice.
 după natura datelor:
 date constante;
 date variabile.
Operaţiile utilizate în descrierea algoritmilor sunt:
 operaţii de calcul aplicate asupra variabilelor. În cadrul acestora, se
utilizează operatorii aritmetici +, -, , /,* ce corespund operaţiilor de
adunare, scădere, înmulţire, împărţire şi ridicare la putere, care se împart
pe trei nivele de prioritate:
 ridicarea la putere - prioritatea maximă;
 înmulţirea şi împărţirea;
 adunarea şi scăderea.
 operaţii de atribuire (x=(a+b)-c);
 operaţii de decizie (relaţionali , , , ,  sau logici , , )
Descrierea algoritmilor se realizează cu ajutorul reprezentărilor grafice sau
textuale cât mai sugestive, care să permită obţinerea unei imagini de ansamblu
asupra etapelor din cadrul acestora, dar şi transpunerea mai facilă a algoritmilor în
programe.
Orice reprezentare trebuie să reflecte toate etapele, toate operaţiile conţinute
de algoritmi, ceea ce presupune existenţa unor convenţii de reprezentare a acestora.
Algoritmii pot fi reprezentaţi grafic cu ajutorul schemelor logice şi a diagramelor
arborescente, iar reprezentarea textuală se efectuează cu ajutorul limbajelor de tip
pseudocod.

Scheme logice
Schemele logice reprezintă scrierea algoritmilor de calcul cu ajutorul unor
simboluri (forme) geometrice, care evidenţiază diferite tipuri de acţiuni.
Realizarea schemei logice corespunzătoare unui algoritm este utilă fie la
depanarea programelor, fie la lucrul în echipă, fie la schimbul de informaţii dintre
diverse grupuri de programatori,întrucât ea specifică precis şi clar ordinea de
parcurgere a blocurilor (simbolurilor geometrice).

3
Simbolurile uzuale utilizate în realizarea schemelor sunt cuprinse în tabelul
de mai jos:

SIMBOL DENUMIREA UTILIZAREA


Uneşte componentele schemei logice, indicând
săgeată
succesiunea operaţiilor
Evidenţiază punctele de intersecţie a săgeţilor
Bloc conector dintre mai multe blocuri dispuse pe aceeaşi
pagină
Evidenţiază continuarea schemei logice pe o altă
Conector de
pagină; se menţionează în locurile de început /
pagină
sfârşit de pagină din cadrul schemei logice
Marchează începutul / sfârşitul schemei logice;
Bloc terminal în interior se menţionează START / STOP, iar în
cazul subrutinelor PRELUCRAE / REVENIRE
Marchează operaţiile de citire a variabilelor
Bloc de intrare / supus prelucrării şi de scriere a rezultatelor:
ieşire READ / WRITE sau CITEŞTE / SCRIE preced
variabilele
Pune în evidenţă operaţiile de calcul şi atribuire
Bloc de calcul
(ex.: x=y+z, I=0)
Marchează ramificaţii, determinate de condiţia
Bloc de decizie
înscrisă în bloc
Bloc de Se utilizeză pentru a marca începutul sau apelul
procedură unei proceduri.
Evidenţiază o subrutină (detalierea unor părţi din
Bloc de
algoritm separat de schema de bază) care
procedură
urmează a fi apelată.
Succesiunea operaţiilor din cadrul unui algoritm poate fi pusă în evidenţă
prin intermediul a trei tipuri de structuri de bază, elementare:
- structura liniară (secvenţială) – presupune executarea necondiţionată a
operaţiilor din cadrul unui algoritm, în ordinea logică a derulării acestora;

START

CITEST

E
i
SUBRUTINA
XEITES
TE
PRINT
i

STOP

4
- structura alternativă (de selecţie) necesită punerea în evidenţă a tuturor
căilor de rezolvare a problemei – cu descrierea operaţiilor specifice de
realizare pe fiecare variantă – ce apar ca urmare a existenţei unei condiţii
date în cadrul algoritmului. Pot fi utilizate trei tipuri de structuri
alternative:
 Structura alternativă cu selecţie simplă (IF – THEN) – apariţia condiţiei
C presupune existenţa a două căi alternative de parcurgere în continuare a
operaţiilor;
 Structura alternativă cu selecţie dublă (IF – THEN - ELSE) – dacă este
îndeplinită condiţia C, se execută operaţiile de pe ramificaţia notată cu
DA, altfel se execută alte operaţii, total diferite, evidenţiate pe ramura
notată cu NU;
 Structura alternativă cu selecţie multiplă (CASE – OF) – permite selecţia
între mai mult de două posibilităţi de continuare în rezolvarea problemei.
START START
I
I
CITEST CITEST
I
E DA E DA I
A2
i i
I
EITES EITES
TE A1 A3
TE

PRINT PRINT
i
i

STOP STOP i

IF - THEEN IF – THEN - ELSE CASEi - OF


I

- STRUCTURA REPETITIVĂ (CICLICĂ) se bazează pe repetarea unei


secvenţe din algoritm, care poate să cuprindă una sau mai multe operaţii.
Există următoarele tipuri de operaţii repetitive:
- WHILE – DO presupune executarea unei anumite secvenţe din algoritm
atâta timp cât este îndeplinită condiţia C. Deoarece structura este
condiţionată anterior, există posibilitatea ca secvenţa respectivă să nu se
execute niciodată.
- DO – UNTIL , condiţionare posterioară, secvenţa din program se execută
cel puţin o dată, întrucât decizia de reluare a secvenţei se ia după
executarea acesteia.
- DO – FOR se execută atunci când se cunoaşte de câte ori trebuie repetată
o anumită secvenţă. Ea se caracterizează prin apariţia unei variabile
numită contor, care evidenţiază numărul de repetări a secvenţei.

=Vi

A
A
C
NU V=V+r
C 5
DA
A V>V
r
WHILE - DO DO - UNTIL DO - FOR
Exemplu:
Se cere algoritmul şi schema logică pentru calculul lui n!
Paşii algoritmului de calcul sunt :
1. citeşte valoarea lui n;
2. atribuie lui P valoarea 1;
3. atribuie lui I valoarea 1;
4. atribuie lui P valoarea expresiei P * I;
5. atribuie lui I valoarea expresiei I + 1;
6. dacă I<N atunci treci la pasul 4;
7. scrie valoare lui P;
8. stop.
Schema logică corespunzătoare algoritmului:

START

Citeşte
n

p: = 1

i: = 1

p: = p * i

i: = i + 1

i< = n scrie STOP


p

Diagrama arborescentă
Diagrama arborescentă constituie o altă modalitate de reprezentare grafică a
algoritmilor. Ca şi în cazul schemelor logice, există mai multe convenţii de
reprezentare a operaţiilor în cadrul algoritmilor.

Limbajul Pseudocod
Spre deosebire de schemele logice, limbajele Pseudocod folosesc cuvinte cu
înţeles prestabilit (numite cuvinte cheie) şi câteva reguli simple de aliniere a
textului scris.
Pseudocodul reprezintă un mijloc de exprimare naturală şi dezvoltare
sistematică a algoritmilor.

6
Pseudocodul are puţine reguli sintactice lăsând programatorului o mare
libertarte în exprimarea acţiunilor algoritmilor.
Pseudocodul permite specificarea algoritmilor prin două tipuri de enunţuri
nestandard şi standard.
Enunţurile nestandard sunt fraze în limbaj natural care pot fi utilizate de
programator în schiţarea formelor iniţiale ale algoritmilor şi sunt precedate de
***. În dezvoltarea algoritmilor, enunţurile nestandard sunt înlocuite treptat cu
enunţuri standard care exprimă operaţii cu corespondente directe în limbajele de
programare.
În forma standard fiecare comandă (operaţie) este reprezentată în limbajul
Pseudocod printr-un cuvânt care exprimă operaţia ce trebuie executată, însoţit de
obicei, de elemente suplimentare care îi particularizează efectul.
Limbajul pseudocod nu este un limbaj de programare, ci o modalitate
textuală de reprezentare a algoritmilor. El poate fi utilizat în locul reprezentărilor
grafice, dar faţă de schemele logice este mult mai puţin utilizat de către
programatori.
Construcţia de bază a limbajului pseudocod este propoziţia, un algoritm
fiind reprezentat printr-o succesiune de propoziţii care pot fi:
- propoziţii simple care exprimă operaţii ce pot fi transpuse direct într-un
limbaj de programare;
- propoziţii complexe, notate cu simbolul #, care urmează să fie detaliate
ulterior până la nivelul propoziţiilor simple.
Fiecare propoziţie începe cu un verb care exprimă operaţia descrisă. Un
exemplu de algoritm reprezentat cu ajutorul limbajului pseudocod poate fi
următorul:
citeşte var
atribuie var=expr
execută nume_proced
scrie var
stop
unde: var semnifică o variabilă;
expr reprezintă o expresie algebrică sau logică;
nume_proced este numele unei proceduri, care va fi detaliată
ulterior.
Pentru a fi puse în evidenţă operaţiile, verbele sunt subliniate.
Cuvântul care identifică operaţia se numeşte cuvânt cheie. Enunţurile
standard utilizate în limbajele Pseudocod şi semnificaţia lor sunt următoarele:
a) operaţia de intrare (citire) - constă în transferul unor valori de pe
mediul de intrare (eventual de pe cartele sau de la un terminal) în locaţii de
memorie specificate prin ‘lista de variabile’
Structura comenzii: citeşte lista de variabile
Exemplu: citeşte a,b,c

7
În locaţiile desemnate prin variabilele a,b,c se transferă valori de pe mediul de
intrare.
b) Operaţia de ieşire (scriere) - constă în transferul unor valori din
locaţiile de memori specificate prin ‘lista de variabile’, pe mediul de ieşire
(imprimantă, display etc.)
Structura comenzii: scrie lista de variabile
Exemplu: scrie x,a,d,g
Conţinutul locaţiilor de memorie desemnate prin variabilele x,a,d,g este
transferat de mediul de ieşire.
c) Operaţia de atribuire – constă în calculul valorii unei expresii, valoare ce
se atribuie unei variabile.
Structura comenzii: atribuie variabilă  expresie
Exemplu: atribuie D a*b+c
atribuie E  x /\ y \/ z
Variabilelor D,E li se atribuie valorile obţinute în urma calculului valorii
expresiilor din dreapta semnului 
d) Operaţia de oprire – are ca efect oprirea execuţiei comenzilor în
calculator
Structura comenzii: stop
e) Secvenţa – este o structură realizată prin scrierea succesivă (în secvenţă) a
comenzilor componente.
Exemplu: citeşte A,B
atribuie C  A + B
scrie A , B , C
stop
Efectul execuţiei unei comenzi depinde de poziţia comenzii în cadrul secvenţei .
f) Decizia – este o structură care asigură alegerea pentru execuţie a unei
secvenţe din două alternative posibile.
Structura comenzii: dacă condiţie atunci
secvenţa1
altfel
secvenţa 2
[]
Începutul comenzii de decizie este marcat de cuvântul cheie “dacă” iar
sfârşitul său de semnul []
Execuţia acestei comenzi comportă următoarele etape:
 se evaluează “ condiţia”;
 dacă rezultatul evaluării este adevărat (condiţie îndeplinită) se execută
secvenţa 1;
 în caz contrar se execută secvenţa 2.
După executarea secvenţei 1 sau a secvenţei 2 se trece la următoarea
comandă (cea după semnul [] )

8
Observaţie: În cazul în care secvenţa care urmează după cuvântul cheie “altfel”
lipseşte, se utilizează forma simplificată a deciziei:
dacă condiţie atunci
secvenţa1
[]
În cazul în care condiţia nu este îndeplinită se trece direct la comanda ce
urmează deciziei

Exemplul:
dacă A > B atunci
scrie A
altfel
scrie B
[]
Efectul execuţiei exemplului de mai sus este următorul:dacă valoarea
variabilei A este mai mare decât a variabilei B se scrie valoarea lui A în caz contrar
se scrie valoarea variabilei B şi nu valoarea variabilei A.
Exemplul: Decsrierea în Pseudocod a algoritmului de aflare a celui mai
mare element din 3 valori reale desemnate prin variabilele a,b,c.Variabila “x” va
conţine cel mai mare element din cele 3 valori.Algoritmul de rezolvare a unei
probleme nu este unic.Ca atare se dau două descrieri Pseudocod pentru rezolvarea
acestei probleme.
a) varianta 1
citeşte a,b,c
dacă a>b atunci
atribuie x  a
altfel
atribuie x  b
[]
dacă c > x atunci
atribuie x  c
[]
scrie x
stop
b) varianta 2
citeşte a,b,c
atribuie x  a
dacă x < b atunci
atribuie x  b
[]
dacă x < c atunci
atribuie x c
[]
9
scrie x
stop
O variantă simplificată : citeşte a,b,c,
atribuie x a
dacă x < b atunci atribuie x  b
dacă x < c atunci atribuie x  c
scrie x
stop
Observaţie: Ultima variantă a algoritmului are avantajul că poate fi uşor
generalizată pentru aflarea maximului unui şir.
g) Selecţia reprezintă o extindere a operaţiei de decizie, ea permitând alegerea
unei alternative din mai multe posibile.Forma generală a comenzii de selecţie
este următoarea :
alege expresia dintre
c1 : secvenţa 1
c2 : secvenţa 2
.
.
cn : secvenţa n
rest : secvenţa n+1
[]
Unde c1 , c2 , ... cn sunt etichete şi se folosesc pentru identificarea
secvenţelor.Sfârşitul comenzii este marcat de _[] iar liniile textului selecţiei sunt
marcate prin etichetele c.
Modul de execuţie al comenzii de selecţie este următorul:
 se evaluează expresia
 se identifică eticheta ci ce are aceeaşi valoare cu expresia ( în urma
evaluării expresiei)şi este selectată secvenţa corespunzătoare.Dacă nici o
etichetă nu are valoarea expresiei atunci este selectată secvenţa n+1,
corespunzătoare etichetei rest.
 se execută secvenţa selecctată şi se sare la sfârşitul comenzii de selecţie
adică după semnul [].
Exemplu: Să se adune valoarea întreagă v la una din variabilele s0,s1,s2 ,s3,
după cum restul împărţirii valorii v la 4 este 0,1,2 sau 3 .Descrierea în Pseudocod
arată astfel:
citeşte v,s0,s1,s2,s3
alege v – int ( v/4)*4 dintre
0: atribuie s0  s0 + v
1: atribuie s1  s1 + v
2: atribuie s2  s2 + v
3: atribuie s3  s3 + v
[]
scrie s0,s1,s2,s3
stop
10
În acest caz , eticheta “rest” şisecvenţa respectivă lipseşte ,deoarece
domeniul de valori ale expresiei este mulţimea (0,1,2,3).
h) Ciclul cu test final – În rezolvarea unei probleme , nu de puţine ori apare
situaţia executării repetate a unei secvenţe de operaţii.O astfel de combinaţie ,
în care execuţia unui grup de operaţii se repetă se numeşte ciclu sau
iteraţie.Pentru reprezentarea ei se utilizează o comandă de ciclare care
specifică atâtoperaţiile care se repetă cât şi condiţia de repetare.
Forma generală a comenzii de ciclare cu test final este următoarea:

repetă
secvenţa
până condiţia
[]
Modul de execuţie al comenzii de ciclare este următorul:
1-se execută secvenţa
2-se evaluează condiţia şi dacă rezultatul este fals(condiţie neîndeplinită)se
continuă cu etapa 1 , altfel execuţia comenzii se termină şi se trece la comanda
următoare.
Exemplu: Se dă algoritmul lui Euclid pentru afişarea celui mai mare
divizor comun a două numere întregi m,n(m>=n>0).
1. citeşte valorile lui m şi n
2. atribuie lui c valoarea lui n ( în variabila c se reţine cel mai mare divizor
comun )
3. atribuie lui r restul împărţirii întregi a lui m la n
4. dacă r diferit de 0 atunci treci la 7
5. scrie valoarea lui c
6. stop
7. atribuie lui m valoarea lui n
8. atribuie lui n valoarea lui r
9. treci la pasul 2
Se observă că operaţiile care se realizează calculul restului şiactualizarea
valorilor c, m şi n se repetă.
Folosind Descrierea în Pseudocod a algoritmului şi ciclul cu test final vom
avea:
citeşte m,n
repetă
atribuie c  n , r  m-int(m/n)*n
atribuie mn , n  r
până r=0
_[]
scrie c
stop

11
Condiţia de terminare a ciclului poate fi orice expresie logică.Secvenţa de
operaţii din ciclu alcătuieşte corpul ciclului .Ea poate conţine oriceoperaţii,
inclusiv iteraţii.
i) Ciclul cu test iniţial – În cazul ciclurilor sau iteraţiilor condiţia de ciclare
poate apare şi la începutul secvenţei de ciclare
Forma generală este :
cât timp condiţia execută
secvenţa
[]
Condiţia poate fi orice expresie logică , iar secvenţa poate conţine orice
comenzi , inclusiv comenzi de ciclare.
Modul de execuţie al ciclului cu test iniţial :
1-se evaluează condiţia;dacă rezultatul este fals(condiţie neîndeplinită) execuţia se
termină,iar dacă rezultatul este adevărat se continuă secvenţa(etapa 2)
2-se execută secvenţa,după care se continuă cu 1.
În cazul în care rezultatul evaluării condiţiei este fals încă de la
început,secvenţa nu se execută niciodată spre deosebire de ciclul cu test final,când
secvenţa se executa cel puţin o dată.
Scrierea algoritmului lui Euclid în Pseudocod folosindciclul cu test iniţial
ne conduce la:
citeşte m,n
atribuie c  n , r  m-int(m/n)*n
cât timp r <> 0 execută
atribuie m  n , n  r, c  n
atribuie r  m-int(m/n)*n
[]
scrie c
stop
j) Ciclul de contor, cu forma generală:
pentru contor = val iniţială, val.finală,pas execută
secvenţa
[]
unde prin contor se înţelege o variabilă cu valori întregi:”valoarea iniţială, finală
şi pas” pot fi expresii aritmetice cu valori întregi.
Execuţia ciclului cu contor se explicitează astfel:
1) variabilei contor i se atribuie valoarea iniţială;
2) se verifică condiţia contor > val. Finală; dacă rezultatul este fals se
continuă cu, astfel execuţia ciclului se termină;
3) se execută secvenţa
4) se modifică valoarea contorului cu pasul p şi se continuă cu pasul 2)
Exemplu: aflarea lui n!
Observaţii: 1. Dacă pasul de ciclare este 1, se poate omite
2. Algoritmul a fost completat şi pentru cazul în care n = 0
citeşte n
12
atribuie p = 1
dacă n>0 atunci
pentru i=1,n execută
atribuie p=p*i
[]
[]
scrie p
stop
k) Proceduri şi funcţii
În rezolvarea unor probleme apar frecvent situaţii când un număr decomenzi
se repetă schimbându-se numai variabilele ce compun aceste comenzi,structura
comenzilor rămânând aceeaşi.
Pentru a nu repeta acel număr de comenzi în mai multe locuri în cadrul
descrierii algoritmului de rezolvare a problemei se folosesc procedurile şi funcţiile.
Procedura – descrie în termeni generali un algoritm cu posibilitatea de a
aplica acel algoritm în diverse cazuri particulare concrete.
Pentru a se identifica,procedurii i se asociază un nume.La definirea
procedurii trebuie să se asocieze un se de parametri , variabile care specifică
mărimile ce se modifică la fiecare apelare a procedurii.
Structura unei proceduri, în Pseudocod este :
Procedure nume (parametrii) este:
secvenţa
sfârşit
unde:
- nume = numele procedurii
- parametrii = parametrii formali ai procedurii
Apelul unei procedurei specifică numeleprocedurii,precum şi parametrii
actuali prin care se transmit valorile cu care se efectuează comenzile din
procedură.
Structura apelului unei proceduri este :
execută nume ( parametrii )
unde : - nume = numele procedurii ce se apelează
- parametrii = parametrii actuali ( efectivi ),adică cei pentru care
urmează a se efectua comenzile din procedură.
Exemplu: Să se construiască o procedură pentru aflarea normei unui
vector.Se ştie că norma unui vector A de n componente se defineşte prin relaţia:
S=

Descrierea în Pseudocod a procedurii este :


Procedura norma (a, n; s) este :
atribuie s  0
pentru i=1,n,1 execută
atribuie s  s + |ai|

13
[]
sfârşit norma
Numele procedurii este “norma”.Parametrii de intrare necesari pentru a se
realiza calculele din procedură sunt vectorul a şi numărul de elemente ale
vectorului n, iar parametrul de ieşire este S,prin el se obţine rezultatul calculelor-
norma . Separarea parametrilor de ieşire de cel de intrare se face prin punct şi
virgulă . Parametrii de intrare şi cei de ieşire specificaţi la definirea procedurii se
numesc parametrii formali.
Exemplu: Să se folosească procedura definită pentru a determina dacă norma
vectorului x de l componente este mai mare decât norma vectorului w de m
componente.
Descrierea în Pseudocod a algoritmului de aflare a celei mai mari dintre
normele vectorilor x şi w este următoarea :
citeşte l ,(xi , i = 1, 1)
citeşte m,(xi , i = 1,m)
execută norma (x ,l ; s1)
execută norma (w,m; s2)
dacă s1>s2 atunci
scrie ‘norma vectorului x este mai mare’
altfel
scrie ‘norma vectorului w este mai mare’
[]
stop
În apelulprocedurii norma , parametrii x,l,s1,respectiv w,m,s2 sunt
parametrii actuali.
Comanda “execută” urmată de numele procedurii are ca efect execuţia
operaţiilor care constituie procedura cu numele specificat , în care valorile
parametrilor formali sunt înlocuite cu valorile parametrilor efectivi
corespunzători,adică parametrii a,n,s din procedura sunt înlocuiţi cu x,l,s1
respectiv w,m,s2 din apelul procedurii.
Corespondenţa dintre parametrii efectivi şi parametrii formali este
poziţională , adică parametrul care ocupă poziţia p în lista parametrilor formali
este înlocuit cu parametrul care ocupa poziţia p în lista parametrilor
efectivi.Aceasta substituţie se numeşte transferul parametrilor.Comanda “ execută”
se termină odată cu terminarea execuţiei ultimei operaţii din procedură.
Funcţia
Atunci când procedura calculează o singură valoare se poate utiliza un tip
particular de procedură numit funcţie.Descrierea unei funcţii cuprinde :
- linia de definire a funcţiei
- secvenţa de operaţii ce constituie corpul funcţiei
- linia finală
Structura unei funcţii în Pseudocod este următoarea :
funcţia nume (parametrii ) este:
secvenţa
14
sfârşit
unde:
- nume reprezintă numele funcţiei
- parametrii sunt parametrii funcţiei şi trebuie să fie doar parametrii de
intrare
Singurul parametru de ieşire în cazul funcţiei este considerat chiar numele
funcţiei care este utilizat în secvenţa de operaţii din corpul funcţiei ca orice
parametru. Valoarea acestui parametru reprezintă valoarea funcţiei.Secvenţa din
corpul funcţiei trebuie să conţină o comandă de atribuire prin care numelui funcţiei
i se atribuie o valoare.
Exemplu: Să se definească o procedură pentru calculul lui n!.
Descrierea în pseudoco a funcţiei este :
funcţia fact(m) este :
atribuie p 1
dacă m>1 atunci
pentru i=1,m,1execută
atribuie p p*i
[]
[]
atribuie fact p
sfârşit fact
Apelul unei funcţii este considerat ca operand în cadrul expresiilor .Structura
apelului unei funcţii în Pseudocod este :
nume( parametri )
unde :
- nume -reprezintă numele funcţiei
- parametrii - reprezintă lista parametrilor actuali de intrare ai funcţiei
Eexmplu:
Să se folosească funcţia descrisă mai sus pentru calculul combinărilor:
= =

Descrierea în Pseudocod a algoritmului este :


citeşte n,k
atribuie cnk  fact(n)/fact(n-k)*fact(k)
ank  cnk*fact(k)
scrie cnk,ank
stop
Execuţia unei funcţii intervine atunci când la evaluarea unei expresii este
necesară valoarea sa .În acest caz se face transmisia parametrilor efectivi,se
execută secvenţa de operaţii corespunzătoare corpului funcţiei, găsindu-se astfel
valoare funcţiei.

Programarea
15
În general, scopul final al elaborării unui algoritm este transpunerea şi
execuţia automată a acestuia cu ajutorul calculatorului. Etapele de parcurs sunt
prezentate mai jos.
O primă fază constă în editarea programului în format sursă cu ajutorul unui
editor de texte propriu limbajului de programare sau extern.
Când se dispune de un compilator se parcurg următoarele faze:
- compilarea programului – constă în conversia unui program din limbajul
de programare de nivel înalt în care a fost scris (program sursă) într-un
limbaj apropiat de cel al calculatorului (program obiect);
- editarea de legături (link-editarea) – realizează legăturile între diferitele
module obiect şi soluţionează apelurile la funcţiile de bibliotecă referite
în program;
- execuţia programului – constă în parcurgerea pas cu pas şi efectuarea
operaţiilor specificate de codul de instrucţiuni, în limbaj maşină, de către
unitatea centrală a calculatorului.

PROBLEMĂ
Analiză, proiectare
OM
ALGORITM Programare

Editare
PROGRAM SURSĂ
PROGRAM SURSĂ
EDITAT
NU DA
Compilare
COMPILATO
R
Run
Program obiect
Linkeditare

Run
Execuţie sub Program
interpretor executabil
Execuţie

SOLUŢIE

Când nu se dispune de un compilator ci doar de interpretor, după introducerea


programului sursă se trece direct la execuţia programului.
Deosebirea fundamentală între execuţia unui program care a fost compilat şi
linkeditat şi cea efectuată sub interpretor, constă în faptul că, în primul caz se
16
execută numai programul propriu-zis, pe când în al doilea caz în timpul execuţiei
se efectuează şi interpretarea, verificarea şi decodificarea instrucţiunilor, ceea ce
conduce la un timp de răspuns mult mai mare.

Sugestii pentru scrierea programelor :


În rezolvarea unei probleme cu ajutorul calculatorului pot fi puse în evidenţă
următoarele etape :
1. Enunţarea problemei şi formularea ei matematică .În această etapă se
precizează problema de rezolvat,formularea ei matematică adică trebuie :
- să se exprime matematic relaţiile şi restricţiile dintre parametrii problemei;
- să se precizeze condiţiile iniţiale ale problemei;
- să se formuleze restricţiile referitoare la soluţia sau soluţiile problemei;
- să se precizeze modul de prezentare a rezultatelor( tabele,grafice etc.)
2. Alegerea metodei numerice trebuie să se facă , ţinând cont de precizia
calculelor,viteza de calcul, cantitatea de date cu care se lucrează şi simplitatea
formulelor.
3. Descrierea algoritmului de calcul ales sub forma unei scheme logice sau în
Pseudocod.Realizarea schemei logice sau a Pseudocodului pune în evidenţă
succesiunea logică a etapelor importante de calcul şi a deciziilor logice necesare
obţinerii rezultatelor.
4. Întocmirea programului de calcul.În această etapă se realizează transcrierea
algoritmului de calcul direct după schema logică sau după Descrierea în
Pseudocod într-un limbaj de programare.
5. Testarea rezultatelor .Această etapă este absolut necesară în cazul elaborării
unor noi programe şi constă în verificarea programului sursă , a algoritmului
ales şi a modului în care se obţin rezultatele .Pentru aceasta se vor folosi
exemple de control pentru care se cunosc soluţiile.
6. Interpretarea rezultatelor.Implică o analiză detaliată a rezultatelor obţinute ,
efectuarea unor modificări de date,de condiţii în cazul în care rezultatele nu
sunt scontate.

17
IMPLEMENTAREA ALGORITMILOR

De pe mediul de intrare se citeşte un număr real alfa ce reprezintă un


unghi exprimat în radiani.Să se convertească unghiul alfa în grade,minute
şi secunde.
a) Descrierea algoritmului în limbaj natural.
Conversia unui unghi din radiani într-un număr fracţionar de grade se face cu
relaţia:
x = alfa * 180 / PI
După separarea părţii întregi a lui x, ce reprezintănumărul întreg de grade (grade),
partea fracţionară se utilizează pentru aflarea părţii fracţionare de minute
(minfract). Din minfract se obţine minute, numărul întreg de minute şi partea
fracţionară de secunde (secfract), din care se extrage partea întreagă de secunde
(secunde).
Descrierea şi semnificaţia structurilor de date folosite:
alfa: valoarea în radiani a unghiului
grade,minute,secunde : valoarea transformată
x,minfract,secfract : variabile de lucru
START

citeşte alfa

x : = 180* alfa / PI

grade : = trunc (x)

Minfract: = (x-grade)*60

Minute: = trunc(minfract)

Secfract: = (minfract-minute)*60

secunde: = trunc(secfract)

Scrie
grade,minute,secunde

STOP

Descrierea algoritmului în Pseudocod


O primă formă a algoritmului este:
citeşte unghiul în radiani , alfa
calculează grade,minuteşi secunde

18
afişează rezultatele
Prin detalierea acestor acţiuni se obţine următoarea descriere în Pseudocod :
citeşte alfa
atribuie x  180* alfa / PI;
grade  trunc (x);
minfract x-grade)*60;
minute trunc(minfract);
secfract(minfract-minute)*60;
secundetrunc(secfract)
scrie grade,minute,secunde
stop

Programul Pascal
Program conversie;
const
PI =3.14159;
cvgms =60;
cvrg =180;
var
alfa,x,minfract,secfract : real;
grade,minute,secunde : integer;
BEGIN{main}
{citire conversationala de date}
write(‘introduceti alfa in radiani’);
readln(alfa);
x:=alfa*cvrg/PI;
grade:=trunc(x);
minfract:=(x-grade)*cvgms;
minute:=trunc(minfract);
secfract:=(minfract-minute)*cvgms;
secunde:=trunc(secfract);
writeln(alfa:8:4,’radiani =’,grade:4,’grade ,minute:3,’minute’, secunde:3,
’secunde’);
END.
La conversia atât a gradelor în minute cât şi a minutelor în secunde se face
cu o înmulţire cu 60. Această valoare s-a introdus ca o constantă de conversie a
gradelor, minutelor, secundelor (cvgms). În acest mod programul a căpătat un
caracter mai general. Astfel, dacă se doreşte utilizarea programului pentru
conversii grade centesimale se va modifica numai această declaraţie de constantă.
La fel au fost tratate PI şi constanta de conversie a radianilor în grade (cvrg). Se
remarcă utilizarea la scriere a formatului.

19
De pe mediul de intrare se citesc 3 valori reale a,b,c, ce reprezintă
coeficienţii ecuaţiei de ordinul 2 : a * x2 + bx + c = 0. Să se calculeze
soluţiile ecuaţiei.
a) Descrierea şi semnificaţia structurilor de date folosite :
a : coeficientul lui x2
b : coeficientul lui x
c : coeficientul termenului liber
delta : b* b-4 * a * c
x : rădăcina ecuaţiei în cazul în care a=0 şi b<>0
x1,x2: rădăcinile reale ale ecuaţiei pentru delta>0
xR,xI: partea reală,respectiv imaginară a rădăcinilor pentru delta<0
b) Descrierea algoritmului în Pseudocod
Cea mai simplă formă a algoritmului este următoarea:
- citeşte conversaţional coeficienţii a,b,c
- calculează rădăcinile ecuaţiei în funcţie de coeficienţi
- scrie rezultatele
citeşte a,b,c
scrie a,b,c
dacă a=0 atunci
dacă b=0 atunci
dacă c=0 atunci
scrie’coef . a , b , c sunt zero’
altfel
scire’coef. a , b sunt 0 şi c <> 0’
_[]
altfel
atribuie xc/b
scrie x
_[]
altfel
atribuie delta  b*b-4*a*c
dacă delta > 0 atunci
atribuie x1 (- b + sqrt delta)/2/a
x2 (- b - sqrt delta)/2/a
scrie x1,x2
altfel
dacă delta=0 atunci
atribuie x1  b/2/a
x2  x1
scrie x1,x2
altfel
atribuie xR  -b/2/a
xI  sqrt(-delta)/2/a
scrie xR,xI;xE,-x
20
_[]
_[]
_[]
stop
c) Programul Pascal
Program ecuatie2 ;
var a,b,c,x1,x2,xr,xi,x,delta:real;
BEGIN{main}
write(‘Coeficientii a,b,c?);
readln(a,b,c);
if a = 0 then
if b=0 then
if c=0 then
write(‘Coeficentii sunt 0’)
else
write (‘Coeficientii a si b sunt 0’)
else
begin {ec de gr I }
x:= - c / b ;
write(‘x’,x);
end
else
begin {ec de gr. II netriviala}
delta:=b*b-4*a*c;
if delta > 0 then
begin{rad reale distincte}
x1:=(( -b+sqrt(delta))/2*a);
x2:=(( -b-sqrt(delta))/2*a);
end;
else
write ( ‘x1=’,x1,’ ‘,’x2=’,x2);
begin {rad complex conjugate}
xR:= (-b/(2*a));
xI := (-sqrt (-delta)/2*a);
write(‘x1=’,xr,’+ i ‘,xi);
write(‘x2=’,xr,’- i ‘,xi);
end;
end;
END.

Pe mediul de intrare se dau numere întregi reprezentând data unei


zile(an,lună,zi).Să se stabilească a câta zi din an este aceasta.
Descrierea algoritmului în limbaj natural:

21
Dacă data este precizată prin tripletul(a,l,z)reprezentând anul,luna,ziua,se
observă că poziţia ei în an va fi data de zilele celor K=l-1 luni precedente(când
K>0) la care se adaugă cele z zile trecute din luna respectivă
Aflarea numărului de zile din primele K luni ale anului ridică unele dificultăţi
datorită faptului că lunile au numere
diferite de zile. START

Se poate considera un număr mediu


de 30 de zile pe lună şi corecta Citeste a,l,z

numărul total de zile pe baza


observaţiei : pentru K<=7 lunile
NU DA
impare au 31 de zile,iar pentru K>7 K>0
lunile pare au 31 de zile.
Un an bisect este un an al cărui Corectie pentru luni
număr este divizibil cu 4 exceptând cu 31 de zile
anii divizibili cu 100 , dar considerând
ca bisecţi anii divizibili cu 400.
Descrierea şi semnificaţia structurilor DA
de date folosite: K>=2
a,l,z :data ce transformă
k : variabila ce va conţine numărul
Tratare luna februarie
de luni precedente
nr_zi : a câta zi din an este data
introdusă
Descrierea algoritmului în
Pseudocod: Considerarea lunilor
citeşte a,l,z in curs
afisare rezultate
determină numărul K de luni
precedente
calculul numărului aproximativ de zile STOP
dacă K>0 atunci
corecţie pentru luni cu 31 de zile
dacă k>=2 atunci
tratare luna februarie
_[]
_[]
considerarea zilelor lunii în curs
afişare rezultate
stop
Luna februarie va fi tratată separat ţinând cont de anii bisecţi.Se observă că
în primele K luni ale unui an sunt [(k+1)/2] luni cu 31 de zile pentru k<=7 şi
[(k+2)/2]astfel de luni pentru K>7.
Luna februarie are cu o zi mai puţin decât media de 30 în anii bisecţi şi cu 2
zile mai puţin în anii ceilalţi
Programul Pascal
22
Program zile ;
type
luna = 1 .. 12 ;
zi = 1 .. 31 ;
var
a,nr_zi,k:integer;
l:luna;
z:zi;
BEGIN{main}
{citire date in mod conversaţional}
write(‘anul : integer = ’);readln(a);
write(‘luna : 1 .. 12 = ’);readln(l);
write(‘ziua : 1 .. 31 = ’);readln(z);
k:= l-1 ;
nr_zi :=k*30;
if k>0 then
begin
if k<=7 then
nr_zi := nr_zi + ( k – 1 )div 2
else
nr_zi := nr_zi + ( k + 2 )div 2;
if k>=2 then {pt februarie}
if ( a mod 4=0) and ( a mod 100<>0)or (a mod 400=0) then
nr_zi:=nr_zi-1
else
nr_zi:=nr_zi-2;
end;
nr_zi:=nr_zi+z;
writeln(‘Aceasta zi este a ‘,nr_zi:4,’-a zi din anul ’,a);
END.
Introducerea datelor se face în regim conversaţional.Programul solicită
utilizatorului aflat la consolă introducerea datelor una câte una în ordinea corectă ,
indicând pentru fiecare dată şi tipul de valoare aşteptat.
Soluţie 2 :
Se propune încă o soluţie în care lunile sunt recunoscute prin numele
lor:’ian’,’febr’,’mar’, etc.,dar pe mediul de intrare se precizează numărul de ordine
al lunii în an, deoarece nu există procedura standard de citire pentru variabilele de
tip enumerare.Ca atare este necesară o conversie între cele 2 reprezentări.
Pentru fiecare lună anterioară lunii date se adună numărul ei de zile la suma
care dă poziţia datei curente din an.
Pentru a trata unitar lunile s-a introdus o lună falsă “fără nume” astfel ca şi
înaintea lunii ianuarie să fie o lună.
Programul Pascal arată astfel:
Program zile_1;
23
type luna=(fara_nume,ian,febr,mar,
apr,mai,iun,iul,aug,sept,oct,nov,dec);
var
a,nr,nr_zi : integer;
l :1..12;
z :1..31;
i , k :luna ;
BEGIN{main}
write(‘Introduceti an:
integer,luna:1..12,zi:1..31’);
readln(a,l,z);
l:=l-1;
case l of
0 : k := fara_nume;
1 : k := ian;
2 : k := febr;
3 : k := mar;
4 : k := apr;
5 : k := mai;
6 : k := iun;
7 : k := iul;
8 : k := aug;
9 : k := sept;
10 : k := oct;
11 : k := nov;
12: k := dec;
end;
nr_zi:=z;
for i:=ian to k do
nr_zi=nr_zi+28;
case i of
ian,mar,mai,iul,
aug,oct : apr,iun,sept,nov:
nr_zi:=nr_zi+30;
febr : if ((a mod 4=0)and
(a mod 100 <>0)) or
( a mod 400=0 )then
nr_zi:=nr_zi+29
else
nr_zi:=nr_;zi+28;
nr_zi:=nr_zi+31
end;
writeln(‘este a’,nr_zi:4,’-a zi din an’);
END.
24
Algoritmul implementat este mai ineficient decât cel prezentat anterior,dar
pune în evidenţă unele facilităţi Pascal.
Dacă luna curentă este ianuarie,ciclul ”FOR” nu se face niciodată.

IMPLEMENTAREA UNOR ALGORITMI NUMERICI

Să se calculeze valoarea lui PI din următoarea dezvoltare:


luând în considerare n termeni.
a) Descrierea algoritmului în limbaj natural:
Se consideră S valoarea sumeidin dreapta semnului
egal,formată dinînsumarea inverselor numerelor impare cu semne opuse.După
însumarea celor n termeni , valoarea PI se obţine prin înmulţirea lui S cu 4.
b) Descrierea şi semnificaţia structurilor de date folosite:
PI: variabila în care se va calcula valoarea numărului PI
S : variabila în care se păstrează sumele parţiale
T : termenul ce se adaugă
n : numărul de termeni ce se adună
i : contor START
c) Descrierea în Pseudocod a algoritmului:
citeşte n {numărul de termeni} S:=0, T:=+1
T  - T atribuie S0,T+1
pentru i=1,n,1 execută i:=1
atribuie S  S + T*(1 / (2*i-1) )
T -T
[] NU i<=n DA

atribuie PI  4 * S S := S + T*(1 / (2*i-1) )


scrie PI T := - T
stop i:=i+1
Variabila T asigură însumarea corectă
T:=-T
a termenilor cu semne contrare.
d)Programul Pascal Scrie PI
Program calcul_pi;
STOP
var
i,n:integer;
s,pi,t:real;
BEGIN{main}
writeln(‘introduceti valoarea lui
n:intreg’);
readln(n);
s:=0;t:=1;
for i:=1 to n do
begin
s:=s + t / (2 * i - 1);

25
t:= - t ;
end;
pi := 4 * s ;
writeln(‘valoarea lui PI=’,PI:10,8);
END.

Să se scrie un program care,primind un unghi x şi o precizie


EPS>0.Calculează valoarea funcţiei Sin(x) cu o precizie relativă EPS
folosind dezvoltarea în serie
X X3 X5
SIN ( X )     ... xR
1! 3! 5!

a) Descrierea algoritmului în limbaj natural:


Pentru calculul valorii funcţiei sin(x) se impune o precizie EPS>0 şi se
adună atâţia termeni din seria infinită până când ultimul termen adăugat devine în
modul , mai mic decât precizia EPS.Valoarea termenului cu indicele i din tr-o
astfel de serie se calculează în funcţie de valoarea termenului anterior ,aplicând o
relaţie de recurenţă simplă :
T  - T * X2 / ( i ( i – 1 ) )
În rezolvarea problemei este mai convenabil dacă se consideră că EPS indică o
eroare relativă în locul unei erori absolute.De aceea condiţia abs(T) <= EPS trebuie
înlocuită cu abs(T)<= S* EPS,deoarece în acest caz pentru un EPS fixat obţinem
aceeaşi precizie,indiferent de x .
b) Descrierea şi semnificaţia structurilor de date folosite:
x : punctul în care se calculează funcţia
t : termenul curent ce se adună START
s : suma parţială a termenilor Citeste
i : contor x,EPS
EPS : precizia dată pentru calculul funcţiei
c)Descrierea algoritmului în Pseudocod S:=x,
citeşte x,EPS t:=-x
i:=1
atribuie s  x , t  -x , i  1
repetă i :=i+2
atribuie i i+2 t := t * x * x / ( i * ( i – 1 ))
t  t * x * x / ( i * ( i – 1)) s := s + t
ss+t
până abs(t)<=EPS
[]
scrie s DA
abs(t)<=EPS
stop

NU
Scrie s

26STOP
c) Programul Pascal
Program sinus;
const EPS=0.001;
var
i : integer;
x,s,t : real;
BEGIN{main}
write(‘ x = ’); readln(x);
s := x ; t := - x ; i := 1 ;
repeat
i:=i+2;
t:= t * x * x / ( i * ( i – 1 ));
s:=s+t;
until abs(t)<=s*eps;
write(‘Sin(‘,x,’)=’,s);
END.

Se dă ofuncţie f:[a,b] R şi EPS >0.Se cere programul pentru


calculul soluţiei aproximative a funcţiei f cu o precizie mai bună decât
epsilon (EPS) prin metoda înjumătăţirii.
a) Descrierea algoritmului în limbaj natural:
Se ştie că funcţia f are cel puţin o rădăcină în intervalul(a,b),dacă f(a)*f(b)<=0.În
acest caz se va calcula c=(a+b)/2 şi dacă f(a)*f(c)<0 se va înlocui cu c,iar în caz
contrar se înlocuieşte a cu c şi procesul iterativ se continuă până |a-b|<EPS sau
când f(c)=0.
b) Descrierea şi semnificaţia structurilor de date folosite
a,b,c : capetele,respectiv mijlocul intervalului
y1,y2,y: valoarea funcţiei respectiv în a,b,c
EPS : precizia calculului
c) Descrierea algoritmului în Pseudocod
funcţia f(x) este:
atribuie f  x – cos(x)
sfârşit
citeşte a,b,EPS
atribuie y1 f(a), y2  f(b)
dacă y1*y2>=0 atunci
scrie’f(a)şi f(b) au acelaşi semn’
altfel
repetă
atribuie c  (a+b)/2 , y f(c)
dacă y1*y <0 atunci
atribuie b  c , y2  y
27
altfel
dacă y1*y=0 atunci
atribuie ac
altfel
atribuie ac , y1  y
[]
[]
până |a-b| < EPS sau y1*y=0
[]
scrie a
[]
stop
S-a propus spre rezolvare ecuaţia cos x = x , în acest scop s-a definit o
funcţie
f(x)= x – cos x.
S-a notat cu y1 valoarea funcţiei f în punctul a şi y2 = f(b) , y = f(c).
Dacă f(c) = 0,c este rădăcina ecuaţiei.
d)Programul Pascal
program metoda_injumatatirii;
const EPS=0.001;
var a,b,c,y1,y2,y:real;
function f(x:real):real;
begin
f:=x-cos(x);
end;
BEGIN{main}
write(‘a,b ?’);readln(a,b);
y1:=f(a);y2:=f(b);
if y1 * y2 >= 0 then
write(‘f(a) si f(b) au acelasi semn’)
else begin
repeat
c:=( a+b )/2;
y:=f(c);
if y1*y<0 then
begin
b:=c;
y2:=y;
end
else
if y1*y=0 then
a:=c
else
begin
28
b:=c;
1:=y
end;
until (abs(a-b)<EPS)
or (y1*y=0);
write(‘solutia este ‘ ,a);
end;
END.

Metoda Newton poate determina rădăcini de ordinul ”p” dintr-o


valoare ”a”, foloseşte şirul cu termenul
general

convergent spre .Eroarea absolută (EPS) se poate folosi pentru


oprirea evaluării elementului din şir.
Să se scrie programul care primind de pe mediul de intrare P,A,EPS şi x0
calculează rădăcina aproximativă de ordinul p din A
a) Descrierea algoritmului în limbaj natural
Notăm cu x aproximarea (i-1)şi cu y aproximarea curentă ( calculată ) i , deci
termenul general cu aceste notaţii devine :

Se va porni cu x = x0 dat,diferit de zero.Oprirea calculelor se va face când


diferenţa în modul dintre două aproximări consecutive este mai mică decât EPS.
Dat.Atâta timp cât
diferenţa în modul dintre START
două aproximări
succesive este mai mare Citeste
p,a,EPS,x0,n_max
decât EPS se va atribui
lui x valoarea y calculată
b) Descrierea şi x x0, i1 ,
y  1 / p ( ( p – 1 ) x + a / xp-1)
semnificaţia
structurilor de date
folosite:
a : valoarea din care |y-x|>=EPS
se extrage radicalul i<=n_max
p : ordinul
radicalului xy,
y  1 / p ( ( p – 1 ) x + a / xp-1),
x0 : aproximarea Scrie y,i i  i+1
iniţială:
EPS : aproximarea
calculului STOP

29
X,y : doi termeni consecutivi ai aproximării
N_max : numărulmaxim de iteraţii
c) Descrierea algoritmului în Pseudocod:
citeşte p,a,EPS,x0,n_max
atribuie x x0, i1 , y  1 / p ( ( p – 1 ) x + a / xp-1)
cât timp |y-x|>=EPS şi i<=n_max execută
atribuie x  y ,
y  1 / p ( ( p – 1 ) x + a / xp-1),
i  i+1
[]
scrie y,i
stop
Obs1. Valoarea lui x0 trrebuie să fie diferită de zero.Dacă dupăn_max
iteraţii nu s-a atins precizia EPS impusă,procesul de calcul se întrerupe tipărindu-se
aproximarea rădăcinii şi numărul de iteraţii
Obs2.Pentru calculul ridicării la o putere AB se folosesc funcţiile EXP şi LN
astfel că AB = EXP ( B * LN( A ))
d)Programul Pascal
Program radical_p;
var
n_max ,i,p : integer;
EPS,x0,a,x,y: real;
BEGIN{MAIN}
write(‘valoarea x0:integer;valoarea
EPS:real;valoarea :real;
n_max:integer ?’);
readln(x0,EPS,n_max);
i:=0;x:=x0;
y:=((p-1)*x+a/EXP((p-1)*LN(x)))/p;
while (abs(y-x)>=EPS)and
(i<=n_max)do
begin
x:=y;
y:= ((p-1)*x+a/EXP((p- 1)*LN(x)))/p;
i:=i+1;
end;
writeln(‘val. Radicalului =’,y:10:4,’
după’i:3,’iteraţii’);
END.

30
IMPLEMENTAREA ALGORITMILOR RECURSIVI

Să se calculeze coeficienţi binomiali în care n şi p sunt întregi pozitivi daţi


( p <= n ), ştiind că există următoarea relaţie de recurenţă :

Descrierea algoritmului în limbaj natural:


Se aplică relaţia de recurenţă pentru calculul coeficienţilor .Valorile
calculate se vor afişa pe măsura calculării lor , ele fiind păstrate pe rând în aceeaşi
variabilă C.
Descrierea şi semnificaţia structurilor de date folosite
n , p : valorile înteregi pentru care se calculează combinaţiile
k : contor întreg
c : valoarea în care se calculează ,pe rând, combinările
Descrierea algoritmului în Pseudocod
citeşte n , p
scrie n,p
atribuie c 1
pentru k=1,p,1 execută
atribuie c c* (( n – k + 1 ) / k)
[]
scrie c
stop
Programul Pascal
Program comb;
var n,p,k,c:integer;
BEGIN{main}
write (‘n,p ?’) readln(n,p);
c:=1;
for k:=1 to p do
begin
c:=c*(n-k+1)div k;
writeln(‘combinari
de’,n,’luate
cate’,k,’=’,c);
end;
END.

Să se calculeze pentru un n dat , toţi termenii şirului lui Fibonacci,


cunoscând relaţia de recurenţă f k = f k-1+ f k-2 , pentru orice k >= 2 şi f0
=0, f1 = 1
a) Descrierea algoritmului în limbaj natural
31
Relaţia de recurenţă necesită două valori iniţiale f0 şi f . Această relaţie va fi
aplicată de n-2 ori , actualizând de fiecare dată pe f k-2 şi f k-1.Deci pentru calculul
termenului curent f k sunt suficienţi 2 termeni consecutivi din şir. Vom nota cu “a”
termenul f k-2 ,cu “b” f k-1 şi cu “c” termenul f k calculat.
b.) Descrierea şi semnificaţia structurilor de date folosite:
a, b, c : întregi în care se calculează, pe rând termenii şirului Fibonacii
n : indicele maxim al termenului ce se calculează
k : contor START
c.) Descrierea algoritmului în pseudocod:
citeşte n Citeste n
scrie n
Scrie n Scrie a,b
{iniţializează primi 2 termeni ai şirului}
atribuie a 0, b 1 a:=0, b:=1
scrie a,b {primi doi termeni}
k:=3
pentru k=3, n, 1 execută
atribuie c a+b {calculează termenul curent}
a b {actualizarea ultimilor doi}NU DA
k<=n
b c {termeni din şir}
Scrie c c:=a+b
scrie c a:=b , b:=c
stop
STOP
d.) Programul PASCAL:
program fibonacii;
var
a,b,c,k,n:integer;
BEGIN{main}
write('Introduceti nr. de
termeni:');
readln(n);
a:=0; b:=1;
write(a:3);
for k:=3 to n do
begin
c:=a+b;
a:=b; b:=c;
write(c:3)
end;
END.

Să se calculeze c.m.m.d.c. şi c.m.m.m.c a două numere întregi


aplicând algoritmul lui Euclid.
a.) Descrierea algoritmului în limbaj natural:
Se ştie că c.m.m.m.c a două numere A şi B este egal cu raportul dintre
produsul celor două numere şi c.m.m.d.c. al celor două numere. Ca atare în
variabila p se va reţine produsul celor două numere. Variabila CMMMC va reţine
32
c.m.m.m.c, iar variabila CMMDC va reţine c.m.m.d.c. Conform algoritmului lui
Euclid de aflare a c.m.m.d.c se împarte cel mai mare număr (A) la cel mai mic (B)
şi se calculează restul împărţirii întregi (R). Dacă restul împărţiirii este 0 atunci
c.m.m.d.c. este B. În caz contrar se fac atribuirile: lui A i se atribuie B iar lui B i se
atribuie R şi procesul se continuă până R=0.
Dacă la introducerea datelor B>A, se schimbă între ele cele două valori.
Dacă cel mai mic număr este 0 se va tipări mesajul ‘unul dintre numere este
0’ şi nu se va calcula c.m.m.m.c.
Pentru calculul restului împărţirii se va folosi operatorul PASCAL ,,mod”.
b.) Descrierea şi semnificaţia structurilor de date folosite:
A,B : cele două numere întregi
CMMDC, CMMMC : variabile întregi pentru calculul c.m.m.d.c. şi
c.m.m.m.c.
P : produsul celor două numere (pentru calculul c.m.m.m.c.)
X : variabilă auxiliară
START

Citeste
a,b
p := a * b

a<b

x := a ,a := b
b := x

NU DA
b<>0

r:= a mod b

r<>0

a :=b, b := r
r := a mod b

cmmdc := b
cmmmc := p / b

cmmmc,cmmd
Scrie c
‘unul din termeni este
0’

STOP
33
c)Descrierea şi semnificaţia structurilor de date folosite
a,b : cele două numere întregi
cmmdc,cmmmc : variabile xîntregi pt.calculul cmmdc şi cmmmc
p : produsul celor două numere ( pentru calculul cmmmc)
x : variabilă auxiliară
d)Descrierea algoritmului în Pseudocod
citeşte a,b
atribuie p  a * b { reţine produsul numerelor }
dacă a<b atunci
atribuie x  a {schimbă cele două valori între ele}
ab
bx
[]
dacă b<>0 atunci
atribuie r a mod b {restul împărţirii întregi }
cât timp r<>0 execută
atribuie a b {pregăteşte o nouă reluare
a algoritmului }
br
r  a mod b
[]
atribuie cmmdc  b
cmmmc  p / b
scrie cmmmc,cmmdc
altfel
scrie ‘ unul din termeni este zero’
[]
stop
c)Programul Pascal
Program Euclid;
var a,b,x,p,r,cmmdc,cmmmc:integer;
BEGIN{main}
write(‘introduceţi a si b : integer’);
readln(a,b);
p:=a*b;
if a<b then
begin
x:=a;
a:=b;
b:=x;
end;
if b<>0 then
begin
r:=a mod b;
34
while r<>0 do
begin
a:=b
b:=r;
r:=a mod b;
end;
cmmdc:=b;
cmmmc:=p div b;
writeln(‘cmmdc=’,cmmdc:8,
’cmmmc=’,cmmmc:9);
end
else writeln(‘unul din termeni este
zero’);
END.

Dându-se un număr întreg N, să se afişeze toţi factorii primi ai


acestuia precum şi ordinele lor de multiplicitate.
a) Descrierea algoritmului în limbaj natural:
O soluţie posibilă ar fi aceea de a alege dintre numerele 2,3,4,5...d...[n/2] pe
acelea care sunt numere prime urmând a fi “extrase” din numărul n.Ordinul de
multiplicare al fiecărui factor prim d va fi egal cu numărul de împărţiri cu rest nul
care se pot face succesiv cu el.Pentru a verifica că d este număr prim trebuie
cercetată divizibilitatea sa cu 2,3,4,...[sqrt(d)],ceea ce presupune un număr mare de
împărţiri.O serie de observaţii ce se vor face va conduce la reducerea numărului de
calcule.Dintre toate numerele pare, singurul număr prim este 2.Deci este suficient
să căutăm factorii primi numai printre 2 şi numerele impare ce satisfac condiţia
2k+1<=[n/2] (partea întreagă din n/2).
Dacă se scot din “n” divizorii săi în ordine crescătoare, un număr neprim nu
va fi găsit divizor al lui n, deoarece proprii săi factori primi au fost eliminaţi din n.
De exemplu un număr nu se mai divide cu 25 după ce toţi divizorii 5 au fost
eliminaţi. Deci nu este necesar să se verifice dacă un număr este prim. Algoritmul
ne asigură că dacă un număr este divizor al lui n atunci acesta este un divizor prim.
Căutarea divizorilor este o operaţie care se repetă ciclic necunoscându-se
aprioric numărul de repatări. Operaţia continuă până numărul mai admite divizori
(n>1). Dacă n=1, el nu admite divizori, deci ciclul nu se va efectua niciodată (se va
folosi ciclu cu test iniţial).
Întrucât valoarea lui n se modifică prin extragerea divizorilor,este necesară
afişarea sa înaintea începerii procesului de căutare a acestora.
b) Descrierea şi semnificaţia structurilor de date folosite
n : numărul ce se descompune
d : divizorul (potenţial )
m : ordinul de multiplicare
c) Descrierea algoritmului în Pseudocod
O primă formă arată astfel:
35
citeşte n
scrie n
atribuie d 2
cât timp *n mai admite divizori execută
* determină multiplicitatea eventualului divizor şi extrage d din n
dacă *d a fost divizor atunci
afişează d şi ordinul de multiplicare
[]
trecere la următorul d
[]
stop
Acţiunea “*determină multiplicitatea eventualului divizor d şi îl extrage pe d
din n” are un caracter ciclic, necunoscându-se numărul de repetări ale
ciclului.Această acţiune se poate realiza în Pseudocod astfel:
atribuie m  0 {ordinul de multiplicitate}
cât timp *n estedivizibil cu d execută
*extrage d din n
atribuie m  m+1
[]
Deoarece divizorii se caută printre numerele 2,3,5,7.... acţiunea”*trecere la
următorul d” se realizează în Pseudocod astfel :
dacă d=2 atunci
atribuie d  3
altfel
atribuie d  d + 2
[]
Acţiunea “* îl extrage pe d in n” se cere realizează astfel:
atribuie n  n div d
Pentru valaorea maximă a lui d nu trebuiesc impuse condiţii , d va căpăta noi
valori atât timp cât n mai admite divizori.El nu va putea avea o valoare mai mare
decât [ n / 2 ].
Având în vedere faptul că un număr n este prim dacă nu se divide cu
2,3,4,...[sqrt(n)] algoritmul poate fi inductabil. Deci, trebuie căutaţi divizori ai lui n
până la [sqrt(n)] şi nu până la [n/2]. În final n va conţine iltimul divizor prim (cel
mai mare) dacă acesta are multiplicitatea 1. În caz contrar, n va fi 1. Algoritmul
trebuie să facă distincţie între cele 2 situaţii.
Deoarece funcţia sqrt(n) oferă un rezultat de tip real, care poate fi afectat de
erorile interne operării cu numere reale, de exemplu sqrt(16) are valoarea
3,99999E+00, iar trunc(sqrt(16))=3, va trebui introdusă corecţia sqrt(n+0.5), pentru
ca algoritmul să lucreze corect.

36
Cu aceste observaţii algoritmul rafinat arată astfel:
citeşte n START
atribuie d  2
cât timp d<=(sqrt(n+0.5)) execută Citeste n
atribuie m0
cât timp n mod d =0 execută
d := 2
atribuie n  n div d
mm+1 DA
d<=(sqrt(n+0.5))
[]
dacă m>0 atunci m:=0
scrie d , m
[] n mod d :=0
dacă d = 2 atunci
atribuie d  3 n :=n divd
altfel m := m + 1
NU
atribuie d  d + 2 NU DA
m>0
[]
[] Scrie d,m
dacă n > 1 atunci
scrie n NU DA
d: = 2
[] n>1
stop d := 3 d:= d + 2

Scrie n

STOP
d)Programul Pascal
Program divizorii ;{descompunere în factori primi}
var n,d,m:integer;
BEGIN{main}
write (‘introduceti n:integer’);
readln(n);
writeln(n:4,’are urmatorii factori primi’);
writeln(‘factor’,’‘:5,’multiplicitate’);
d:=2;{cel mai mic numar prim}
while d<= trunc(sqrt(n+0.5)) do
begin
m:=0;
while(n mod d)= 0 do
begin
n:=n div d;
m:=m+1;
end;
37
if m>0 then
writeln(d:5,’ ‘:9,m:2);
if d = 2 then d:=3
else d:=d+2;
end;
if n>1 then writeln(n:5,’ ‘:10,’1’);
END.
Observaţie: S-a folosit indicarea de formă la afişarea unui şir de forma’ ‘:9,
care are ca efect lăsarea a 9 spaţii libere. Afişarea, de exemplu de 5 ori a
caracterului “a” nu se poate realiza prin “a”:5 ci prin instrucţiunile:
for i:=1 to 5 do write(‘a’);
În primul caz se va afişa un caracter a precedat de 4 spaţii libere.

Să se verifice dacă un număr întreg citit de pe mediul de intrare este


palindrom, adică se citeşte la fel de la stânga la dreapta şi de la dreapta la
stânga. Un astfel de număr este 4315134. Nu se vor folosi tablouri de
variabile pentru START
păstrarea cifrelor
numărului. Citeste n
a) Descrierea
algoritmului în
limbaj natural NU
putere=1
DA
Se repetă
compararea între Scrie este palindrom’
cea mai p:=n div putere
q:=nmod putere
semnificativă şi n:=n mod mare
cea mai puţin n:=ndiv10
semnificativă cifră putere:=putere div 10
a numărului,fie
până cele două (p<>q) sau
cifre diferă,fie (putere=10)
până s-a efectuat
numărul suficient
NU DA
de comparaţii. În p:=q
primul caz
numărul nu este scrie‘nu este palindrom’ scrie‘este palindrom’
palindrom. Cele
două cifre
simetrice ce sunt
egale se vor
elimina din număr
STOP
astfel că ne vom

38
referi la următoarele cifre din poziţiile simetrice prin cea mai semnificativă şi cea
mai puţin semnificativă cifră.
b) Descrierea şi semnificaţia structurilor de date folosite
n : numărul ce se verifică
p , q : cifrele cmps şi cms ale numărului
putere: întreg în care se calculează 10L-1
r : variabilă auxiliară
L : lungimea numărului
c) Descrierea în Pseudocod
O primă formulare a algoritmului este:
Citeşte n
Stabileşte lungimea L a numărului
Dacă L=1 atunci
Scrie ‘este palindrom’
Altfel
Repetă
Atribuie p c.m.s. cifră din n
q c.m.p.s cifră din n
suprimă c.m.s. şi c.m.p.s. cifră din n
atribuie L L-2
până p<>q sau L<2
[]
dacă p=q atunci
scrie ‘este palindrom’
altfel
scrie ‘nu este palindrom’
[]
[]
stop
Acţiunile de mai sus se pot rafina prin
- ‚atribuie q c.m.p.s. cifră din n’: atribuie q n mod 10
- ,atribuie p c.m.s. cifră din n’ : atribuie p n div 10
- ,suprimă c.m.p.s. şi c.m.s. cifră din n’ prin:
atribuie n n div 10
atribuie n n div 10L-1
Deoarece în Pascal nu există operator de ridicare la putere, se va înlocui în
algoritm L prin putere =10L-1.
Noua descriere în pseudocod devine:
Citeşte n
Determină putere=10l-1 {L fiind lungimea numărului}
Dacă putere=1 atunci
Scrie ‘este palindrom’
Altfel
Repetă
39
Atribuie p n div putere {separă c.m.s. cifră}
q n mod putere {separă c.m.p.s. cifră}
n n mod mare {suprimă c.m.s. cifră}
n n div 10 {suprimă c.m.p.s. cifră}
putere putere div 10
până (p<>q) sau (putere=10)
[]
dacă p=q atunci
scrie ‘este palindrom’
altfel
scrie ‘nu este palindrom’
[]
[]
stop
Acţiunea ,,determină putere =10L-1” se rafinează astfel:
Atribuie R n
Putere 1
Cât timp R>10 execută
Atribuie putere putere*10
R R div 10
d)Programul Pascal
Program pai;
type cifra= 0..9;
var
n,r,putere : integer;
p,q: cifra;
BEGIN{main}
write(‘n=’);readln(n);
r:=n;putere:=1;
while r>=10 do
begin
putere := 10 * putere;
r := r div 10;
end;
if putere = 1 then write(‘este ’)
else
begin
repeat
p := n div putere;
q := n mod 10;
n := n mod putere;
n := n div 10;
putere := putere div 100
until(p<>q)or(putere<10);
40
if p = q then write (‘este’)
else
write(‘nu este’);
end;
write(‘ palindrom’);
END.

Să se tabeleze funcţia:

în intervalul [0,10] cu pasul ,,delta_x”=0.15.

a.) Descrierea algoritmului în limbaj natural


Pentru valori ale variabilei x cuprinse între 0 şi 10 cu pasul ,,delta_x”
calculează valoarea funcţiei în funcţie de domeniul de definiţie al funcţiei.
b.) Descrierea şi semnificaţia structurilor de date folosite:
x : punctul în care se calculează valoarea funcţiei START
f : valoarea funcţiei în punctul x
Dx : pasul de calcul Citeste delta x
c.) Descrierea algoritmului în pseudocod
citeşte delta_x
atribuie x 0 x:=0
cât timp (x>=0) şi (x<=10) execută
dacă x<1 atunci NU (x>=0) şi DA
(x<=10)
atribuie f ex-2
altfel NU DA
x<1
dacă x<2 atunci STOP
atribuie f sinx+cosx
f:=ex-2
altfel x<2
atribuie f 0.5*ln(x+1)
[]
[] f:=0.5*ln(x+1) f:=sinx+cosx
scrie x, f
atribuie x x+delta_x scrie x, f
[]
stop x:=x+delta_x
d.) Programul PASCAL:
program functie;
var
x,f,Dx:real;
BEGIN{main}
read(Dx);
writeln('x',' ':10,'F(x)');

41
x:=0;{valoarea limita inferioara}
while (x>=0) and (x<=10) do
begin
if x<1 then
f:=EXP(x-2)
else if x<2 then
f:=sin(x)+cos(x)
else
f:=0.5*LN(x+1);
writeln(x:2:2,' ':4,F:8:2);
x:=x+Dx
end;
end.

ALGORITMI PENTRU ŞIRURI NUMERICE

Fiind dat şirul de numere reale x1, x2,…, xn ş.a să se afle cel mai
mare element al şirului precum şi rangul sau (poziţia sa în şir). Dacă există
mai multe elemente în şir care ar avea valoarea maximă, se va reţin e
rangul primului maxim întâlnit de la stânga la dreapta.
a)Descrierea algoritmului în limbaj natural:
Fie CMAX variabila unde se va păstra valoarea maximă şi IR variabila în
care se va reţine
rangul primului START
maxim. Variabila I
numără (selecteză) Citeste n
elementele şirului.
Pentru început se i:=1
consideră că cel
mare element este NU
i:=i+1
DA
primul element al
şirului şi poziţia CMAX X1 , IR1 Citeste x[i]
sa este unică i:=i+1
(atribuie CMAX i:=2
 x1,IR1).
Valoarea lui i<=n
CMAX şi a lui IR DA
NU CMAX <Xi
se schimbă în
cazul în care Y > Scrie CMAX, IR CMAX :=Xi,
xI, adică atunci IR:=1
când elementul
analizat (xi) este STOP i:=i+1

42
mai mare decât valoarea lui CMAX, caz în care se realizează: atribuie YXI,
IRI
Procesul de căutare a maximului şi a rangului se termină după analiza
ultimului element al şirului.
b)Descrierea şi semnificaţia structurilor de date folosite:
x: tabloul de numere reale (maxim 25)
n: dimensiunea efectivă a tabloului
CMAX, IR: elementul maxim şi poziţia sa
i: contor(întreg)
c)Descrierea algoritmului în Pseudocod :
citeşte n
pentru i=1,n,1 execută
citeşte xi
[]
atribuie CMAX X1 , IR1
pentru i=2,n,1 execută
dacă CMAX <Xi atunci
atribuie CMAX Xi, IR1
[]
[]
scrie CMAX, IR
stop
d)Programul în Pascal:
Program MAXIM_RANG;
Const Nmax = 25;
Var x : array [1..Nmax] of real;
I : 1..Nmax;
IR,N : integer;
CMAX: real;
BEGIN
Write(‘numarul de elemente’);
readln(n);
For i: = 1 to n do
Begin
Writeln(‘x[‘,i,’]=’);
readln(x[i]);
end;
CMAX : = x[1];
IR: = 1;
For i: = 2 to n do
If CMAX < x[i] then
begin
CMAX : = x[i];
IR: = i;
43
end;
Writeln(‘cel mai mare element este’, CMAX);
Writeln(‘pozitia sa este:’,IR);
End.

Fie şirul x1,x2,…,xn de elemente întregi. Să se afle cel mai mare


element al şirului şi toate poziţiile în care apare.
a)Descrierea algoritmului în limbaj natural
Se va aplica algoritmul de la problema precedentă completat cu reţinerea
poziţiilor din şir ale ale elementului maxim. Se consideră şirul IR în care se vor
reţine poziţile elementelor de valoare maximă. Indicele acestui şir se consideră j.
b)Descrierea şi semnificaţia structurilor de date folosite:
x: tabloul de numere reale (maxim 25)
n : dimensiunea efectivă a tabloului
CMAX, IR: elementul maxim şi poziţia sa
IR : tablou în care se memorează toate apariţiile maximului
i : contor(întreg)
c)Descrierea algoritmului în Pseudocod :
citeşte n
pentru i=1,n,1 execută
citeşte xi
[]
atribuie CMAX X1
pentru i=1,n,1 execută
dacă CMAX <Xi atunci
atribuie CMAX Xi
[]
[]
atribuie j 0
pentru i=1,n,1 execută
dacă CMAX =Xi atunci
atribuie j j+1, IRj i
[]
[]
scrie CMAX
pentru i=1,j,1 execută
scrie IRi
[]

Să se ordoneze crescător şirul de numere reale: x1,x2,…,xn


Sortare prin selecţie
a)Descrierea algoritmului în limbaj natural:

44
Se calculează cel mai mic dintre elementele şirului, numit MIN=min(x1,x2,…,xn)
şi-l plasăm în locul elementului x1, pe acesta ducându-l în locul unde s-a aflat cel
mai mic dintre elementele şirului.
Se obţine şirul: x1’,x2’,…,xn’
Se calculează: MIN = min(x1’,x2’,…,xn’)
şi se plasează în locul elementului x2’, iar pe acesta îl depunem în locul unde s-a
aflat cel mai mic dintre elementele şirului, obţinând şirul: x1’’,x2’’,…,xn’’
Se continuă raţionamentul până când şirul pe care îl analizăm are două
elemente, moment în care procesul de ordonare crescătoare s-a terminat.
Algoritmul de ordonare conform acestei metode:
- se execută n-1 paşi, cu j = 1,2,3,…,n-1
- la fiecare pas k:
- se determină poziţia j a elementului cel mai mic dintre elementele xi,
xi+1, ,xn
- se schimbă între ele valorile lui xi şi xj
Deci la fiecare pas se “selecteză” cel mai mic element dintre xi, xi+1,…,xn ,
motiv pentru care metoda se numeşte “sortare prin selecţie”.
b)Descrierea şi semnificaţia structurilor de date folosite:
x: tabloul ce se ordonează
n: dimensiunea efectivă a tabloului
temp: variabila de lucru(auxiliara)
i,j: contoare
k: poziţia elementului minim (relativ)
c)Descrierea algoritmului în Pseudocod:
citeşte n, (xi, j-1,n)
pentru i=1,n-1,1 execută
atribuie k i
pentru i=i+1,n,1 execută
dacă xk>xj atunci
atribuie k j
[]
[]
atribuie tempx
xkxi
xitemp
[]
scrie xi,i-1,n
stop
Soluţia 2 (“metoda prin interschimbare”)
a)Descrierea algoritmului în limbaj natural:
Se inspecteză perechi de elemente adiacente din şirul x, adică xI şi xi+1 pentru
i=1,n-1. Dacă xi<=xi+1 le lăsăm nemodificate, iar dacă xI>xi+1 atunci inversăm cele
2 valori.

45
Dacă se ajunge la capăt şi şirul nu este ordonat trebuie să se reia parcurgerea
şi inversarea până când şirul devine ordonat. De aceea se va lua o variabilă k care
va lua valoarea 1 ori de câte ori se inversează două elemente din şir. Iniţial
variabila k are valoarea zero. Procesul continuă până ce “indicatorul” k NU se mai
modifică.
b)Descrierea şi semnificaţia structurilor de date folosite:
x :tabloul ce se ordonează
n :dimensiunea efectivă a tabloului
temp:variabila de lucru(auxiliara)
i,j :contoare
k :indicator(flag)
c)Descrierea algoritmului în Pseudocod:
O primă variantă ar putea fi:
citeşte n
 citeşte şirul x
 ordonează şirul x
 scrie şirul ordonat
stop
Operaţia “citeşte şirul x” implică citirea pe rând a fiecărui element din şir
pentru i=1,n,1 execută
citeşte x(i)
[]
Operaţia “ordonează şirul” poate fi detaliată
repetă
parcurgere şir
până şir ordonat
[]
Pentru condiţia “şir ordonat” se foloseşte o variabilă ”ORDONAT” cu valori
logice sau o variabilă întreagă “k” ce pot lua valorile:
Şir ordonat : ORDONAT = adevărat: k=0
Şir neordonat: ORDONAT = fals :k=1
În aceste condiţii “ordonează şir” devine :
repetă
atribuie ORDONATadevarat {k0}
parcurgere şir şi actualizează ORDONAT {K}
până ORDONAT {k=0}
[]
Operaţia “parcurge şir” constă în compararea succesivă a tuturor perechilor
de valori alăturate x(i) şi x(i+1). Deoarece sunt n-1 perechi operaţia se poate
detalia astfel:
pentru i=1,n-1,1 execută
compară x(i) cu x(i+1)
[]

46
Operaţia de interschimbare necesită 3 atribuiri:
atribuie tempx(i)
atribuie x(i)x(i+1)
atribuie x(i+1)x(i)
Astfel încât “compară x(i) cu x(i+1)” devine:
dacă x(i)>x(i+1) atunci
atribuie tempx(i)
x(i)x(i+1)
x(i+1)x(i)
atribuie ORDONATfals {k1}
[]
Operaţia “scrie şir ordonat” implică scrierea pe rând a tuturor elementelor
şirului, adică:
pentru i=1,n,1 execută
scrie x(i)
[]
Cu acestea algoritmul arată astfel:
citeşte n, (xi, i=1,n)
repetă
atribuie k0
pentru i=1,n-1,1 execută
dacă xi > xi+1 execută
atribuie tempxi
xixi+1
xi+1temp
atribuie k1
până k=0 []
[]
scrie xi, i=1,n
STOP

Pe o cartrelă de date se află descris un circuit format din rezistenţe


conectate şi/sau paralel astfel:
- dacă circuitul este format dintr-o singură rezistenţă, el este descris prin
litera “R”;
- dacă circuitul este format prin legarea în serie a două circuite atunci este
descris întâi C1, apoi C2, apoi se pune litera “S”;
- dacă circuitul este format din legarea în paralel a două circuite C1 şi C2,
atunci este descris întâi C1, apoi C2, apoi se pune litera “P”.
Circuitul: R1 R2 R3

R4 R5 R8 R9

47
R6 R7

Este descris de cartela următoare:


RRSRSRRSPRRSPRSRS
Pe următoarea cartelă se dau valorile rezistenţelor care participă la circuit, în
ordinea în care au apărut pe prima cartelă (R1,R2,…,R9). Să se scrie un program
care, citind descrierea circuitului şi valorile rezistenţelor, calculează rezistenţa
echivalentă.
a)Descrierea algoritmului în limbaj natural:
Conţinutul descrierii circuitului (prima cartelă) se memorează în tabloul de
caractere CART. Se presupune că descrierea circuitului se încheie la apariţia
primului blanc. Numărul de caractere din descriere este reţinut de variabila LCAR.
Numărul de rezistenţe din circuit este dat de variabila NREZ. Tabloul REZ
conţine valorile rezistenţelor.
Dacă primul caracter din tabloul CART este diferit de R, circuitul este
descris greşit.
Pentru calcularea rezistenţei echivalente se va folosii o stivă (tablou de
elemente reale). Indicele stivei este Istiva.
Când caracterul curent din CART este “S” se calculează rezistenţa
echivalentă (suma) ultimelor două elemente introduse în stivă, cu depunerea
rezultatului în locul primului din cele 2 valori adunate, modificând corespunzător
Istiva, adică:
STIVA[istiva-1]: =STIVA[istiva] + STIVA[istiva-1]
istiva: = istiva-1
Dacă CART[j] este “P” se calculează rezistenţa echivalentă paralel, folosind
relaţiile:
STIVA[istiva-1]:=STIVA[istiva-1]*STIVA[istiva]/(STIVA[istiva-1]* STIVA[istiva]);
istiva: = istiva-1;
Rezistenţa echivalentă a circuitului se va afla în prima poziţie a stivei (baza
stivei), adică STIVA[1]. Mărimea IR reprezintă numărul rezistenţei.
b)Descrierea şi semnificaţia structurilor de date folosite:
CART: tablou de caractere în care se introduce descrierea circuitului (cea citită)
Lcar : numărul de caractere citite
car : variabila de tip caracter prin intermediul căreia se citesc datele de intrare
Stiva : tablou în care se păstrează datele şi rezultatele parţiale; simulează
comportarea unei stive
Istiva : indicator în tabloul Stiva (indicatorul stivei)
Rez : tablou în care se păstrează valorile rezistenţelor
Nrez : numărul rezistenţelor
IR : indicator în tabloul Rez; indică rezistenţa curentă
c)Descrierea algoritmului în Pseudocod:
citeşte car
atribuie i0, j0
48
cât timp car<> ‘ ‘ execută
atribuie jj+1, CART[j]car
dacă car =’R’ atunci
atribuie ii+1
[]
citeşte car
[]
atribuie Lcarj, Nrezi
pentru i=1,Nrez,1 execută
citeşte Rez(i)
[]
dacă CART [i] = ‘R’ atunci
atribuie STIVA[1]Rez[1]
Istiva1
Ir1
pentru j=2,Lcar,1 execută
alege Cart[j] dintre
‘R’: atribuie IRIR+1, Istiva Istiva+1
STIVA[Istiva]Rez[Ir]
‘S’: atribuie STIVA[istiva-1] STIVA[istiva] +
STIVA[istiva-1]
Istiva Istiva-1;
‘P’: atribuie STIVA[istiva-1] STIVA[istiva] *
STIVA[istiva-1] / (STIVA[istiva-1] +STIVA[istiva])
atribuie Istiva Istiva-1;
[]
[]
scrie Stiva[1]
altfel
scrie ’circuitul nu este descris corect’
[]
stop

Se dau două şiruri de numere întregi A şi B cu n A , respectiv nB


elemente care reprezintă 2 mulţimi de numere. Să se scrie un program
care, pornind de la cele 2 şiruri, constituie un sir D care conţine
elementele din mulţimea A U B (şirul D conţine elementele şirului A şi ale
şirului B, elementele comune şirurilor A şi B, se vor lua o singură dată).
a) Descrierea algoritmului în limbaj pseudocod
Se introduce în şirul D unul din cele două şiruri (ex. şirul A) după care se ia
câte un element din celălalt şir (şirul B)şi se verifică dacă se află deja în şirul D
(adică în şirul A). Operaţia se continuă până se ajunge la ultimul element al celui

49
de-al doilea şir B. Dacă elementul comparat nu se află în şir, el se va adăuga şirului
D.
b) Descrierea şi semnificaţia structurilor de date folosite:
a, b: şirurile iniţiale
na, nb: dimensiunile efective ale celor două şiruri
d: şirul rezultat (reuniunea celor două şiruri)
i, j :contoare
k: indicator (flag):=1:condiţie îndeplinită
=0 :condiţie neândeplinită
c) Descrierea algoritmului în pseudocod:
citeşte nA, (ai,i=1,nA)
citeşte nB, (bi, I=nB)
pentru i=1,n, 1 execută
atribuie di ai
[]
atribuie nd na
pentru i=nb, 1 execută
atribuie k 0
pentru j=1,n , 1 execută START
dacă dj = bi atunci
atribuie k 1 Citeste nA si nB
dacă k=0 atunci
atribuie nd nd+1 i:=1
d b
nd  I NU DA
i<=n1
[]
nd:=na di:= ai
[]
i:=iI+1
scrie nd, (di , I=1,nd)
stop i:=nb

i >0

Scrie nd k:=0

STOP j:=1

j<=n

NU dj = bi DA

i:=i-1
k:=1

50 NU k=0 DA

nd:=nd+1
d:=b
j:=j+1 nd := I
Variabila k devine egală cu I dacă elementului bi se găseşte în şirul D. Dacă
k=0, se va adăuga elementul bi şirului D, mărindu-se dimensiunea tabloului D.
În final se scrie numărul de elemente al şirului D şi elementele acestuia.
a)Programul Pascal este:
Program reuniune;
const nmax=20;
var
i,j,k:integer;
na,nb,nd:integer;
a,b,d:array[10..nmax]of integer;
BEGIN {citirea tablourilor}
write('introduceti na si nb');
readln(na,nb);
write('Introduceti elementele sirului a');
for i:=1 to na do read(a[i]);
write('Introduceti elementele sirului b');
for i:=1 to nb do read(b[i]); {introducerea sirului a in sirul d}
for i:=1 to na do d[i]:=a[i];
nd:=na; {testarea si introducerea daca este cazul a elementelor lui b in d}
for i:=1 to nb do
begin
k:=0;
for j:=1 to nd do
if d[j]=b[i] then k:=1; {elementulo bi se afla in sirul d}
if k=0 then
begin
nd:=nd+1;
d[nd]:=b[i] {adauga un nou element sirului d}
end;
end;
writeln('Sirul D are nd=',nd:4,' termeni');
writeln('elementele sirului D sunt:');
for i:=1 to nd do
write(d[i],' ');
END.

51
N copii identificaţi prin numerele 1,2,…,N, joacă următorul joc: se
aşează într-un cerc în ordinea 1,2,…N şi începând de la copilul K, numără
de la 1 la N, eliminând din cerc pe cel care a fost numărat N, eliminând din
cerc pe cel care a fost numărat N, ş.a.m.d. Folosind identificarea iniţială, să
se stabilească ordinea de ieşire a copiilor din joc.
a) Descrierea algoritmului în limbaj natural:
Într-un vector x se vor introduce numerele de ordine 1,2,…N, ale copiilor,
printr-o acţiune de forma:
Pentru i=1,n,1 execută
Atribuie ai i
Să se identifice poziţia copilului care trebuie să părăsească jocul, tipărindu-se
poziţia sa iniţială. Apoi se reface şirul x deplasându-se cu o poziţie la stânga toţi
copii din dreapta celui care a ieşit. Noul şir va avea cu o componentă mai puţin
(atribuie n n-1) după care procesul continuă la fel. Procesul se termină când a
ieşit din joc ultimul copil.
b) Descrierea şi semnificaţia structurilor de date folosite :
x: tablou în care se introduc copii
n: numărul de copii
k, n : caracteristicile jocului
s: numărul de ordine al copilului care”iese” din joc
c.) Descrierea algoritmului în pseudocod:
citeşte n {numărul de copii}
citeşte k,m
pentru i=1,n,1 execută {identifică copiii}
atribuie xi i
scrie xI
[]
atribuie S 0 {dă ordinea de ieşire din joc}
repetă
atribuie k (k-1+m) mod n
{selecteză poziţia copilului în şir}
atribuie S S+1
dacă k<>0 atunci
{este un copil din interiorul şirului}
scrie ‘copilul’,xk,’iese din joc al’ S,’-lea’
pentru i=k,n-1,1 execută
atribuie xi xi+1
altfel
{copilul care iese este al n-lea}
atribuie k 1
scrie ‘copilul’,xn,’iese din joc al ’,S,’-lea’
[]
atribuie n n-1 {restrânge şirul}

52
până n=1
[]
scrie ‘copilul’,x,’iese al ’,S+1,’-lea’
stop
Se remarcă folosirea operatorului ,,MOD” pentru selectarea ,,copilului care
părăseşte jocul”.

53
ALGORITMI. DE CAUTARE IN TABLOURI.

Se dă un tablou X, având N componente. Să se stabilească dacă o


valoare y se află în tabloul X. În caz afirmativ se va da poziţia lui y in codul
şirului.
Cazurile: a) tabelul nu este ordonat
b) tabelul ordonat
a)Descrierea algoritmului în limbaj natural
Această operaţie poartă numele de "căutare într-un şir".Atunci când
elementele sirului sunt arbitrare trebuie să comparăm pe rând fiecare element al
şirului Xi cu valoarea y până la găsirea valorii y în şir şi a poziţiei în care se afla
sau până la epuizarea şiruri .Metoda aceasta de căutare este o metodă secvenţială
b)Descrierea şi semnificaţia structurilor de date folosite :
X : şirul (tabloul) în care se face căutarea
n : numărul de elemente al tabloului(dimensiunea efectivă)
y : valoarea ce se caută în tablou
i : contor
k : indicator( flag ) ; = 1 : condiţie îndeplinită ( y în şir )
= 0 : condiţie neîndeplinită
c)Descrierea algoritmului în Pseudocod
citeşte n , (xi , i = 1 , n ) , y
atribuie i 1, k 0
repetă
dacă xi = y atunci

atribuie k  1 {s-a găsit elementul în şir }


altfel
atribuie i  i + 1
[]
pînă k = 1 sau i > n
[]
dacă k =1 atunci
scrie ' elementul este în şir în pozitia',i
altfel
scrie ' elementul nu este în şir '
[]
stop
Variabila K introdusă ia valoarea i dacă elementul se află în şir.
Soluţie 2
a) Descrierea algoritmului în limbaj natural:
Dacă elementele şirului sunt ordonate crescător: x1<x2<x3…<xn,

54
putem efectua căutarea mai eficient, oprindu-ne atunci când întâlnim un element
din şir care este mai mare decât y, deoarece în acest caz este clar că valoarea
căutată nu este în şir.
b) Descrierea şi semnificaţia structurilor de date folosite:
x : şirul (tabloul) în care se face căutarea
n : numărul de elemente al tabloului(dimensiunea efectivă)
y : valoarea ce se caută în tablou
i : contor
k : indicator( flag ) ; = 1 : condiţie îndeplinită ( y în şir )
= 0 : condiţie neîndeplinită
c)Descrierea algoritmului în Pseudocod
citeşte n , (xi , i = 1 , n ) , y
atribuie i 1, k 0
repetă
dacă xi = y atunci

atribuie k  1
scrie'elementul este în poziţia',i
altfel
atribuie i  i + 1
[]
pînă k = 1 sau (xi > y) sau (i>n)
[]
dacă k =0 atunci
scrie ' elementul nu este în şir '
[]
stop
Soluţia 3
a)Descrierea algoritmului în limbaj natural:
În cadrul şirurilor ordonate, o metodă rapidă de căutare în şiruri este"metoda
de căutare binară" (logaritmcă). În cazul acestei metode se compară elementul xk
din mijlocul tabloului.
Sunt 3 situaţii posibile:
-xk = y -s-a găsit componenta dorită
-xk < y -componenta y se va căuta în jumătatea superioară a şirului
-xk > y -componenta y se va căuta în jumătatea inferioară a şirului.
Căutarea se încheie fie la găsirea valorii în şir, fie la restrângerea domeniului
de căutarela un singur element.
b)Descrierea şi semnificaţia structurilor de date folosite:
x : şirul (tabloul) în care se face căutarea
n : numărul de elemente al tabloului(dimensiunea efectivă)
y : valoarea ce se caută în tablou
i,j,k : indici în şir (capetele intervalului şi mijlocul)
N : indicator( flag ) ; = 1 : condiţie îndeplinită ( y în şir )
55
= 0 : condiţie neîndeplinită
c)Descrierea algoritmului în Pseudocod
citeşte n , (xi , i = 1 , n ) , y
atribuie i 1, j 0, N0
repetă
atribuie k[(i+j)/2]
dacă y = x atunci

atribuie Nk  1
altfel
dacă y < x atunci
atribuie jk k-1
altfel
atribuie i k+1
[]
[]
pînă N = 1 sau (i>j)
[]
dacă N=1 atunci
scrie ' elementul y este în şir în poziţia ', k
altfel
scrie ' elementul y nu este în şir '
[]
stop

O funcţie este cunoscută prin valorile ei în N puncte, adică prin două


tablouri X şi Y de abcise, respectiv ordonate. Să se calculeze valoarea
funcţiei într+n punct de abcisă A, utilizând polinomul de interpolare
Lagrange. Se ştie că valoarea polinomului în punctul A este dată de relaţia:
B= *
a)Descrierea algoritmului în limbaj natural:
Dându-se cele două tablouri, trebuie calculată valoarea B realizând o sumă
de produse. Variabila P va reţine produsul la un moment dat. Trebuie evitată
situaţia când j = i.
b)Descrierea şi semnificaţia structurilor de date folosite:
x,y: tablouri în care se introduc coordonatele
n : numărul de puncte (dimensiunea tablourilor)
a : abscisa în care se calculează funcţia
B,P: variabile ajutătoare în care se memorează sumele, respectiv
produsele parţiale
c)Descrierea algoritmului în Pseudocod:
citeşte n {numărul de puncte}

56
citeşte (xi, i =1,n), (yi, i =1,n) {coordonatele punctelor}
citeşte a {abscisa punctului}
atribuie B0
pentru i =1,n,1 execută {realizează suma}
atribuie P1
pentru j = 1,n,1 executa {realizează produsul}
dacă i <> j atunci A-xi
atribuie P  P*xi - xj
[]
[]
atribuie BB+yi * P
[]
scrie B
stop

Se dă un şir X cu N componente reale. Se cere să se localizeze cel


mai mare subşir ordonat strict crescător în cadrul şirului.
a)Descrierea algoritmului în limbaj natural:
Două elemente din şir pot face parte dintr-un subşir dacă xi < xi+1. Se consideră
variabile ls –lungimea soluţiei, lc –lungimea curentă determinată şi poz-poziţia de
început a subşirului în şirul iniţial. Se consideră pentru început că subşirul este
format dintr-un singur element (ls=1) şi poziţia sa este 1(poz=1). Se compară apoi
câte două elemente consecutive: xi şi xi+1
Atâta timp cât între elementele consecutive avem relaţia xi < xi+1 se
măreşte cu o unitate valoarea lui lc. În momentul în care între două elemente
consecutive din şir avem relaţia xi > xi+1 înseamnă că subşirul curent
ordonat s-a terminat şi începe un nou subşir.
Ca atare se compară lungimea presupusă a soluţiei ls cu lungimea curentă lc.
Dacă lc > ls se actualizeză lc şi pozişia subşirului cu relaţiile:
atribuie ls  lc,
pozi - lc+1
După parcurgerea şirului trebuie să mai actualizăm odată lungimea soluţiei
ls, dacă este cazul.
b)Descrierea şi semnificaţia structurilor de date folosite:
x :şirul de numere reale
nmax:dimensiunea maximă a şirului
n :dimensiunea efectivă a şirului (numărul de componente)
poz :poziţia din care începe subşirul cel mai lung
ls :lungimea soluţiei
lc :lungimea curentă
i :contor
c)Descrierea algoritmului în Pseudocod:

citeşte n, (x,i=1,n)
57
atribuie ls 1,
poz 1, lc 1;
pentru i =1,n-1,1 execută
dacă xi < xi+1 atunci
atribuie lc lc+1
altfel
dacă lc > ls atunci
atribuie ls 1
pozi - lc+1
[]
atribuie lc 1
[]
[]
dacă lc > ls atunci
atribuie ls lc
pozn - lc+1
[]
scrie ls,poz
scrie xi, i = poz, poz + ls
stop
d)Programul Pascal;
Program subsir_1;
Const nmax=20;
Var
x : array [1..nmax] of real;
n,I :1..nmax;
lc,ls,poz:integer;
BEGIN{main}
write (‘n=’);read (n); {citeste elementele sirului}
for i:=1 to n do
begin
writeln(‘introduceti n’,i);
read(x[i]);
end; {stabileste lc,ls,poz }
lc:=1; ls:=1;poz:=1;
for i:=1 to n -1do
if x[i] < x[i+1] then
lc:=lc+1 {incrementeaza lungimea subsirului}
else
begin
if ls > lc then
begin {retine lungimea si pozitia subsirului cel mai lung}
ls := lc;
poz:= i- lc+1;
58
end;
lc:=1;
end;
if lc > ls then
begin
ls := lc;
poz:=lc+1;
end;
writeln(‘lungimea subsir maxim=’ , ls ,’pozitia=’,poz);
writeln(‘elementele subsirului cel mai lung sunt:’);
for i:=poz to poz + ls do
write(x[i]:4);
END.
Soluţia 2
a)Descrierea algoritmului în Pseudocod:
procedura subşir(n,xx,ls,poz) este :
atribuie ls1
poz1
lc1
pentru i=1,n-1,1 execută
dacă xxi<xxi+1 atunci
atribuie lclc+1
altfel
dacă lc>ls atunci
atribuie lsls
pozi-lc+1
[]
atribuie lc1
[]
[]
dacă lc>ls atunci
atribuie lsls
pozi-lc+1
[]
sfârşit{subşir}
citeşte n,(xi,i=1,n)
execută subşir (n,x, ls,poz)
scrie ls,poz
scrie (xi,i=poz, poz + ls - 1)
stop]
b)Programul Pascal:
Program subsir_2;
Const
nmax=20;
59
Type Sir: array [1..nmax] of real;
Dom:= 1 .. nmax;
Var
x: sir;
i,n,ns,poz,ls:dom;
PROCEDURE SUBSIR (n:dom;xx:sir; var ls,poz:dom )
var i,lc:dom;
begin
ls:= 1;lc:= 1; poz:=1;
for i:=1 to n-1 do
if xx[i] < xx[i+1] do
lc:=lc+1
else
begin
if lc>ls then
begin
ls:=lc;
poz:=i-lc+1;
end;
lc:=1;
end;
if lc>ls then
begin
ls:=lc;
poz:=n-lc+1;
end;
end;{subsir}
BEGIN {Programul principal}
write(‘n=’);
readln(n);
for i:= 1 to n do
begin
write (‘introduceti elementul x(‘,i:2,’)’);
readln (x[i]);
end;
SUBSIR (n,x,ls,poz);
Writeln(‘l subsir=’, ls,’pozitia din care incepe=’,poz);
Writeln(‘elementele subsirului sunt:’);
For i:= poz to poz + ls do
write(x[i]:4);
end.

60
ALGORITMI PENTRU POLINOAME

Se dau două polinoame de grad m, respectiv n. Să se scrie programul


care calculează polinomul produs.
a)Descrierea algoritmului în limbaj natural:
Fie cele două polinoame A(x)=a1xm+ a2xm-1+… +am+1 de grad m, respectiv
B(x)=b1xn + b2xn-1 +… +bn+1 de grad n.
Polinomul produs va avea gradul m+n şi m+n +1 termeni. Polinomul produs
se va obţine prin înmulţirea coeficienţilor polinomului P(x) cu fiecare monom al
polinomului A(x).
Coeficientul puterii celei mai mari se obţine prin înmulţirea coeficieţilor
a1*b1, iar termenul liber se obţine prin înmulţirea termenilor liberi am+1* bn+1. Prin
înmulţirea coeficienţiilor polinimului P(x) cu termenul a se va obţine un polinom
de grad m+n cu n+1 termeni; analog prin înmulţirea cu termenii a2, an+1 se obţin
polinoame de grade m+n-1, …, n.
Polinomul produs se obţine prin însumarea acestor m+1 polinoame
intermediare.
Notând cu C(x)=c1xp+c2xp-1+…+cp+1, coeficienţii c1,c2,…,cp+1 vor trebui
iniţializaţi cu 0 la începutul calcului.
b)Descrierea şi semnificaţia structurilor de date folosite:
a,b,c: tabloul de numere reale coeficienţii polinoamelor
m,n,p: dimensiunile tablourilor(gradele polinoamelor)
i,j :contoare
c)Descrierea algoritmului în Pseudocod:
citeşte m,n
citeşte a1,a2,…,am+1
citeşte b1,b2,…,bn+1
atribuie m1m+1
atribuie n1n+1
atribuie pm+n
pentru i=1,p+1,1execută
atribuie ci0
[]
pentru i=1,mi,1execută
pentru j=1,ni,1execută
[] atribuie ci+j-1 ci+j-1+ai+bj
scrie p
scrie c1,…,cp+1
[]stop
d)Programul Pascal:
Program produs_polinoame;
Var

61
m,n,p,i,j :integer;
a,b,c:array [1..40] of integer;
BEGIN{main}
Write (‘dimensiunea polinoamelor=’);
readln(m,n);
Write(‘polinomul a=’);
For i:=1 to m+1 do
begin
Write(‘a[i]=’);
readln (a[i]);
end;
write(‘polinomul b=’);
For i:=1 to n+1 do
begin
Write(‘b[i]=’);
readln (b[i]);
end;
p:=m+n;
for i:=1 to p+1 do
c[i]:=0;
for i:=1 to p+1 do
for j:=1 to n+1 do
c[i+j-1]:= c[i+j-1] +a[i] *b[j];
writeln(‘polinomul produs=’);
for i:=1 to p+1 do
write(c[i]);
END.

Se dau două polinoame de grad m, respectiv n. Să se scrie programul


care scrie câtul şi restul.
a)Descrierea algoritmului în limbaj natural:
Fie polinomul deîmpărţit A(x)=a1xm+ a2xm-1+… +am+1 de grad m şi polinomul
împărţitor B(x)=b1xn + b2xn-1 +… +bn+1 de grad n.
Polinomul cât va avea gradul m-n şi deci m-n+1termeni, iar polinomul rest
va avea gradul r < n. Împărţirea se poate realiza prin scăderi succesive. După
fiecare scădere se va actualiza polinomul deîmpărţit. Vor fi m-n+1 astfel de
actualizări corespunzător fiecărui termen al câtului. Astfel, fiecare coeficient al
câtului va fi
ci = ai / bi
Se face observaţia că trebuie evidenţiat cazul când gradul deîmpărţitului este
mai mic decât gradul împărţitorului.
b)Descrierea şi semnificaţia structurilor de date folosite:
a,b,c,r : tablouri de numere reale: coeficienţii polinoamelor
m,n,p : dimensiunile tablourilor:gradele polinoamelor
62
i,j,k : contoare
c)Descrierea algoritmului în Pseudocod:
citeşte m,n
citeşte a1,a2,…,am+1
citeşte b1,b2,…,bn+1
dacă m<n atunci
scrie ’gradul deîmpărţitului < gradul împărţitorului’
altfel
pentru i=1,m-n+1,1execută
atribuie ci  ai/bi
pentru j=1,n+1 execută
ai+j-1 ai+j-1+ ci + bj
[]
[]
scrie c1,…,cm-n+1
scrie am-n+2,…,am+1
[]
stop
Polinomul cât va avea coeficienţii c1,…,cm-n+1, iar polinomul rest am-n+2,…,am+1
START

Citeste m,n
a1,a2,…,am+1
b1,b2,…,bn+1

NU DA
m<n

i:=1 Scrie
’gradul deîmpărţitului<gradul împărţitorului’
NU DA
i<=m-n+1

ci := ai/bi
Scrie
c1,…,cm-n+1
j:=1

Scrie DA
am-n+2,…,am+1 j<=n+1

NU ai+j-1 ai+j-1+ ci + bj
STOP

j:=j+1

63
d)Programul Pascal:
Program impartire_polinoame;
Var
m,n,i,j,k,p: integer;
a,b,c,r : array [1..30] of real;
BEGIN{main}
Write (‘dimensiunea polinoamelor=’);
readln(m,n);
Writeln(‘polinomul deimpartit =’);
For i:=1 to m+1 do
read (a[i]);
Writeln(‘polinomul impartitor =’);
For i:=1 to n+1 do
read (b[i])
if m < n then
write(’gradul deîmpărţitului < gradul împărţitorului’)
else
begin
p := m-n;
writeln (‘gradul citului=’,p);
64
for i:= 1 to m-n+1 do
begin
c[i] := a[i] / b[i];
for j:=1 to n+1do
a[i+j-1]:= a[i+j-1] -c[i]*b[j];
end;
end;
writeln(‘polinomul cit=’);
for i:=1 to m-n+1 do
write(c[i]);
writeln;
writeln(‘polinomul rest=’);
for i:=1 to m-n+2 do
write(a[i]);
END.

Să se calculeze integrala unui polinom în 3 variabile, format din 20 de


monoame.
a)Descrierea algoritmului în limbaj natural:
Se foloseşte egalitatea (adevărată în cazul polinoamelor):
∫∫∫ xai ybi zci dx dy dz = ∫xai dx * ∫ ybi dy * ∫ zci dz
Coeficienţii polinomului vor fi memoraţi într-un vector C,iar exponenţii
lui x,y,z din fiecare monom sunt păstraţi în cele 3 coloane ale matricei EXP.
Limitele de integrare (interioară şi superioară) sunt memorate în vectorii A şi B de
câte 3 componente.
Calculul integralei constă în integrarea succesivă a monoamelor
componente şi în adunarea rezultatelor. Pentru calculul puterilor se foloseşte o
funcţie.
c)Descrierea algoritmului în Pseudocod:
funcţie putere (baza, exponent)
atribuie ptr  1
pentru i=1, exponent, 1 execută
atribuie ptr  ptr * baza
[]
atribuie putere  ptr
sfârşit putere
citeşte expt,c,a,b
atribuie int  0
pentru i = 1, 20, 1 execută
atribuie p  c(i)
pentru k = 1, 3,1 execută
atribuie
p  p/(expt(i,k)+1)*(B(k) expt(i,k)+1 - a(k) expt(i,k)+1)
[]
65
atribuie int  int + p
[]
scrie int
stop
d)Programul în PASCAL:
Program integrală;
Var a,b :array[1..3] of real;
c :array[1..20] of real;
expt :array[1..20,1..3] of integer;
p,int :real;
i,j,k, :integer;
FUNCTION PUTERE (baza:real;exponent:integer):real;
Var i :integer;
ptr: real;
begin
ptr:=1;
for i:=1 to exponent do
ptr:=ptr * baza;
putere:=ptr
end;
{PROGRAM PRINCIPAL}
BEGIN
Writeln(‘introduceti coeficientii polinomului’);
For i :=1to 20 do read(c[i]);
Writeln(‘introduceti puterile de monoame’);
For i :=1to 20 do
For j :=1to 3 do
read(expt[i,j]);
Writeln(‘introduceti limitele de integrare’);
For i :=1to 3 do
read(a[i],b[i]);
Int:=0;
For i :=1to 20 do
begin
p:=c[i];
For k :=1to 3 do
begin
p1:= expt[i,k] + 1;
p:= p/p1 * (putere(b(k),p1)-putere (a(k),p1));
end;
int:=int + p;
end;
writeln(‘integrala este =’, int);
END.
66
Să se scrie algoritmul de calcul al valorilor polinomului de gradul n al
lui Cebâşev în punctele: xi = 0,1 +0,7i i =1,2,…,m
unde Tk(x)=2*x – Tn-1(x) – Tn-2(x) cu T1(x)=1, T2(x)= x
a)Descrierea algoritmului în limbaj natural:
Algoritmul va calcula pentru fiecare punct xi valorile :
T1(xi), T2(xi),…, Tn(xi) şi va tipări valoarea Tn(xi).
b)Descrierea şi semnificaţia structurilor de date folosite:
T1,T2,T3 : cei trei termeni din relaţia de recurenşă ai definiţiei şirului
Cebâşev
x: punctul în care se calculează polinomul
k: contor
c)Descrierea algoritmului în Pseudocod:
citeşte m,n
pentru i=1,m,1execută
atribuie x  0,1 + 0,7*0,7*i
atribuie T1  1
atribuie T2  x
atribuie T3  2 * x * T2 – T1
atribuie k  3
cât timp k<=n execută
atribuie T1  T2
atribuie T2  T3
atribuie T3  2 * x * T2 – T1
atribuie k  k + 1
[]
scrie T3
[]
stop

ALGORITMI PENTRU TABLOURI BIDIMENSIONALE

Pe mediul de intrare se dau dimensiunile m,n,p a două matrice reale,


precum şi elementele acestor matrice. Se cere un program pentru
înmulîirea acestor matrice.
a)Descrierea algoritmului în limbaj natural :
Presupunem că matricea A are m linii şi n coloane, matricea B are n linii şi p
coloane iar matricea produs C va avea m linii şi p coloane. Pentru aflarea matricei
produs se va folosii relaţia: cij = aik * bkj pentru i = 1,m şi j = 1,p
b)Descrierea şi semnificaţia structurilor de date :
- m,n,p: variabile întregi ce reprezintă dimensiunile reale ale celor trei matrice;
- a,b,c: tablouri reale în care se reţin cele trei matrice ;
-s : variabila reală folosită la clculul unui element al matricei produs;
67
- i,j,k: variabile întregi folosite în ciclurile cu contor.
c)Descrierea algoritmului în Pseudocod:
O primă variantă a algoritmului eate:
 citeşte dimensiunile matricelor
 citeşte prima matrice
 citeşte adoua matrice calculează matricea produs
 scrie matricea produs
stop
Operaţia ‘citeşte dimensiunile matricelor ‘ se materializează prin:
citeşte m,n,p
Operaţia ‘citeşte prima matrice’ se realizeză prin citirea secvenţială pe linie
a elementelor matricei, adică prin:
pentru i = 1, m, 1 execută
pentru j = 1, n, 1 execută
citeşte a(i,j)
[]
[]
Operaţia ‘citeşte a doua matrice’ se realizează similar prin :
pentru i = 1, n, 1 execută
pentru j = 1, p, 1 execută
citeşte b(i,j)
[]
[]
Pentru operaţia ‘calculează matricea produs’ se observă că fiecare element
c(i,j) este o sumă de n termeni. Calculul sumei se poate realiza printr-un ciclu cu n
paşi. Acest ciclu trebuie repetat pentru fiecare element al matricei produs, deci
pentru fiecare linie şi pentru fiecare element din cadrul liniei. Operaţia poate fi
detaliată astfel: pentru ‘fiecare linie execută’ execută
pentru ‘fiecare coloană’ execută
calculează c(i,j)
[]
[] sau în enunţ standard prin:
pentru i = 1, n, 1 execută
pentru j = 1, p, 1 execută
citeşte b(i,j)
[]
[] Operaţia ‘calculează c(i,j)’se poate detalia astfel:
atribuie S0
pentru i = 1, p,1 execută
atribuie S  S + a(i,k) * b(k,j)
[]
atribuie c(i,j)  S Operaţia ‘scrie matricea produs’ implică:
pentru i = 1, n, 1 execută

68
pentru j = 1, p, 1 execută
scrie c(i,j)
[]
[] Detaliind operaţiile se ajunge la următorul algorim:
citeşte m,n,p
pentru i = 1, n, 1 execută
pentru j = 1, p, 1 execută
citeşte b(i,j)
[]
[]
pentru i = 1, n, 1 execută
pentru j = 1, p, 1 execută
citeşte b(i,j)
[]
[]
pentru i = 1, m, 1 execută
pentru j = 1, p, 1 execută
atribuie S0
pentru i = 1, p,1 execută
atribuie S  S + a(i,k) * b(k,j)
[]
atribuie c(i,j)  S
[]
[]
pentru i = 1, m , 1 execută
pentru j = 1, p, 1 execută
scrie c(i,j)
[]
[]
stop
d)Descrierea programului în PASCAL:
Program prod_mat;
Const
mmax = 10; nmax = 20;
pmax=30;
var
i,j,k,m,n,p: integer;
s : real;
a: array [1..mmax,1..nmax] of real;
b: array [1..nmax,1..pmax] of real;
c: array [1..mmax,1..pmax] of real;
BEGIN{main}
Write(“Dati valorile pentru m,n,p=”);
readln(m,n,p);
69
Writeln(‘Dati elementele matricei A’);
For i:= 1 to n do
begin
Writeln(‘Dati linia’, i:3, ‘:’);
For j:= 1 to n do
read(a[i,j]);
Readln;
end;
Writeln(‘Dati elementele matricei B’);
For i:= 1 to n do
begin
Writeln(‘Dati linia’, i:3, ‘:’);
For j:= 1 to p do read(b[i,j]);
readln;
End;
Writeln(‘calculeaza si tipareste matricea C’);
For i:= 1 to n do
begin {calculeaza o linie}
For j:= 1 to p do
begin {calculeaza un element}
S:=0;
For k:=1 to n do
s:=s + a[i,k]*b[k,j];
c[i,j]:= s;
end;
write(s:8:2); {scrie un element}
end;
END.

Într-o matrice cu m lini şi n coloane să se permute circular dreaptă


fiecare linie i cu i poziţii. Se va utiliza o procedură care permută circular
dreapta cu o poziţie componentele unui vector.
a)Descrierea algorimului în limbaj natural:
Se va construi o procedură care permută circular dreapta cu o poziţie
componentele unui vector. Fiecare linie a matricei se va introduce într-un vector,
se va apela procedura de i ori (i numărul liniei) după care se va introduce vectorul
în matrice. În final se va afişa matricea.
b)Descrierea şi semnificaţia structurilor de date folosite :
pentru procedura avem:
- l : dimensiunea vectorului ce se permută cu o poziţie
- x : vectorul ce se permută
- y : variabila reală în care se salvează ultimul element
- i : variabila întregă folosită pentru ciclul cu contor pentru programul principal:
- n,m : dimensiunile matricei
70
- i,j,k : variabile contor
- a : matricea dată
- b : vector linie în care se salvează o linie a matricei, se permută linia i de i ori
c)Descrierea algoritmului în Pseudocod:
Se consideră un vector x care are n componente. Printr-o permutare
circulară dreaptă cu o poziţie a elementelor vectorului, elementul din ultima poziţie
trece în prima poziţie, iar restul se deplasează spre dreapta cu o poziţie.
O primă formă a algoritmului procedurii ar fi:
Procedura permută (p,x) este :
 salvează ultimul element
 deplasează cu o poziţie
 restaurează prima poziţie
sfîrşit {permută}
Pentru a asalva elementul din poziţia n se va folosi o variabilă y căreia i se
va atribui ultimul element, adică: atribuie y  x(n) iar pentru deplasarea
celorlalte elemente la dreapta cu o poziţie se va folosi un ciclu cu contor, adică:
pentru j  p, 2, -1 execută
atribuie a(i)a(i-1)
[]
Operaţia ‘restaurează prima poziţie’ implică introducerea valorii salvate în y
în prima poziţie a vectorului, adică în x(i) operaţie realizată prin atribuirea :
atribuie x(i)  y
Procedura în Pseudocod este :
Procedura permută (p,x) este :
atribuie y  x(n)
pentru i  1, 2, -1 execută
atribuie x(i)x(i-1)
[]
atribuie x(i)  y
sfîrşit {permută}
2)Descrierea programului principal :
Se citesc dimensiunile reale ale matricei şi elementele matricei. Pentru
fiecare linie (i) algoritmul va apela procedura ‘permută’de i ori, după ce în
prealabil linia (i) a fost salvată în vectorul B. În final linia (i) permutată cu i poziţii
se va repune în matrice în poziţia sa. O primă variantă a algoritmului ar fi :
citeşte m,n
pentru i = 1, m, 1 execută
pentru j = 1, n, 1 execută
citeşte a(i,j)
[]
[]
pentru i = 1, m, 1 execută
 extrage linia i

71
 permută de i ori linia i
 reintrodu linia
[]
pentru i = 1, m , 1 execută
pentru j = 1, p, 1 execută
scrie a(i,j)
[]
[]
stop
Operaţia ‘extrage linia i’ se realizează printr-un ciclu cu contor, prin care
elementele matricei A din linia i se introduc se introduc înnvectorul b, adică :
pentru k=1, n execută
atribuie b(k)a(i,k)
[]
Operaţia ‘permută de i ori linia i’ implică un ciclu cu contor în care
procedura permută este apelată de i ori, adică :
pentru j = 1, i, 1
execută permută (n,b)
[]
Operaţia ‘reintrodu linia’ implică introducerea elementelor vectorului b în
linia i din matrice prin:
pentru k=1, n execută
atribuie a(i,k)b(k)
[]
În aceste condiţii, algoritmul programului principal descris în procedură
arată astfel : citeşte m,n
pentru i = 1, m, 1 execută
pentru j = 1, n, 1 execută
citeşte a(i,j)
[]
[]
pentru i = 1, m, 1 execută
pentru k=1, m execută
atribuie b(k) a(i,k)
[]
pentru j = 1, i, 1
execută permută (n,b)
[]
pentru k=1, n execută
atribuie a(i,k)b(k)
[]
[]
pentru i = 1, m , 1 execută
pentru j = 1, p, 1 execută
72
scrie a(i,j)
[]
[]
stop
c) Programul PASCAL:
Program permuta_matrice;
Const
Nmax=10;
Type
linie = 1..nmax;
vector = array [linie] of real
Var
a : array [linie,linie] of real;
b : vector;
m,n:linie;
i,j,k: 1..nmax;
PROCEDURE PERMUTA (var x:vector; p: linie);
var
i: linie;
y:real;
begin
y:=x[p];
for i:= p downto 2 do
x[i]:= x[i-1];
x[1]:=y;
end;{permuta}
BEGIN {program principal}
read(m,n); {citeste dimensiunile tabloului}
for i:=1 to m do
for j:=1 to n do
read(a[i,j]);{citeste elementele matricei}
for i:=1 to m do
begin
for k:=1 to n do b[k]:=a[i,k];{extrage o linie din matrice}
for j:= 1 to i do permuta(b,n); {apeleaza permuta de i ori}
for k:=1 to n do a[i,k]:=b[k];{reintroduce lin i in matrice}
end;
for i:=1 to m do
begin
for j:=1 to n do
write(a[i,j]);
writeln;
end;
END.
73
O matrice rară, adică o matrice având majoritatea elementelor nule
(peste 90 %) se memorează economic sub forma a doi vectori, unul
conţinând elementele nenule din matrice, iar celălalt poziţiile lor în matrice,
făcând liniarizarea matricei pe linii. Să se definească oprocedură care
reconstituie o matrice rară A, având m linii şi n coloane şi p elmente
nenule, matricea este dată prin vectorii de componente nenule şi de
poziţiile acestora.
a) Descrierea algoritmului în limbaj natural:
Pentru matricea A de m = 3 linii şi n = 4 coloane, dată mai jos :
0 7,5 0 0
A= 0 0 -1,5 0
0 11 0 0
elementele ei se memorează sub forma a două tablouri în cadrul vectorilor :
val = (7.5, -1.5,11)
poz=(2,7,10)
unde tabloul val reţine valoarea elementelor matricei A nenule, iar tabloul poz
conţine poziţiile acestor elemente liniarizate pe linii.
Dacă elementul a(i,j) este diferit de 0, atunci potiţia sa în cadrul matricei sub
formă liniarizată are valoarea : Poz(k) = (i-1) * n + j unde k indică al
câtelea element nenul din matricea A este, i,j este numărul liniei, respectiv al
coloanei din matrice unde se află elementul al k- lea nenul, iar n numărul de
coloane al matricei date.
Dându-se cei doi vectori val şi poz şi ştiind că matricea A are m linii şi n
coloane, poziţia elementului nenul în matrice se află folosind relaţiile :
Linia i = [poz(k)/n] + 1
Coloana j = poz(k) mod n (1)
În aceste condiţii dându-se dimensiunile matricei de refăcut “m” şi ”n”,
numărul de elemente nenule din matrice şi cele două tablouri val şi poz se
iniţializează matricea A la zero după care folosind relaţiile (1) se calculează poziţia
elementelor nenule din matrice şi se asignează acestora valoarea din tabloul val.
Pentru rezolvarea problemei se va folosii o procedură de refacere a unei
matrici rare.
b)Descrierea şi semnificaţia structurilor de date.
p: numărul de elemente nenule din matricea A, nr. de elemente din val şi poz
val : tablou ce conţine elementele nenule din A
poz : tablou ce conţine poziţiile elementelor nenule din A
m,n : numărul de linii respectiv de coloane din matricea A
A : matricea rară cu m linii şi n coloane
b)Descrierea algoritmului în Pseudocod.
1)Descrierea procedurii.
Procedura refacemat (val,poz,p,m,n;A) este:
{se iniţializeză la 0 toate elementele matricii A}

74
pentru i = 1, m, 1 execută
pentru j = 1, n, 1 execută
atribuie a(i,j)  0
[]
[] {Se ia câte un element di vectorul val, respectiv poz şi se
calculează poziţia elementului în matricea A şi se atribuie acestuia}
pentru k = 1, p, 1 execută
atribuie i  [poz(k)/n] + 1
atribuie j  poz(k) mod n
atribuie a(i,j)  val(k)
[]
sfârşit {refacemat}
2)Descrierea în Pseudocod a programului principal este :
citeşte m,n {numărul de linii şi coloane ale matricei A}
citeşte p {numărul de elemente nenule din matricea A}
pentru i = 1, p, 1 execută
citeşte val(i),poz(i) {elementele <> 0 ale lui A}
{şi poziţiile elementelor <> 0 ale lui A }
[]
execută refacemat (val,poz,p,m,n;A);

stop
2)Descrierea programului în PASCAL:
Program matrice_rara;
Const
nmax=10;
type
linie = 1..nmax;
matrice = array [linie,linie] of real;
vector = array [linie] of real;
pozitie = array [linie] of integer;
var
poz : pozitie;
val : vector;
a : matrice;
i,j,m,n,p : integer;
PROCEDURE REFACEMAT (val:vector; poz:pozitie; p,m,n: linie;var a: matrice);
var
i,j,k,: integer ;
begin {initializam matricea A cu 0}
for i:=1 to m do
begin
for j:=1 to n do
a[i,j]:=0;
75
end;
{determina linia si coloana elementului nenul din matrice}
for k:= 1 to n do
begin
I:= poz[k] div n + 1;
j:= poz[k] mod n;
a[i,j]:= val[k];
end;
end; {reface matricea}
BEGIN{main}
Read(m,n);
Read(p);
for i:=1 to p do
read(val[i]);
for i:=1 to p do
read(poz[i]);
refacemat(val,poZ,m,n,p,a);
for i:=1 to m do
begin
for j:=1 to n do write(a[i,j] :8:2);
writeln;
end;
END.

Se consideră o matrice pătrată A cu n linii şi n coloane. Să se


elaboreze algoritmul pentru parcurgerea în sens de ‘spirală’ a matricei A,
adică:
a11…………………….ain
a21………………..
………….

………………\
a1n…………………….an n
a)Descrierea algoritmului în limbaj natural:
Se dă dimensiunea n a matricei. Se observă că avem de parcurs în sens orar
n/2 (pentru n par), respectiv [n/2] + 1 (pentru n impar)
akk…………………………. ak,n-k+1

an-k+1,k……………………… an-k+1, n-k+1


Parcurgerea va fi însoţită de afişarea elementelor selectate din matricea A.
b)Descrierea şi semnificaţia structurilor de date folosite:
-A :tablou bidimensional cu n linii şi n coloane
-n :dimensinea tabloului
-i,j,k: variabile contor
76
c)Descrierea algoritmului în Pseudocod.
O primă descriere a algoritmului este:
citeşte n
pentru i = 1, n , 1 execută
pentru j = 1, n, 1 execută
citeşte a(i,j)
[]
[]
pentru k= 1,p,1 execută
*parcurge pătratul k şi afişează
[]
stop
Operaţia’ parcurge pătratul k şi afişează’ implică
- parcurgerea laturii de sus a pătratului de la stânga spre dreapta prin
secvenţa:
pentru j=k, n-k , 1 execută
scrie a(k,j)
[]
- parcurgerea laturii din dreapta a pătratului de sus în jos prin secvenţa:
pentru i=k, n-k , 1 execută
scrie a(i,n - k + 1)
[]
- parcurgerea laturii de jos a pătratului de la dreapta la stânga prin secvenţa:
pentru j=n-k+1, k+1 , -1 execută
scrie a(n-k+1,j)
[]
- parcurgerea laturii din stânga a pătratului de jos în sus prin secvenţa:
pentru i=n-k+1, k+1 , -1 execută
scrie a(i,k)
[]
În aceste condiţii descrierea algoritmului arată astfel:
citeşte n
pentru i = 1, n , 1 execută
pentru j = 1, n, 1 execută
citeşte a(i,j)
[]
[]
dacă n mod 2 = 0 atunci
atribuie pn/2
alfel
atribuie p[n/2] + 1
[]
pentru k= 1,p,1 execută
pentru j=k, n-k , 1 execută
77
scrie a(k,j)
[]
pentru i=n-k+1, k+1 , -1 execută
scrie a(i,k)
[]
pentru j=n-k+1, k+1 , -1 execută
scrie a(n-k+1,j)
[]
pentru i=k, n-k , 1 execută
scrie a(i,n - k + 1)
[]
[]
stop
Programul PASCAL:
Program permuta_matrice;
Const
Nmax=10;
Type
linie = 1..nmax;
vector = array [linie] of real
Var
a : array [linie,linie] of real;
b : vector;
m,n:linie;
i,j,k: 1..nmax;
PROCEDURE PERMUTA (var x:vector; p: linie);
Var
i: linie;
y: real;
begin
y:=x[p];
for i:= p downto 2 do
x[i]:= x[i-1];
x[1]:=y;
end; {permuta}
BEGIN {program principal}
read(m,n); {citeste dimensiunile tabloului}
for i:=1 to m do
for j:=1 to n do
read(a[i,j]);{citeste elementele matricei}
for i:=1 to m do
begin
for k:=1 to n do
b[k]:=a[i,k]; {extrage o linie din matrice}
78
for j:= 1 to i do
permuta(b,n); {apeleaza permuta de i ori}
for k:=1 to n do
a[i,k]:=b[k]; {reintroduce linia i in matrice}
end;
for i:=1 to m do
begin
for j:=1 to n do
write(a[i,j]); writeln;
end;
END.

79
ALGORITMI PENTRU STUDIUL LEGILOR DE
COMPOZIŢIE

Fiind dată o mulţime finită G şi o relaţie R. Să se scrie un algoritm


prin care se verifică dacă relaţia dată este sau nu tranzitivă.
a)Descrierea algoritmului în limbaj natural:
Deoarece orice mulţime finită de N elemente se poate pune pune în
corespondenţă biunivocă cu mulţimea numerelor 1,2,…,n putem considera că
aceasta este mulţimea pe care estre definită relaţia.
O relaţie R este tranzitivă dacă este adevărată afirmaţia:
dacă (iRj) şi (jRk) atunci(iRk)
pentru orice i,j,k din mulţimea {1,2,…,n}
Se va reprezenta relaţia definită pe mulţimea A ca o matrice în care
elementul A(i,j) este 1 dacă AiRAj şi 0 dacă Ai nu este în relaţia R
b)Descrierea şi semnificaţia structurilor de date:
a : matricea de reprezentare a relaţiei
n : dimensiunea matricei A
i,j,k: indici în matrice
t : indicator (flag) = 0-relaţie tranzitivă
= 1-relaţie netranzitivă
c)Descrierea algoritmului în Pseudocod:
Varianta 1 : testare ‘directă’ ( conform definiţiei).
citeşte n,(a[ij], i=1,n, j=1, n)
atribuie t  0
pentru i = 1, n execută
pentru j = 1, n execută
dacă (i<>j şi a(i,j)=1)atunci
pentru k = 1, n execută
dacă (i=k şi k<>j şi a(j,k)=1)atunci
dacă (a(i,k)<>1)atunci
atribuie t  1
[]
[]
[]
[]
[]
[]
dacă t=0 atunci
scrie ‘relaţia este tranzitivă’
altfel
scrie ‘relaţia este tranzitivă’
[]

80
stop
Varianta 2:
Se prezintă şi o altă variantă, în care testul aiRaj şi ajRak
se face prin compararea produsului A(i,j) * A(j,k) cu zero.
citeşte n,(a[ij], i=1,n; j=1, n)
atribuie T  0
pentru i = 1, n execută
pentru j = 1, n execută
dacă (i<>j )atunci
pentru k = 1, n execută
dacă (k<>i şi k<>j şi
a(j,k)*a(i,j)=1)atunci
dacă (a(i,k)<>1)atunci
atribuie T  1
[]
[]
[]
[]
[]
[]
dacă T=0 atunci
scrie ‘relaţia este tranzitivă’
altfel
scrie ‘relaşia este tranzitivă’
[]
stop

Fiind dată o mulţime finită G şi o lege de compoziţie ‘*’, să se scrie


un algoritm prin care se va verifica dacă legea dată este sau nu asociativă.
a)Descrierea algoritmului în limbaj natural :
Legea de compoziţie se reprezintă într-o matrice care A(ij)=i*j. Pentru ca
legea să fie asociativă trebuie să fie adevărată egalitatea A(i,A(j,k))= A(A(i,j),k)
pentru orice i,j,k <= n
b)Descrierea şi semnificaţia structurilor de date:
a : matricea de reprezentare a relaţiei
n : dimensiunea matricei A
i,j,k: indici în matrice
t : indicator (flag) = 0-relaţia este asociativă
= 1-relaţia nu este asociativă
c)Descrierea algoritmului în Pseudocod:
citeşte n,(a[ij], i=1,n; j=1, n)
atribuie T  0
pentru i = 1, n execută
pentru j = 1, n execută
81
pentru k = 1, n execută
dacă (A(i,A(j,k))<> A(A(i,j),k))atunci
atribuie T  1

[]
[]
[]
[]
dacă T=0 atunci
scrie ‘relaţia este asociativă
altfel
scrie ‘relaţia nu este asociativă
[]
stop

Fiind dată o mulţime finită G şi o lege de compoziţie ‘*’, să se verifice dacă


există un element unitate.
a)Descrierea algoritmului în limbaj natural :
Se ştie că l este elementul neutru dacă A(l,j)=A(j,l)=1, pentru orice
j=1,n.
b)Descrierea şi semnificaţia structurilor de date:
a : matricea de reprezentare a relaţiei
n : dimensiunea matricei A
i,j, : indici în matrice
N : indicator (flag) = 0-relaţia are element neutru
= 1-relaţia nu are element neutru
c)Descrierea algoritmului în Pseudocod:
citeşte n,(a[ij]; i=1,n; j=1, n)
atribuie i  0
repetă
atribuie N 0
j 1
repetă
dacă (a(i,j)<>j sau (a(j,i)<>j) atunci
atribuie N 1
altfel
atribuie j j + 1
[]
până N=1 sau j>n
[]
atribuie i i + 1
până N=0 sau j>n
[]
dacă N=0 atunci
82
scrie i-l
altfel
scrie ‘ nu există element neutru’
[]
stop

Dându-se două legi de compoziţie pe o mulţime finită să se studieze


proprietatea acestor legi precum şi structura definită de ele pe această
mulţime.
a)Descrierea în limbaj natural a algoritmului:
Deoarece orice mulţime finită cu n elemente se poate pune în corespondenţă
biunivocă cu mulţimea numerelor 1..n putem considera că aceasta este mulţimea
pe care sunt definte cele 2 legi de compoziţie. Trebuie să verificăm ce proprietăţi
posedă fiecare din cele 2 legi de compoziţie:
1.dacă este peste tot definită
Faptul că o lege este peste tot definită se verifică prin declararea structurilor
de date folosite (tablourile ce corespund legilor) ca având elemente de tip
subdomeniu;
2.dacă este asociativă
O lege de compoziţie T este asociativă (iTj)Tk = iT(jTk) pentru orice i,j,k =
1..n. Verificarea asociativităţii se va face cu procedura ASOC care primeşte ca
parametrii de intrare numărul de elemente al mulţimii finite pe care este definită
legea, o matrice pătratică ce descrie legea şi ca parametru de ieşire un indicator
întreg care ia valoarea 1 dacă legea este asociativă şi 0 în caz contrar.
3.dacă este comutativă
O lege de compoziţie este comutativă dacă iTj = jTi pentru i,j = 1..n.
Procedura CONUT verifică această proprietate.
4.dacă are element unitate
O lege de compoziţie are element unitate dacă există un element l aparţinând
mulţimii 1..n astfel încât să aibă loc relaţia lTi = iTl pentru i= l..n. Găsirea
elementului unitate se face luând fiecare valoare şi compunând-o la stânga lui la
dreapta cu toate numerele între 1 şi n. Dacă există un element care compus cu toate
elementele le lasă neschimbate acela este element neutru. Procedura NEUTRU
verifică existenţa elementului neutru. Parametrii de ieşire sunt ‘ne’- un indicator
întreg care ia valoarea 1 când există element neutru şi 0 în contrar şi ‘l’-elementul
neutru; dacă valoarea lui ‘ne’ este 0 atunci nu există element neutru.
5.dacă fiecare element are un element invers faţă de lege
Dacă legea are un element neutru l, un element i este inversabil dacă există
un element j asfel încât iTj = jTi = 1. Procedura INVERS verifică dacă orice
element este inversabil. Parametrul de ieşire ‘iv’ ia valoarea 1 dacă orice element
are element invers şi 0 în caz contrar.
6.dacă o lege este distributivă fată de alta
O lege de compoziţie T este distributivă faţă de o lege de compoziţie L dacă
au loc egalităţile: (iTj)Lk = (iLk)T(jLk)
83
kL(iTj) = (kLi)T(kLj) pentru orice i,j,k = 1..n.
Procedura DISTRI verifică proprietatea de distribuitate şi are o structură
asemănătoare cu procedura ASOC dar condiţia de testare se înlocuieşte cu:
(b[i,a[j,k]] = a[b[i,j],b[i,k]]) and
(b[a[i,j],k] = a[b[i,k],b[j,k]])
Verificarea proprietăţilor pe care le posedă fiecare lege se face cu procedura
GRUP. Parametrul de ieşire ‘i’ arată dacă legea este asociativă (i=1), ‘j’ dacă legea
are element neutru (j =1), ‘k’ dacă fiecare element are un element invers (k=1), ‘m’
dacă legea este comutativă iar ‘l’ este elementul neutru când există.
Programul principal citeşte matricile corespunzătoare celor două legi de
compoziţie internă, activează procedura GRUP pentru fiecare dintre ele şi afişează
proprietîţile pe care le posedă cele două legi de compoziţie.
b)Descrierea şi semnificaţia structurilor de date folosite:
Ca structuri de date globale se folosesc :
- cele două matrici pătratice A şi B corespunzătoare celor două legi de compoziţie
- variabilele de lucru pentru parcurgerea lor: indicii i,j
- variabilele în care procedurile returnează valorile calculate: ia, ja, ka, la, ma, ib,
jb, kb, lb, mb, p, q.
c)Descrierea algoritmului în Pseudocod:
Descrierea în Pseudocod pentru verificarea proprietăţilor de asociativitate,
comutativitate, existenţa elementului neutru, existenţa elementelor inverse,
distributivitate, verificarea proprietăţilor de grup este:
Procedura ASOC (n,a, as) este
pentru i = 1, n,1 execută
pentru j = 1, n,1 execută
pentru k = 1, n,1 execută
dacă a[a[i,j],k]<> a[a[j,k],i]]atunci
atribuie as  0
sfârşit
[]
[]
[]
[]
atribuie as  1
sfârşit
Procedura conut (n,a,co) este :
pentru j = 1, n,1 execută
pentru k = 1, n,1 execută
dacă a[i,j]<> a[j,i]]atunci
atribuie co  0
sfârşit
[]
[]
[] atribuie co  1
sfârşit
84
Procedura NEUTRU (n,a,ne,l) este
pentru i = 1, n,1 execută
pentru j = 1, n,1 execută
dacă not ((j= a[i,j]) and (j= a[j,i])) atunci
goto 1
[]
atribuie l  i; ne  1
sfârşit
[]
l:
[]
atribuie l  0; ne  0
sfârşit
Procedura INVERS (n,a,iv) este:
pentru i = 1, n,1 execută
pentru j = 1, n,1 execută
dacă not ((l= a[i,j]) and (l= a[j,i])) atunci
atribuie iv  0
sfârşit
[]
[]
[]
atribuie iv  0
sfârşit
Procedura DISTRI (n,a,b,ds) este :
pentru i = 1, n,1 execută
pentru j = 1, n,1 execută
pentru k = 1, n,1 execută
dacă not (b[i,a[j,k]] = a[b[i,j],b[i,k]]) and
(b[a[i,j],k] = a[b[i,k],b[j,k]]) atunci
atribuie ds  0
sfârşit
[]
[]
[]
[]
atribuie ds  1
sfârşit
d)Programul în limbajul PASCAL:
Program_legec;
Const
nmax:=10;
type
lege=array [1..nmax,1..nmax] of integer;
85
var
a,b: lege;
n,j,i,ia, ja, ka, la, ma, ib, jb, kb,
lb, mb, p, q :integer;
PROCEDURE ASOC (n:integer;a:lege; var as:integer);
Label 1;
Var
i,j,k: integer;
begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
if a[a[i,j],k]<>a[j,k],i]
then
begin
as:=0;
goto 1;
end;
as:=1;
1:
end;
PROCEDURE COMUT (n:integer; a:lege; var co: integer);
Label 1;
Var
i,j:integer;
Begin
for i:=1 to n do
for j:=1 to n do
if a[i,j]<> a[j,i]
then
begin
co:=0;
goto 1;
end;
co:=1;
1:
end;
PROCEDURE NEUTRU (n:integer; a:lege; var ne,l: integer);
Label 1,2;
Var
i,j:integer;
Begin
for i:=1 to n do
for j:=1 to n do
86
if not ((j= a[i,j]) and (j= a[j,i]))
then goto 1;
ne:=1; l:=0;
goto 2;
1:
ne:=0; l:=0;
2:
end;
PROCEDURE INVERS
(n,l:integer; a:lege;var iv: integer);
Label 1,2;
Var
i,j:integer;
Begin
for i:=1 to n do
for j:=1 to n do
if ((l= a[i,j]) and (l= a[j,i]))
then goto 1;
iv:=0;
goto 2;
1:
iv:=0;
2:
end;
PROCEDURE DISTRI
(n:integer;a,b:lege; var ds:integer);
Label 1;
Var
i,j,k: integer;
begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
if not (b[i,a[j,k]] =a[b[i,j],b[i,k]]) and (b[a[i,j],k] = a[b[i,k],b[j,k]]) then
begin
ds:=0;
goto 1;
end;
ds:=1;
1:
end;
PROCEDURE GRUP (n:integer;a:lege; var i,j,k,l,m:integer);
var
e: integer;
87
begin
asoc(n,a,i);
comut(n,a,m);
neutru(n,a,j,e);
if j<>1 then
begin
k:= 0;
l:= 0;
end
else
begin
invers(n,e,a,k);
if (i = 1) and (j = 1) and (k = 1) then l:=1
for i:=1 to n do
begin
for j:=1 to n do
read(a[i,j]);
else
l:= 0;
end;
end;
BEGIN {MAIN}
Writeln(‘dati numarul de elemente ale legii de compozitie’);
Readln(n);
readln;
Writeln(‘dati legea B’);
for i:=1 to n do
begin
for j:=1 to n do
read(b[i,j]);
readln;
end;
grup(n,a,ia,ja,ka,la,ma);
asoc(n,b,ib,jb,kb,lb,mb);
if ia:=1 then writeln (‘legea A este asociativa’);
if ja:=1 then writeln (‘legea A are element neutru’);
if ka=1 then writeln (‘fiecare element are un invers’, ‘fata de legea A’);
if la:=1 then
begin
write(‘legea A este o lege de grup’);
if ma:=1 then
write(‘comutativ’);
writeln;
end;
88
if ib:=1 then writeln (‘legea B este asociativa’);
if jb:=1 then writeln (‘legea B are element neutru’);
if kb:=1 then writeln (‘fiecare element are un invers’, ‘fata de legea B’);
if lb:=1 then
begin
write(‘legea B este o lege de grup’);
if ma:=1 then
write(‘comutativ’); writeln;
end;
if not ((la: = 1) and (ib := 1) and (ma := 1)) then
writeln(‘legile A si B nu dau structura de inel’)
else
begin
distri(n,a,b,q);
if q:=0 then
writeln(‘legile A si B nu dau structura de inel’)
else if ((mb:=1) and (jb:=1)) then
writeln (‘legile A si B dau structura de inel’ ,
comutati ,cu element unitate’)
else if mb:=1 then
writeln (‘legile A si B dau structura de inel’,’ comutativ’)
else if jb:=1
then
writeln (‘legile A si B dau structura de inel’ , ’unitar’);
end;
if not ((lb := 1) and (ia: = 1) and (mb: = 1)) then
writeln(‘legile B si A nu dau structura de inel’)
else
begin
distri(n,b,a,q);
if p:=0 then
writeln(‘legile B si A nu dau structura de inel’)
else if ((ma:=1) and (ja:=1)) then
writeln (‘legile B si A dau structura de inel’ , ’comutativ,
cu element unitate’)
else if ma:=1
then
writeln (‘legile B si A dau structura de inel’,’comutativ’)
else
if ja:=1 then
writeln (‘legile B si A dau structura de inel’ ,
’unitar’);
end;
END.
89
ALGORITMI. PENTRU SIRURI ALFANUMERICE

Să se descrie o structură de date ce poate fi asimilată cu structura de


date "STRING" din unele dialecte ale implementării limbajului Pascal şi să
se implementeze funcţiile obişnuite de lucru cu şirurile de caractere :
- Length = determină numărul de caractere din şir
- Substring = întoarce un subşir din şir ( o parte a acestuia )
- Concat = concatenează 2 şiruri
- Delete = şterge un subşir dintr-un şir
- Insert = inserează un şir într-un şir
- Search = caută un şir în altul
- Compare = comparaţie lexicală a două şiruri
- Append = adaugă un caracter la sfârşitul unui şir
Structura ce se propune pentru definirea structurii de date "String" este :
CONST
MaxLength = … ;
TYPE
IndexRange = 0..MaxLength;
String = record
Length : IndexRange;
Chars : array[1..MaxLength] of char
End;
Este evident că se asimilează un şir cu o "înregistrare" (variabilă de tip
"RECORD") ce are 2 componente: lungimea şi caracterele ce alcătuiesc şirul.
1.Operaţia "LENGTH":
a) Descriere: FUNCTION Length(Şir: String): IndexRange
b) Definire intrări / ieşiri: Intrări : şir - de tip String
Iesiri : numărul de caractere în şir
c) Implementarea în Pascal:
FUNCTION Length( Şir: String):IndexRange);
Begin
Length Şir.length
End;
Observaţii:
I ) Se va observa folosirea aceluiaşi nume pentru entitaţi diferite:"Length"atât
pentru numele unei funcţii cât şi pentru denumirea unui câmp al unei înregistrări.
II ) Răspunsul la întrebarea"Nu este ineficientă folosirea unei funcţii de o
singură linie ?",este : Implementarea tipului de date abstract" String" Trebuie ştiută
numai de către proiectant, pentru utilizator aceasta trebuind să fie
transparentă.Dacă utilizatorul ar fi avut acces la câmpul înregistrării s-ar fi violat
conceptul de " tip de data abstract".
2)Operaţia "SUBSTRING"

90
a) Descriere:
PROCEDURE Substring(Şir: String;startpos,num:IndexRange;
Var subşir : string; var error:boolean)
b) Definire intrări / ieşiri:
Intrări :Şir - şirul original
StartPos - poziţia de început
Num - numărul de caractere ale subşirului
Ieşiri : SubŞir - Subşirul de "Num" caractere începând din poziţia
"StartPos"
Error - indicator de eroare : subşirul nu face parte din şirul original
c) Descrierea în Pseudocod:
poziţionează indicatorul de eroare în funcţie de intrări
dacă not error atunci
pentru pos = 1 , Num , 1 execută
atribuie SubŞir.Chars[pos] Şir.Chars[StartPos+Pos+1]
[]
umple restul subşirului cu blancuri
atribuie SubŞir.Length  Num
[]
d) Implementarea în Pascal:
Procedure SubString(Sir:String;StartPos,Num:IndexRange;
Var SubSir:String;Var error : boolean)
Var Pos: IndexRange;
Begin { Sub String }
Error:= StartPos+Num-1>Sir.Length;
if not error then begin { not error }
for pos:=1 to Num do
SubSir.Chars[pos]:=Sir.Chars[StartPos-1];
for pos:=Num+1 to MaxLength do
SubSir.Chars[pos]:= ' ';
Subsir.Length:=Num
end; { not error }
end; { SubString}

3.Operaţia CONCAT
a) Descriere:
Procedure CONCAT(var Sir1:String;Sir2:String;Var error:boolean);
b) Definire intrări / ieşiri:
Intrări : Sir1 - primul şir
Sir2 - al 2-lea şir
Ieşiri Sir1 - concatenarea celor 2 şiruri
Error - Dacă lungimea totală > MaxLength
c) Descrierea în Pseudocod
calculează lungimea totală
91
atribuie errorlungimea totală>MaxLength
dacă not error atunci
atribuie LastPoslungimea Sir1
pentru pos=1,lungimea Sir2 , 1 execută
atribuie LastPosLastPos+1
atribuie Sir1.Chars[LastPos]Sir2.Chars[pos]
[]
[]
atribuie lungimea Sir1  LastPos
d) Implementarea în Pascal:
procedure CONCAT(var Sir1:String;Sir2:String;var error:boolean);
var Len,Pos,LastPos:IndexRange;
begin{Concat}
len:=Sir1.Length+sir2+length;
error:=len>maxlength;
if not error then begin
LastPos :=Sir1.Length;
for : pos :=1 to Sir2>Length do begin
Lastpos:=Lastpos+1
Sir1.Chars[LastPos]:=Sir2.Chars[pos];
End;
Sir1.Length:=lastPos;
End;{not error}
End;{Concat }
4. Operaţia DELETE
a) Descriere:
Procedure Delete ( var sir : String; pos,num:IndexRange;var error:boolean);
b) Definire intrări / ieşiri
Intrări Sir - şirul din care se şterge
Pos - poziţia din care se şterge
Num - numărul de caractere de şters
Ieşiri : Sir - noul şir
Error - semnalizează că subşirul ce se şterge este / nu este în
interiorul şirului dat
Se vor folosi procedurile deja scrise : SubString şi Concat
c) Descriere în PSEUDOCOD
calculează poziţia ultimului caracter ce se şterge
error este True dacă ultima poziţie nu e în şir
dacă not error atunci
extrage subşirul de la dreapta părţii ce se şterge
extrage subşirul de la stânga părţii ce se şterge
concatenează cele 2 subşiruri
[]

92
d) Implementarea în Pascal
Procedure delete(var sir:string;pos,num:IndexRange;
Var error : boolean );
Var sir1:string;
Lastpos:indexrange;
Suberror:boolean;
begin { Delete }
lastpos:= pos+num-1;
error :=lastpos>sir.length;
if not error then begin
substring(sir,sir1,lastpos+1,sir,length-lastpos,suberror);
substring(sir,sir,1,pos-1,suberror);
concat(sir,sir1,suberror);
end;
end;{delete}
5.Operaţia Insert
a) Descriere:
Procedure Insert(var sir :string;sir1:string;pos:indexrange;var
erroe:boolean);
b) Definire intrări/ieşiri:
Intrări : sir - şirul în care se inserează
sir1 - şirul care se inserează
pos - poziţia de unde se inserează
Ieşiri: sir - şirul iniţial în care a fost inserat sir1
error - testează dacă pos este în interiorul şirului iniţial şi dacă
lungimea şirului nou > MaxLength
Se folosesc din nou procedurile deja scrise Substring şi Concat
c) Descrierea în Pseudocod:
atribuie error  (pos>lungime sir) sau ( lungimea totală > MaxLength)
dacă not error atunci
extrage subşirul ce începe din poziţia în care se inserează
extrage subşirul ce precede poziţia în care se inserează
concatenează cu sirul sir1
concatenează rezultatul cu primul subsir extras
[]
d) Implementarea în Pascal
Procedure insert(var sir : String; sir1:String; pos: IndexRange;
var error: boolean)
var SirTemp : String;
Suberror : Boolean;
Begin {insert }
Error:=(pos> Sir.Length)or(Sir.Length+Sir1.Length>MaxLength);
If not error then begin
Substring(Sir,sirtemp,pos,sir.length-pos+1,suberror);
93
Substring(sir,sir,1,pos-1,suberror);
Concat(sir,sir1,suberror);
Concat(sir,sirtemp,suberror);
End;
End;{insert}
6.Operaţia Search
a) Descriere:
Procedure Search(sir,subsir:string;var found:boolean;
var pos:indexrange;var error:boolean);
b) Definire intrări/ieşiri
Intrări : sir - sirul în care se caută
Subsir-şirul ce se caută
Ieşiri : Found- semnalizează găsirea/negăsirea subşirului căutat
Pos - dacă se găseşte poziţia în care se află subşirul căutat în şir
Error - semnalizează şiruri vide sau lungimea subşirului ce se caută
este > lungimea şirului în care se caută
c) Descrierea în Pseudocod :
O primă variantă a algoritmului este:
- se caută apariţia primului caracter din subşir
- dacă nu apare atunci nu există
- dacă apare atunci vom continua cu apariţia celorlalte caractere
- dacă le găsim pe toate căutarea se termină cu succes
- dacă se întâlneşte un caracter ce nu se potriveşte ne întoarcem la început
- procesul se opreşte la succes sau atunci când numărul caracterelor
rămase de verificat este mai mic decât lungimea subşirului ce se caută.
Prin rafinarea enunţurilor nestandard ,algoritmul devine :
atribuie error (sirurile sunt de lungime 0) sau (subşirul > şirul în care se
caută)
dacă not error atunci
atribuie foundfalse;încătrue;PosCrt1;
cât timp mai e de căutat şi încă nu s-a găsit execută
dacă primul car în Subşir=car din poziţia crt atunci
verifică restul SubSir cu următoarele poz în Sir
altfel incrementează poziţia crt în Sir
[]
atribuie încă (mai sunt posibilităţi de verificare)şi
(mai sunt caractere în Sir)
[]
dacă s-a terminat căutarea cu succes atunci
atribuie pospoziţia crt din Sir
[]
d) Implementare în Pascal :
procedure Search(sir,subsir:string;varfound:boolean;
var pos:indexrange;var error:boolean);
94
var stpos,subpos:indexrange;
match,inca:boolean;
begin {Search }
error:=(sir.length=0)or(subsir.length=0)or(sir.length<subsir,length);
if not error then begin
stpos:=1;
found:=false;inca:=true;
while inca and not found do begin {inca}
if subsir.chars[1]=sir.chars[stpos]then begin
subpos:=1
match:=true;
while(subpos<subsir.subsir.length)and match do
if subsir.chars[subpos+1]=sir.chars[stpos+subpos]
then subpos:=subpos+1
else begin
match:=false;
stpos:=stpos+1
end;
found:=match;
end
else stpos:=stpos+1;
inca:=(stpos+subsir-1)<=sir.length
end{inca}
if found then pos:=stpos;
end{not error}
end;{search}

Să se scrie un program care tipăreşte distribuţia frecvenţei lungimilor


cuvintelor aflate într-un fişier text.Cuvintele sunt separate prin blancuri
a) Descrierea algoritmului în limbaj natural.
Se va adopta următoarea strategie : se citeşte câte o linie din fişier şi se extrag
apoi cuvintele din acesta. Cuvintele sunt de tipul "String" definit anterior.Pentru
determinarea lungimii se foloseşte o funcţie "Length" ce întoarce un întreg.
Frecvenţa lungimii se memorează într-un tablou de [lmax+1] întregi.De la 1
la lmax sunt memorate frecvenţele de apariţie (în poziţia dată chiar de lungime) a
cuvintelor cu lungime<=Lmax, în poziţia "lmax+1]se memorează apariţiile tuturor
cuvintelor a căror lungime este mai mare decât lmax.
b) Descrierea şi semnificaţia structurilor de date folosite:
fis : fişierul text ce se prelucrează
Nume : numele fişierului (sir de caractere)
cod_open :cod returnat de funcţia de deschidere a fişierelor (open)
linie : şir de caractere în care se citeşte o linie
lLinie : indice în cadrul liniei
Cuvânt : şir de caractere ce conţine un cuvânt
95
lungime : lungimea unui cuvânt
Frecvenţa : tablou de lungimi(întregi)ale cuvintelor
gata : indicator(flag) pentru indicarea terminării prelucrării unei linii
i : contor,întreg
c) Descrierea algoritmului în Pseudocod:
citeşte numele fişierului
repetă
citeşte o linie din fişier
cât timp sunt cuvinte în linie execută
extrage cuvântul următor
calculează lungimea lui
actualizează frecvenţa apariţiei
[]
până sfârşit de fişier
[]
scrie frecvenţa apariţiei cuvintelor
stop
Pentru extragerea unui cuvânt şi calculul lungimii sale se vor folosi 2
proceduri.
d) Programul în limbajul Pascal
Program frecventa;
Label 13;
const lmax=20; { cuvintele au lungimea maxima=20}
l1=21;
type
file_name=packed array[1..17] of char;
tip_linie=array[1..80] of char;
tip_cuvant=record
lungime:integer;
chars:array[1..21]of char;
end;
var
fis:text;
nume:file_name;
cod_open:integer;
linie:tip_linie;
Ilinie:integer;
cuvant:tip_cuvant;
gata:boolean;
lungime:integer
I:integer
Frecventa:array[1..l1]of integer;
Procedure extrag(var cuvant:tip_cuvant);
var
96
Icuvant:integer;
gata:boolean;
lung:integer
begin {extrag }
Icuvant:=0;
lung:=0;
gata:=Ilinie>80;
while not gata do begin {extrag cuvant}
car:=linie[Ilinie];
if car in ['A'..'Z'] then begin {lit}
Icuvant:=icuvant+1;
cuvant.chars[Icuvant]:=car;
Ilinie:=Ilinie+1;
lung:=lung+1
gata:=Ilinie>80;
end{lit}
else if car= ' ' then begin {bl}
Ilinie:=Ilinie+1;
gata :=Ilinie>80;
while not gata do begin {elimin blancuri}
if linie[ilinie]<> ' ' then gata:=true
else begin
Ilinie:=Ilinie+1;
gata :=Ilinie>80;
end;
end; {elimin blancuri}
gata:=true;
end; { bl }
end; { extrag cuvant }
cuvant.lungime:=lung;
end; { extrag }
Function length(cuvant:tip_cuvant):integer;
begin { Length }
length:=cuvant.lungime;
end; { Length }
begin { main }
write('Numele fişierului');readln(name);
reset(fis,nume,,cod_open);
if cod_open=-1 then begin
writeln('eroare deschidere fisier');
goto 13
end;
for I:= 1 to lmax+1 do frecventa [i]:=0;
repeat
97
Ilinie:=1;
gata:=eof(fis);
while not gata do begin { not gata}
readln(fis,linie);{citesc 1 linie}
extrag(cuvant);
lungime:=length(cuvant);
while lungime >0 do begin {sunt cuvinte}
if lungime< lmax+1 then frecventa[lungime]:=frecventa[lungime]+1
else frecventa[lmax+1]:=frecventa[lmax+1];
extrag(cuvant);
end;{sunt cuvinte}
end;{not gata}
until eof(fis);
for i:=1 to lmax+1 do writeln('Lungime=',I:2,'aparitii=',frecventa[I]);
end.

Să se scrie un program care calculează şi tipăreşte numărul cuvintelor


dintr-un text care nu conţin cel puţin 3 vocale distincte.Textul se află
mamorat pe disc într-un fişier creat anterior al cărui nume se cere de la
terminal.Cuvântul este alcătuit din litere şi cifre şi sunt delimitate prin
caracterele:{'.' , ',' , ';', ' '}.
a) Descrierea algoritmului în limbaj natural:
Se citeşte dintr-un fişier de tip "text"câte o linie .Se desparte în cuvinte,iar
pentru fiecare cuvânt se contorizează numărul de vocalecomponente folosindu-se o
mulţime în care se introduc acestea.
b) Descrierea şi semnificaţia structurilor de date folosite:
fis : fişierul text ce se prelucrează
nume : numele fişierului
cod_open : cod returnat de funcţia de deschidere a fişierelor
car : caracterul ce se prelucrează
Mvocale : mulţimea vocalelor
Ncuvinte : nr. Cuvintelor cu mai mult de 3 vocale
Nvocale : nr. Vocalelor dintr-un cuvânt
gata : indicator pentru semnalizarea terminării prelucrării unei linii
c) Descrierea algoritmului în Pseudocod:
citeşte numele fişierului
iniţializează numărul cuvintelor
repetă
iniţializează mulţime vocale
cât timp nu s-a terminat cuvântul execută
citeşte şi tratează un caracter
[]

98
dacă numărul vocalelor distincte >=3 atunci incrementează numărul
cuvintelor
[]
până la sfârşitul fişierului
[]
tipăreşte numărul cuvintelor
Pentru detalierea acţiunilor mai importante se fac câteva observaţii:
1)Se prezintă o variantă pentru dialeatul Pascal implementat sub sistemul de
operare MIX, de pe minicalculatoarele tip Independent I 102F/4M, sau
compatibile.
2)Numele fişierului din care se citeşte textul este memorat într-o variabilă de
tip:
packed array[1..max_name]of char; datorită faptului că operaţia de citire a
valorilor unor astfel de variabile permite citirea într-o singură operaţie a ei (nu
ciclat pentru fiecare caracter ce o alcătuie
Max_Name este o constantă aleasă astfel încât să poată fi memorat cel mai
lung nume valid de fişier. Se ştie că acesta poate fi: "nnnnnnnnn.ttt;vvv"
unde: nnnnnnnnn - numele,maxim 9 caractere
ttt - tipul,maxim de 3 caractere
vvv - versiunea,maxim 3 caractere
astfel încât : Max_Name=17;
3)În exploatarea fişierelor se va folosi o variabilă de tip "integer"pentru a
detecta erorile la deschiderea fişierelor.Ovaloare=-1 a acestei variabile va indică
eşecul operaţiei de deschidere a fişierului respectiv.
4)Detalierea operaţiei de testare de sfârşit de fişier impune şi refacerea citirii
din fişier pentru a testa apariţia sfârşitului de fişier.
d) Programul Pascal;
Program vocale ;
Label 13;
const Max_Name=17;
type file_name=packed array[1..max_name]of char;
multime=set of char;
var fis :text;
nume :file_name;
ncuvine,nvocale:integer;
mvocale:multime;
car :char;
gata :boolean;
cod_open:integer;
BEGIN {main}
write('Numele fisierului text:');readln(nume);
reset(fis,nume, ,cod_open);{atentie la parametrii !}
if cod_open= -1 then
begin
99
writeln('Eroare deschidere fişier!');
goto 13;
end;
ncuvinte:=0;
repeat
mvocale:=[]{multimea vocalelor din cuvant -vida}
nvocale:=0;
gata:=false;
while not gata do
if eof(fis) then gata:=true
else
begin {in fisier}
read(fis,car);
if eoln(fis) then
begin {sfarsit de linie}
readln(fis);
gata:=true;
end
else
begin {caracter normal}
if car in['.',',',';',' '] then gata:=true
else
if not (car in ['A'…'Z','0'…'9'])then
writeln('caracter nepermis');
else
if car in(['A','E','I','O','U']- mvocale )then
begin
mvocale:=mvocale+[car];
nvocale:=nvocale+1;
end;{caracter normal}
end;{sfarsit de linie}
end;{in fisier}
if nvocale>=3 then nvocale:=nvocale+1;
until eof(fis);
writeln('Nr. cuvintelor cu prop. ceruta :' , ncuvinte:8);
13 :
END.

Să se elaboreze programul pentru punerea în pagină a unui text


înregistrat într-un fişier de intrare cu lungimea maximă a unei linii
specificată(80 caractere)
Se cunoaşte că:
- în fişierul de intrare cuvintele sunt separate prin cel puţin un blanc;
- un cuvânt nu se poate continua pe două linii;
100
- lungimea maximă a unui cuvânt este mai mică decât N/2
În textul rezultat se cere ca la început de linie să fie un început de cuvânt,iar
sfârşitul liniei să coincidă cu sfârşitul unui cuvânt .În acest scop spaţiile se
distribuie uniform şi simetric.
Face excepţie ultima linie.
a) Descrierea algoritmului în limbaj natural :
Se citeşte fişierul de intrare linie cu linie.În cadrul fiecărei linii se extrag
cuvintele,se contorizează lungimea acestora şi se calculează numărul de
blancuri dintre cuvinte care se adaugă în linia de ieşire.
b) Descrierea şi semnificaţia structurilor de date folosite:
fisin,fisout : fişiere de intrare/ieşire
namein,nameout : numele fişierelor
cod_open : codul operaţiei de deschidere fişier
linie : şir de caractere în care se preia o linie din fişierul de intrare
c) Descrierea algoritmului în Pseudocod :
initializeaza variabile, deschide fisierele de lucru
repeta
citeste linie
daca nu este ultima linie atunci executa Aranjare(linie)
[]
scrie linie pana la sfarsitul fisierului de intrare
[]
În acest moment se evidenţiază folosirea unei variabile ce conţine o întreagă
linie din fişier : "linie".
Testul:"nu este ultima linie"se materializează în testarea variabilei predefinite
eof(fisier de intrare) care se poziţionează la valoarea "true" la întâlnirea sfârşitului
de fişier,după ce s-a citit ULTIMA linie; deci în "linie" se află ultima linie iar
eof(fis in) este true.
Toate acţiunile de aranjare a liniei se fac în procedura "Aranjare".Algoritmul
acesteia este descris în Pseudocod:
repeta
(1) elimina blancurile
(2) extrage un cuvant
pana la sfarsitul liniei
[]
determinarea numarului de blancuri ce trebuie adaugate
determinarea numarului minim de blancuri intre 2 cuvinte
determinarea "surplusului" de blancuri
determina pozitia in care se vor adauga surplusul de blancuri
repeta
(3) scrie un cuvant
(4) scrie blancurile intre 2 cuvinte
daca pozitia o impune atunci
(5) adauga blancuri suplimentare
101
[]
pana se termina toate cuvintele
[]
Fiecare dintre acţiunile (1)…(5) va fi îndeplinită de câte o procedură.
Scrierea va fi de fapt o copiere în aceeaşi variabilă transimsă ca parametru de
intrare , ce devine astfel şi parametru de ieşire.
Prin calculele ce se fac pentru determinarea numărului de blancuri între 2
cuvinte se asigură "alinierea la dreapta"cerută de enunţ.
În momentul extragerii unui cuvânt din linie se asigură şi memorarea acestuia,
precum şi contorizarea caracterelor utile.
d)Programul Pascal :
Program Ws;
Label 13;
Const lungime = 80;
lungcuvant = 40;
nmaxcuvinte = 40;
lungname =17;
type
tip_linie= packed array[1..lunglinie]of char;
tip_cuvant= packed array[1..lungcuvant] of char;
name_file=packed array[1..lungname]of char;
multime_de_cuvinte=array [1..nmaxcuvinte]of tip_cuvant;
var
linie: tip_linie;
fisin,fisout : text;
namein,nameout:name_file;
cod_open :integer;
PROCEDURE INIT;
begin {init}
readln(namein,nameout);
end;{init}
PROCEDURE ARANJARE (var linie:tip_linie);
var Ilinie:integer;
Icuvinte:multime_de_cuvinte;
Icuvant:integer;
Iintre:integer;
impar:boolean;
ncar,ncuvinte,nblancuri,nminblancuri, nsurplus,low,high,mid:integer;
begin {aranjare}
ilinie:=1;
icuvant:=0;
ncar:=0;
repeat
elimin_blancuri;
102
extrag_cuvant;
until ilinie>lung_linie;
ncuvinte:=icuvant;
if ncuvinte>1
then
begin { > 1}
blancuri:=lunglinie-ncar;
nintre:=ncuvinte-1;
nminblancuri:=nblancuri-nminblancuri;
high:=nintre-low+1;
low:=nsurplus / 2;
high:=nintre-low+1;
low:=nsurplus div 2;
impar:=nsurplus mod 2 <>0;
if impar then
mid := nintre div 2;
end;{>1}
ilinie :=1;
if ncuvinte=1
then
begin {1}
scrie(cuvinte(1));
adauga_blancuri;
end {1}
else
begin
intre:=1;
for icuvant:=1 to ncuvinte-1do
begin
scrie(cuvinte(icuvant));
pun_blancuri(nminblancuri);
if intre <=low then add_1_blanc;
if intre>=high then add_1_blanc;
if impar and (iintre=mid) then
add_1_blanc;
iintre=iintre+1;
end;
scrie(cuvinte(ncuvinte));
end;{else}
end;{aranjare}
PROCEDURE ELIMIN BLANCURI;
var inca:boolean;
begin{elimin blancuri}
inca:=ilinie<=lunglinie;
103
while inca do
begin
if linie[ilinie]=' ' then
begin
ilinie:=ilinie+1;
inca:=ilinie<=lunglinie
end
else inca:=false;
end;
end;{elimin blancuri}
PROCEDURE EXTRAG_CUVINT;
var inca:boolean;
extras:boolean;
icar:integer;
i:integer;
Begin {extrag_cuvant}
icar:=0;
inca:=ilinie<=lunglinie
extras:=inca;
if extras then icuvant:=icuvant+1;
while inca do
begin { inca }
if linie[ilinie]<>' ' then
begin
icar:=icar+1;
cuvinte[icuvant,icar]:=linie[ilinie]
ncar:=ncar+1;
ilinie:=ilinie+1;
inca:=ilinie<=lunglinie;
end
else inca:=false;
end{inca}
if extras then
for i:= icar + 1 to lungcuvant do
cuvinte[icuvant,I]:=' ' ;
end;{extrag_cuvant}
PROCEDURE SCRIE(word:tip_cuvant);
var I:integer;
begin {scrie}
i:= 1;
while word[I]<>' ' do
begin
linie[ilinie]:=word[I];
ilinie:=ilinie+1;
104
i:=i+1;
end{while}
end;{scrie}
PROCEDURE PUN_BLANCURI (number:integer);
var I:integer;
begin {pun blancuri}
i:=1;
while i<=number do
begin
linie[ilinie]:=' ';
ilinie:=ilinie+1;
i:=i+1;
end{while}
end;{pun blancuri}
PROCEDURE ADD_1_BLANC;
begin{add_1_blanc}
linie[ilinie]:=' ';
ilinie:=ilinie+1
end ;{add_1_blanc}
BEGIN{main}
init;
reset(fisin,namein,,cod_open);
if cod_open=-1
then
begin
writeln('Eroare in fis. de intrare');
goto 13;
end;
rewrite(fisout,nameout,,cod_open);
if cod_open=-1
then
begin
writeln('Eroare in fis. de iesire');
goto 13;
end;
while not eof(fisin) do begin {write}
readln(fisin,line);
if not eoln(fisin) then Aranjare(linie);
fclose(fisin);
fclose(fisout);
writeln(fisout,linie);
end;{write}
13: close(fisin);
close(fisout);
105
END.

Să se realizeze un program ce îndeplineşte funcţiile unui calculator de


buzunar: primeşte la intrare un şir de caractere ce formează numere întregi
şi/sau reale şi operaţii '+' , '-' , '*' , '/' şi dă la ieşire rezultatul operaţiilor.
Nu sunt admise reprezentări ale numerelor reale decât în forma:X[.Y], unde X
este partea întreagă, Y partea fracţionară,iar [ ] indică faptul că partea fracţionară
poate lipsi.
Operaţiile se execută în ordinea introducerii lor.
Terminarea şirului de intrare se semnalizează prin caracterul egalitate " = ".
a) Descrierea algoritmului în limbaj natural:
Algoritmul general este foarte clar:după citirea liniei de intrare se extrag
numerele şi operatorii şi se efectuează operaţiile pe măsura apariţiei lor.
Problema principală o constituie această "extragere" de numere şi operaţii.
Operaţia de extragere se face cu ajutorul unei proceduri ce operează asupra unor
parametrii globali :
linie - din care se citesc caracterele
ilinie - indicele curent unde se citeşte în linie
nr - valoarea numerică extrasă
car - caracterul citit
Această procedură apelează o altă procedură ce " citeşte " următorul caracter;
de fapt " aduce " din linia citită următorul caracter.
Citirea liniei se face extrem de simplu ţinând cont de proprietăţile valorilor de
tip "packed array".
b)Descrierea şi semnificaţia structurilor de date folosite:
linie : sir de caractere - linia ce conţine operaţiile
ilinie : indice în cadrul liniei
car : caracterul curent prelucrat
cifre : mulţimea cifrelor permise
operatori:mulţimea operatorilor permişi
nr : valoarea numărului introdus
rez : valoarea rezultatului
erroare : indicator (flag) de eroare
gata : indicator (flag) pentru sfârşitul operaţiilor
altcar : variabilă auxiliară
b) Descrierea în Pseudocod:
execută init
execută citlinie
execută citcar
daca not (car in cifre) atunci
scrie ' erroare 0 '
atribuie eroare true
altfel
execută citnr;
106
dacă not eroare atunci
atribuie reznr
repetă
dacă not ( car in operatori) atunci
scrie'eroare 1'
atribuie eroaretrue
altfel
alege car dintre
'=': atribuie gata true;
'+','-','*': execută cit car;
dacă not (car in cifre) atunci
scrie 'Eroare 2'
atribuie eroaretrue
altfel
execută citnr;
dacă not eroare atunci rez rez op nr
[]
'/':execută citcar;
dacă not (car in cifre) atunci
scrie'Eroare 3'
atribuie eroaretrue
altfel
execută citnr;
dacă not eroare atunci
dacă nr=0 atunci
scrie 'Eroare 4'
atribuie eroaretrue
altfel rezrez/nr
[]
[]
[]
[]
[]
pană gata sau eroare;
[]
[]
[]
daca not eroare atunci
scrie "rezultatul=",rez
[]
Detalierea procedurilor este:
Procedura Citcar este:
daca ilinie > lunglinie atunci
atribuie car'@'
107
altfel
atribuie carlinie[ilinie]
atribuie ilinieilinie+1
[]
sfârşit citcar
Procedura citnr este:
atribuie nr0;incatrue;punct0
cat timp inca executa
atribuie nrnr*10(ord(car)-ord('0'))
executa citcar
cat timp car='.' executa
atribuie punct punct+1
executa citcar
[]
atribuie inca (car in cifre) si (punct <2)
[]
daca punct >=2 atunci
scrie 'Eroare 0'
atribuie eroaretrue
[]
sfârşit citnr
c)Programul Pascal
Programul pocket_calculator;
const maxlinie=80;
type
tip_linie= packet array [1..maxlinie]of char;
multime= set of char;
var
linie : tip_linie;
ilinie : integer;
car,altcar: char;
nr,rez :real;
eroare: boolean;
gata : boolean;
cifre : multime;
operatori:multime;
PROCEDURE AFIERR(nreroare:integer);
begin
eroare:=true;
case nreroare of;
0 : writeln('Primul caracter trebuie sa fie o cifra');
1 : writeln('Operator necunoscut');
2 : writeln('Caracter interzis dupa un operator');
3 : writeln('Caracter interzis');
108
4 : writeln('Numitor nul intr-o operatie de impartire');
5 : writeln('Numar real in format eronat');
end;{case}
end;
PROCEDURE INIT;
begin
cifre:=['0'..'9'];
operatori :=['+','-','*','/','='];
ilinie:=1;
gata:=false;
eroare:=false;
end;
PROCEDURE CITLINIE;
var i: integer;
inca:boolean;
begin {citlinie}
readln(linie);
lunglinie:=0;
i:=1;
inca:=linie[1]<>' ';
while inca do
begin
lunglinie:=lunglinie+1;
i:=i+1;
inca:=(linie[i]<>' ') and(i<maxlinie)
end;
end; {citlinie}
PROCEDURE CITCAR;
begin
if ilinie>lunglinie then car:='@'
else
begin
car:=linie[ilinie];
ilinie:=ilinie+1;
end;
end;{citcar}
PROCEDURE CITNR;
var inca :boolean;
punct :integer;
begin
nr:=0;
inca:=true;
punct:=0;
while inca do
109
begin
nr:=nr*10+(ord(car)-ord('0'));
citcar;
while car='.' Do
begin
punct:=punct+1;
citcar;
end;
inca:=(car in cifre) and (punct <2);
end;
if punct > 2 then afierr(5);
end{citnr}
BEGIN{main}
init;
citlinie;
citcar;
if not (car in cifre) then afierr(0)
else
begin {0}
citnr;
if not (car in operatori) then
begin{1}
rez:=nr;
repeat
if not (car in operatori) then
afierr(1)
else {testarea operatorului}
case car of
'=' : gata:=true;
'+','-','*':
begin
altcar:=car;
citcar;
if not(car in cifre) then
afierr(2)
else
begin
citnr;
if not eroare then
if altcar='+' then
rez:=rez+nr
else
if altcar='-' then
rez:=rez-nr
110
else
rez:=rez*nr;
end;
end;
'/':begin{/}
citcar;
if not (car in cifre) then
afierr(3)
else
begin
citnr;
end;{/}
end {case}
until gata or eroare;
if not eroare
then
writeln('rezultatul :,rez);
end;{1}
end;{0}
END.

TIPUL ÎNREGISTRARE

Pentru o grupă de studenţi (cel mult 30 de studenţi) se cunosc numele


studenţilor (pe cel mult 15 caractere) şi cele 6 note obţinute la sfârşitul semestrului.
Se cere să se afişeze notele obţinute în ordinea descrescătoare a mediilor.
Soluţie :
a)Descrierea algoritmului în limbaj natural:
Pentru fiecare student se va citi numele şi notel obţinute şi se va
calcula media. Se ordonează mediile în ordine descrescătoare şi în final se afişează
studenţii, notele şi mediile obţinute în ordine descrescătoare a mediilor.
b)Descrierea şi semnificaţia structurilor de date folosite:
nmax: numărul maxim de studenţi
n : numărul curent de studenţi
stud : înregistrare cu următorele cupluri:
-nume:numele studenţilor, tablou de 15 caractere
-note: notele studentului, tablou de 6 întrgi
-media: media studentului, variabila reală
y : copie a mediilor studenţilor, şir de numere reale
x : tablou de întregi, conţinând în final poziţiile studenţilor în
ordine descrescătoare a mediilor
i,j : variabile contor
s : variabilă reală, folosită la calculul mediei
grupa : tablou de înregistrări
111
c)Descrierea algoritmului în Pseudocod:
O primă variantă a algoritmului ar fi:
citeşte n
pentru i = 1, n, 1 execută
 Citeşte nume, note student
 Calculează medie
 Copiază medii în y
[]
ordonează medii şi vector poziţii
scrie tablou ordonat
stop
Informaţiile despre un student sunt organizate sub forma unei înregistrări
având structura:
Type stud = record
nume: array [1..15] of char;
note: array [1..6] of integer;
medie: real;
end;
Grupa reprezintă un tablou de astfe de înregistrări:
grupa: array [1..nmax] of stud;
Pentru exemplul dat avem:
Const = 30;
Operaţiile “citeşte nume şi calculează medie” se realizează asfel:
pentru j = 1, 15, 1 execută
citeşte grupa[i] . nume[j]
atribuie s  0
pentru j = 1, 6, 1 execută
citeşte grupa[i] . note[j]
atribuie s  s + grupa[i] . note[j]
[]
atribuie medie  s/6
[]
Operaţia “copiază medie în y” implică copierea câmpului medie a
studenţilor, ,componentă cu componentă în vectorul y prin:
pentru j = 1, n, 1 execută
atribuie y[i]  grupa[i] . medie
[]
Pentru ordonare, în tabloul x se introduc iniţial numerele de ordine ale
studenţilor din grupa, prin:
pentru i = 1, n, 1 execută
atribuie x[i] i
[]

112
Operaţia “ordonează medie şi vector poziţii ” implică ordonarea tabloului y,
cu inversările corespunzătoare ale elementelor tabloului x, adică:
repetă
atribuie k  0
pentru i = 1, n-1, 1 execută
dacă y[i] < y[i+1]atunci
atribuie s  y[i], y[i]  y[i+1], y[i+1] s
m  x[i], x[i]  x[i+1], x[i+1] m
k 1
[]
[]
până k=0
[]
Întrucât tabloul de înregistrări ’grupa nu a fost modificat prin ordonare, ci
doar tabloul x cu poziţiile studenţilor astfel încât prima componentă a acestuia
conţine numărul de ordine al studentului cu media cea mai mare, operaţia ‘scrie
tablou ordonat’, implică:
- selectarea pe rând a componentelor tabloului x prin:
atribuie m  x[i]
- scrierea câmpurilor nume, note şi medie ale componentei grupa [nr], prin
secvenţa:
pentru i = 1, n, 1 execută
atribuie m  x[i]
pentru j = 1, 15, 1 execută
scrie grupa[m] . nume[j]
pentru j = 1, 15, 1 execută
scrie grupa[m] . note[j]
[]
[]
scrie grupa[m] . medie
[]
d)Programul Pascal:
Program grupa;
Const
nmax=30;
type stud = record
nume: array [1..15] of char;
note: array [1..6] of integer;
medie: real;
end;
var
grupa : array [1..nmax] of stud;
y : array [1..nmax] of real;
x : array [1..nmax] of integer;
113
s : real;
i,j,n,m:integer;
BEGIN{main}
Write(’n=’); readln(n);
for i:=1 to n do
with grupa[i] do
begin
for j:=1 to 15 do
read(nume[j]);
S:=0
for j:=1 to 6 do
begin
read(note[j]);
S:=S + note[j];
end;
S:=S/6;
end;
for i:=1 to n do
begin
y[i]:= grupa[i]. medie;
x[i] := 1
end;
repeat {ordonare}
k:=0;
for i:=1 to n-1 do
if x[i]< x[i+1] then
begin
s := y[i];
y[i] := y[i+1];
y[i+1] :=s;
m := x[i];
x[i] := x[i+1];
x[i+1] :=m;
k :=1;
end;
until k :=0;
for i:=1 to n do
begin {scrie tabel}
m:= x[i];
with grupa[m] do
begin
for j:=1 to 15 do
write(nume[j]);
for j:=1 to 6 do
114
write(note[j]);
S:=S + note[j];
Writeln(medie:6:2);
end;
end;
END.

Să se alcătuiască clasamentul diviziei A la fotbal, în urma disputării


meciurilor unei etape.
a)Descrierea algoritmului în limbaj natural:
Clasamentul înaimntea etapei este dat prin:
- numele echipei (pînă la 10 caractere)
- numărul de jocuri: disputate, câştigate, pirdute, egale (sub forma a1 numere
întregi)
- numărulde puncte acumulate,
- golavereajul, dat prin numărul total de puncte marcate şi prin numărul de
puncte primite.
Rezultatul etapei se dă sub forma :
-nume echipă gazdă
-puncte marcate
-nume echipă oaspete
-puncte marcate
În aceste condiţii se introduce clasamentul prin numele fiecărei echipe,
însoţite de numărul de jocuri disputate, câştigate, pierdute şi egale, numărul de
puncte acumulate, numărul total de puncte acumulate şi golaverajul prin numărul
total de puncte marcate şi primite. Se introduce rezultatul etapei prin numele
echipei gazdă şi punctele marcate de gazdă, precum şi numele echipei oaspete
împreună cu numărul de puncte marcate.
În final se afişeză clasamentul actualizat.
b)Descrierea şi semnificaşia structurilor de date folosite:
Informaţiile asupra echipei sunt organizate sub forma unei înregistrări
cu structură:
Type echipa = record
Nume: nume echipă;
Jucat,vict,pierd,egal: 0..nr jocuri;
Puncte: 0..pctaj max ;
Gtmarc,gtprim:integer
End;
Clasamentul reprezintă un tablou de astfel de înregistrări:
Type clasament = array [1..nr echipe] of echipa;
Pentru campionatul nostru de fotbal avem:
Const nr echipe = 18;nr jocuri = 34; pctaj max =68;
Prin gmarc respectiv gprim se reprezintă numărul de goluri marcate
respectiv primite.
115
c)Descrierea algoritmului în Pseudocod:
O formulare generală a soluţiei problemei este:
 citire clasament
 citire rezultate etape şi actualizare clasament
 afişare clasament
stop
Operaţia ‘citire clasament’ se detaliază asfel:
pentru i = 1, nr echipe, 1 execută
citeşte’nume şi celelalte informaţii în componenta i din
clasament ’
[]
Operaţia ‘citire rezultate etape şi actualizare clasament’ se detaliază asfel:
pentru i = 1, nr echipe/2, 1 execută
citeşte echipele şi rezultatul
actualizarea golaverajului pentru ambele echipe
adună 1 la numărul de partide jucate de ambele echipe
alege rezultat dintre
victorie:-pentru echipa gazdă adună 1 la victorie şi 2 la punctaj
-pentru echipa oaspete adună unu la pierderi
egalitate:-pentru ambele echipe adună 1 la meciuri egale şi la
punctaj
pierdere:-pentru echipa oaspete adună 1 la victorie şi 2 la
punctaj
-pentru echipa gazdă adaugă 1 la pierdere
[]
[]

Variabila rezultat se declară asfel :


Var rezultat: (victorie, egalitate , pierdere);
Şi valoarea ei se stabileşte astfel:
Dacă gmarc-gprim >0 atunci
Atribuie rezultat  victorie
Asfel
Dacă gmarc-gprim < 0 atunci
Atribuie rezultat  pierdere
Asfel
Atribuie rezultat  egalitate
[]
[]
În fucţie de rezultatatele etapei se oprează modificări în tabelul clas, declarat
prin: Var clas: clasament;
Ceea ce presupune localizarea după nume a fiecărei echipe în acest tablou. În acest
scop se va utiliza o fucţie:

116
Function localizare (nech: nume echipă):poziţie;
unde tipul poziţie este declarat ca un subdomeniu prin:
Type poziţie = 1..nr echipe
În urma actualizării clasamentuli, acesteatrebuie sortat în ordinea
descrescătoare a punctajului,( la punctaj egal se va folosi criteriul golaveraj), asfel
încât acţiunea ‘afişare clasament’ se detaliază în :
-sortare clasament dupăpuncttaj şi golaveraj
-afişare tablou ordonat
Sortarea tabloului clas se va face prin metoda contorizării inversărilor.
Programul va fi structurat pe proceduri, câte una pentru fiecare acţiune a
algoritmului
b)Programul Pascal arată astfel:
Program fotbal;
Const
Nr.echipe=18;
Nr.jocuri=34;
Pctaj max=68;
Type
Nume echipe = array[1..10] of char;
Pozitie = 1..nrechipe;
Echipa = record
Nume:nume echipa;
Jucat, vict,pierd,
egal : 0.. nrjocuri;
Puncte: 0..pctajmax;
Gtmarc,gtprim: integer;
end;
clasament = array [pozitie] of echipa;
var
rezultat : (victorie, egalitate, pierdere);
clas: clasament;
PROCEDURE CITNUME (var ne : nume echipa);
var i:= 1..10;
begin
For i:=1 to 10 do read(ne[j]);
end; {citnume}
PROCEDURE CITCLASAMENT;
var i: pozitie;
begin
For i:=1 to nrEchipe do
With clas[i] do
begin
CitNume(nume);
Read(jucat,vict,pierd,egal,puncte);
117
Readln(gtmarc,gtprim);
end;
End; {citclasament}
PROCEDURE ACTUALIZARE;
Var
ne:nume echipa;
j:integer;
p1,p2:pozitie;
q1,q2:0:maxint;
begin {actualizare}
for j:= 1 to nrEchipe div 2 do
begin
citNume(ne); read(q1);
p1:= localizare(ne);
citNume(ne); read(q2);
p2:= localizare(ne);
{determinarea tipului rezultatului}
if q1 > q2 then
rezultat:= victorie
else
if q1< q2 then
rezultat :=pierdere
else
rezultat :=egalitate;
{actualizare nr. partide jucate}
whith clas[p1] do
begin
jucat:= jucat+1;
gtmarc:= gtmarc+q1;
gtprim:= gtprim+q2;
end;
whith clas[p2] do
begin
jucat:= jucat+1;
gtmarc:= gtmarc+q2;
gtprim:= gtprim+q1;
end;
{actualizare victorii pierderi punctaj}
case rezultat of
victorie : begin
whith clas[p1] do
begin
vict:= vict+1;
puncte:= puncte+2;
118
end;
whith clas[p2] do
begin
pierd:= pierd+1;
end;
pierdere: begin
whith clas[p2] do
begin
vict:= vict+1;
puncte:= puncte+2;
end;
whith clas[p1] do
begin
pierd:= pierd+1;
end;
egalitate: begin
whith clas[p1] do
begin
egal:= egal+1;
puncte:= puncte+1;
end;
whith clas[p2] do
begin
egal:= egal+1;
puncte:= puncte+1;
end;
end;
end;{case}
end;{actualizare}
FUNCTION LOCALIZARE
(nech:numeEchipa):pozitie;
var i : pozitie;
begin
i:=1;
While clas[i].nume <>nech do
i:=i+1;
localizare:=i;
end; {localizare}
PROCEDURE SORTARE;
(dupa punctaj si golaveraj)
var i: pozitie;
j: 1..10;
Var i: pozitie; ech: echipa;
Begin
119
Repeat
ninv:= 0;
for j:= 1 to nrEchipe -1 do
if (clas[i].puncte< clas[i+1].puncte) or
(clas[i].puncte= clas[i+1].puncte) and
(clas[i].gtmarc - clas[i].gtprim) <
(clas[i+1].gtmarc- clas[i+1].gtprim) then
begin
ninn:= ninv+1;
ech:= clas[i];
{toate campurile inregistrarii}
clas[i]:= clas[i+1];
clas[i+1]:= ech;
end;
until ninv=0;
end; {sortare}
PROCEDURE ASFISCLASAMENT;
begin {afisclasament}
Sortare;
Writeln(‘ ‘ : 10, ‘jocuri vict pierd
egal pcte’);{captabel}
for i:= 1 to nrEchipe do
whith clas[i] do
begin
for j:= 1 to 10 do
write (nume[j]);
writeln(‘ ‘:4,jucat:2,’ ‘:3
,vict:2, ‘ ‘:4,pierd:2‘:3,
egal:2,‘ ‘:3,puncte:2);
end;
end;{afisclasament}
BEGIN {main}
citclasament;
actualizare;
afisclasament;
END.

Dându-se trei puncte în plan P1,P2,P3 prin coordonatele lor să se


traseze cercul circumscris triunghiului ştiind că centrul acestuia se află la
intersecţia mediatoarelor.
a)Descrierea algoritmului în limbaj natural:
După citirea coordonatelor punctelor se verifică dacă punctele sunt
confundate. În cazul în care nu sunt confindate se calculează semisuma a două

120
laturi ale triunghiului şi se trece la utilizarea metodei de construcţie geometrică,
metodă acre implică următorii paşi:
a) Se trasează două mediatoare;
b) Sedetermină punctul lor de intersecţie;
c) Se determină raza cercului circumscris ca distanţa între punctul de
intersecţie al mediatoarelor şi oricare din punctele date;
d) Se trasează cercul cu centrul determinat la punctul b) având raza
determinată la ounctul c).
Trasarea unei mediatoare a unui segment presupune:
- trasarea a două cercuri cu centrele în capetele segmentului, având aceeaşi
rază (mai mare decât jumătatea segmentului)
- intersectarea celor două cercuri şi determinarea ecuaţiei coardei comune
reprezentând mediatoarea
Intersecţia a două drepte:
(D1): a1*x + b1*y + c1 = 0, şi
(D2): a2*x + b2*y + c2 = 0
are coordonatele:
x=-(c1*b2 – c2*b1)/(a1*b2 – a2*b1)
y=-(c1*a2 – c2*a1)/(a1*b2 – a2*b1)
Ecuaţia dreptei de intersecţie a cercurilor
C1(x1,y1,r1) şi
C1(x2,y2,r2)
este:
x*(x1-x2) + y*(y1-y2) + (r12 – x12 – y12 – (r22 – x22 – y22))=0
În final după afişarea tipului de obiect rezultat se trsează triunghiul,
cercurile, dreptele de intersecţie şi cercul circumscris.
b)Descrierea şi semnificaţia structurilor de date folosite:
Elementele geometrice: cercuri, drepte, puncte de intersecţie (ale
cercurilo ale mediatoarelor) sunt descrise prin tipul înregistrare:
Type forma = (nimic,punct,linie,cerc);
Figura = record
Case disc :forma of
Punct(poziţie:coord);
Linie: (a,b,c: real);
Cerc : (centru: coord;raza: real);
End;
Varianta nimic a fost prevăzută pentru cazul în care construcţia geometrică
nu este posiobilă (punctele sunt colineare).
Variabilele p1,p2,p3,c1,c2,c3,d1,d2,p0, cerc sunt înregistrări de tip figură şi
reprezintă coordonatele punctelor date, coordonatele centrelor cercurilor, punctele
de intersecţie al cercurilor, p0 punctul de intersecţie al dreptelor D1,D2 şi
coordonatele centrului cercului circumscris.
Procedura citpct asigură citirea coordonatelor unui punct şi definirea tipului
obiectului- punct.
121
Procedura tipfig realizează afişarea tipului obiectului de afişat împreună cu
formaţiile aferente.
Procedura distanţă determină distanţa dintre două puncte.
Procedura trascerc stabileşte tipul obiectului cerc: raza şi coordonatele
centrului cercului.
Procedura intersdr determină coordonatele punctului de intersecţie a două
drepte x şi y specificând şi tipul obiectului.
Procedura iterscerc realizează dreapta de intersecţie a două cercuri.
Procedura draw asigură trasarea unei drepte
Funcţia identic verifică dacă punctele sunt confundate
c)Descrierea algoritmului în Pseudocod:
O primă variantă a algoritmului implică:
*citeşte coordonate puncte
dacă puncte confundate atunci
scrie puncte confundate
altfel
determină componentele cercului circumscris
[]
afişează grafic stop
Operaţia ‘citeşte coordonatele puncte’ implică apelul procedurii citpct astfel:
Execută citpct(p1)
Execută citpct(p2)
Execută citpct(p3)
Acţiunea ‘determină componentele cercului circumscris’poate fi descrisă
prin apelul procedurilor
Alege raza R
Execută trancec(P1,R,C1);
Execută trancec(P2,R,C2);
Execută trancec(P3,R,C3);
Execută interscerc(C2,C3,D1);
Execută interscerc(C3,c1,D2);
Execută interscerc(C3,C2,D2);
Execută intersdr(D2,D2,P0);
Execută distanţa(P2,P0,Raza);
Execută trascerc(P0,Raza,C);
Execută tipfig;
O alegere corespunzătoare a razei R care să depăşească jumătate oricărei
laturi a triunghiului o reprezintă semisuma a două laturi ale triunghiului.
Operaţia ’afişează grafic’ implică iniţializarea sistemului grafic, trasarea
triunghiului a cercurilor, a punctelor de intersecţie a cercurilor şi dreptelor şi a
cercului circumscris, urmărindu-se metoda geometrică.
d)Programul Pascal arată astfel:
Program cercuri;
Uses graph;
122
Type
Forma= (nimic,punct, linie,cerc);
Coord=record
x,y:real;
End;
Figura=record
Case disc:forma of
Nimic:( );
Punct: (poz:cord);
Linie: (a,b,c:real);
Cerc: (cen:cord;raza:real);
End;
Var
P1,p2,p3,c1,c2,c3,d1,d2,p0,ccirc:figura;
r,rcirc:real;
gd,gm:integer;
procedure citpct (var p;figura);
begin
with p.poz do begin
disc:=punct;
read(x,y);
end;
end;
Procedure tipfig(f:figura);
Begin
With f do
Case disc of
Nimic:write(‘fig nula’);
Punct:with poz do write (‘punct(’,x,y’)’);
Linie:write(‘dreapta’,a,b,c);
Cerc: with cen do
Write(‘cerc’,x,y’raza’,raza);
End;
End;
Function distanta(f1,f2:figura):real;
Begin
If (f1.disc=punct) and (f2.disc=punct) then
Distanta:= sqrt(sqtr(f1.poz.x- f2.poz.x)+ sqtr(f1.poz.y-
f2.poz.y))
Else
Distanta:=0

End;
Procedure transcerc (p:figura;r:real;var c:figura);
123
Begin
With c do
If (p.disc=punct) and (r>0) then begin
Disc:=cerc;
Cent:=p.poz;
Raza:=r
End;
Else
Disc:=nimic;
End;
Procedure intrsdr(d1,d2:figura; var p:figura);
Var
Det:real;
Begin
If (d1.linie=linie) and (d2.linie=linie) then begin
Det:=d1.a*d2.b- d1.b*d2.b;
If abs(det)<1.Oe-6 then
p.disc:= nimic
else
with p do begin
disc:= punct;
with poz do begin
x:= -(d1.c*d2.b- d1.b*d2.c)/det;
y:=+(d1.c*d2.b- d1.b*d2.c)/det
end;
end;
end;
else
p.disc:= nimic;
end;
Procedure interscerc (c1,c2: figura; var d:figura);
Begin
If (c1.disc=cerc) and (c2.disc = cerc) then
With d do begin
Disc:=linie;
a:= (c1.cen.x – c2.cen.x);
b:= (c1.cen.y – c2.cen.y);
c:= ((sqr(c1.raza)-(c1.cen.x)-sqr(c1.cen.y))-
sqr(c2.raza) + sqr(c2.cen.x) + sqr(c2.cen.y)/2.0
end;
else
d.disc:= nimic
end;
Function identic (f1,f2: figura) : boolean;
124
begin
identic:=distanta (f1,f2)< 1.Oe-6
end;
Procedure draw (f: figura);
Var
x1,y1,x2,y2: integer;
begin
if(f.disc=linie) then
if (f.b=0) then {linie verticala}
linie(trunc(-f.c/f.a),0,trunc(-f.c/f.a), getmaxy
else (f.a=0) then {linie orizontala}
linie(0,getmaxy - trunc(-f.c/f.b), 640,
getmaxy - trunc(-f.c/f.b))
else begin{linie intre 2 puncte ce se calculeaza:}
{P1(0,d1(0)) si P2(640,d1(640))}
x1:=c;
y1:=trunc (-(f.c/fb));
x2:=640;
y2:=trunc(-(f.c +f.a*x2)/f.b);
linie(x1,getmaxy – y1,x2,getmaxy – y2);
end;
end;
Begin {main}
Citpct(P1);
Citpct(P2);
Citpct(P3);
If identic (P1,P2) or identic (P2,P3) or identic (P3,P1) then
writeln (‘puncte confundate’)
else begin
r:=(distanta(p1,p2) + distanta(p2,p3))/2;
trascec(p1,r,c1);
trascec(p2,r,c2);
trascec(p3,r,c3);
interscerc(c2,c3,d1);
interscerc(c3,c1,d2);
intrsdr(d1,d2,p0);
rcirc:= distanţa(p1,p0);
trascerc(p0,rcirc,ccirc);
tipfig(ccirc);
end;
{initializare sistem grafic}
readln;
gd:=detect; gm:=2;
initgraph(gd,gm, ‘c:\tp\’);
125
if graphResult <> grOk then halt(1); {eroare de initializare}
{desenare}
linie(trunc(p1.poz..x), getmaxy – trunc(p1.poz.y),
trunc(p2.poz..x), getmaxy – trunc(p2.poz.y);
linie(trunc(p3.poz..x), getmaxy – trunc(p3.poz.y),
trunc(p2.poz..x), getmaxy – trunc(p2.poz.y);
linie(trunc(p3.poz..x), getmaxy – trunc(p3.poz.y),trunc(p1.poz..x),
getmaxy – trunc(p1.poz.y);
setcolor(blue);
circle(trunc(c1.cen.x), getmaxy – trunc(c1.cen.y), trunc(c1.raza));
circle(trunc(c2.cen.x), getmaxy – trunc(c2.cen.y),trunc(c2.raza));
circle(trunc(c3.cen.x), getmaxy – trunc(c3.cen.y),trunc(c3.raza));
setcolor(green);
draw(d1);
draw(d2);
setcolor(red);
circle(trunc(ccirc.cen.x), getmaxy –
trunc(ccirc.cen.y),trunc(ccirc.raza));
{inchiderea sistemului grafic,revenire…}
closegraph;
end.

FIŞIERE ÎN PASCAL

O colecţie de date de acelaşi tip aranjate într-un anumit mod pe un suport de


memorie externă sau dispozitiv periferic se numeşte fişier. Un fişier poate fi
permanent sau temporar. Un fişier permanent este cel al cărui conţinut nu este
distrus după terminarea execuţiei programului. El este folosit pentru a memora date
produse de program şi folosite de alt program sau chiar de acelaşi program la o
execuţie ulterioară. Un fişier temporar este distrus după terminarea execuţiei
programului. El este folosit pentru a memora informaţii ce nu încap în memoria
operativă pentru a fi prelucrate, dar nu mai interesează utilizatorul după execuţia
programului.

Declararea fişierelor.
În limbajul Pascal un fişier apare ca o secvenţă de componente de acelaşi tip
denumit tip de bază. Tipul de bază poate fi orice tip, în afară de tipul fişier. Fiecare
fişier folosit în program este reprezentat de o variabilă de tip fişier. Numai o
singură componentă a unui fişier este accesibilă într-un program, la un moment
dat. În limbajul Pascal există un tip special de fişiere: tipul text. Articolele unui
fişier de tip text sunt caractere structurate pe linii, fiecare linie fiind terminată cu

126
caractere CR, LF. Lungimea liniilor într-un fişier text este variabilă; de aceea
acest tip de fişiere nu poate fi prelucrat decât secvenţial.
Exemple de declaraţii de fişiere:
1) type
inreg=record
denumire : array[1..8] of char;
pret : real;
cant : integer;
end;
tfişier = file of inreg;
var
f1, f2 : tfişier;
2) file1, file2:text;

Operaţii asupra fişierelor.


Asignarea şi deschiderea fişierelor.
În lucrul cu fişierele, înainte de orice operaţii asupra fişierelor trebuie
precizat locul fizic în care fişierul se memorează. Aceasta se face folosind
procedura de ataşare ASSIGN definită ca:
Procedura ASSIGN (var f; nume:string) unde:
- f este variabila de tip fişier
- nume este numele extern al fişierului
Deschiderea pentru crearea unui fişier se face cu procedura rewrite definită
ca:
Procedure Rewrite(var f:file);
Deschiderea pentru citirea / scrierea unui fişier se face cu procedura reset:
Procedure RESET (var f:text);
Pentru fişierele text adăugarea articolelor la sfârşitul fişierului se poate face
numai dacă fişierul este deschis cu procedura APPEND definită ca:
Procedure APPEND(var f:text);

Scrierea şi citirea fişierelor.


Procedurile pentru scrierea respectiv citirea unui articol dintr-un fişier ca tip
sunt definite astfel:
Procedure Write(F; v1[,v2,…]);
Procedure Read(f; v1[,v2,…]); unde: f - este variabila de tip fişier
- v1, v2, … sunt variabile de acelaşi tip cu tipul de bază al fişierului.
Pentru fişierele de tip text, scrierea şi citirea se realizează cu procedurile:
procedure WRITE ([var f:text,]v1[,v2…]);
procedure WRITELN ([var f:text,]v1[,v2…]);
procedure READ ([f:text,]v1[,v2…]);
procedure READLN ([f:text,]v1[,v2…]); unde: - F este numele
variabilei de tip fişier text asociată fişierului fizic din care se vor citi date

127
- V1, V2 … sunt variabile de tip string, char sau de tip numeric în care se
vor depune datele citite.
Exemplu următor ilustrează scrierea într-un fişier cu tip:
type
inf = record
nume: string(9);
preţ:integer;
end;
fls = file of inf;
var
f1:fis;
v1:inf;
begin
assign(f1,’fişier1’);
rewrite(f1);
v1.nume:’material1’;
v1. pret:1432;
write(f1,v1);
v1.nume:=’material2’;
v1.pret:=1300;
write(f1,v1);
…………

Accesul direct
Poziţionarea pe un anumit articol al unui fişier cu tip se face cu procedura:
Procedure SEEK(var F; N:longint);
Unde: - F este o variabilă de tip fişier
- N este nr. articolului pe care se doreşte poziţionarea.
Determinarea numărului de ordine al articolului curent se face cu funcţia
filepos (numai pentru fişiere cu tip):
function FILEPOS (var f):longint;
Determinarea numărului de articole ale unui fişier se face cu funcţia
filesize(numai pentru fişiere cu tip)
function Filesize(file F):longint;
Determinarea sfârşitului de fişier se realizează cu funcţia:
Function EOF(var f):boolean;
Funcţii specifice fişierelor text.
Pentru fişierele text se pot folosi următoarele funcţii:
function EOLN[(var f:text)]:boolean care returnează valoarea
true dacă poziţia curentă în fişier este în dreptul ultimului caracter (CTRL/Z).
function SEEKEOLN(var f:text):boolean care fixează
poziţia curentă în fişier pe primul caracter diferit de spaţiu sau TAB şi testează
caracterul pe care s-a poziţionat. Dacă acest caracter este Eoln (CR+LF) funcţia va
returna valoarea logică True.
128
function SEEKEOF[(var f:text)]:boolean care fixează
poziţia curentă în fişier pe primul caracter diferit de spaţiu sau TAB şi testează
caracterul pe acre s-a poziţionat. Dacă acest caracter este EOF (CTRL/Z) funcţia
va returna valoarea logică True.
Închiderea fişierului.
Închiderea (logică şi fizică) a fişierelor se realizează cu procedura close:
Procedure CLOSE(var f);
Operaţii aplicabile fişierelor închise
În limbajul Turbo Pascal pot fi apelate multe din operaţiile specifice
limbajului de comandă MS-DOS. Aceasta se aplică fişierelor închise şi sunt
implementate prin următoarele proceduri:
Procedure ERASE(var f); Realizează ştergerea unui fişier
Procedure RENAME(var f; Numenou:String); Realizează redenumirea
unui fişier
Procedure GETDIR(D:Byte; var S:String); Determină directorul curent (de
pe unitatea specificată de variabila de tip Bzte D în variabila de tip String S)
Procedure CHOIR (s:string) Determină schimbarea directorului curent
Procedure MKDIR(S:String) Determină crearea unui director gol indicat
prin variabila S
Procedure RMDIR(s:string) Dtermină ştergerea unui director gol indicat
prin variabila S

A) Să se creeze un fişier cu numele studenţilor dintr-o grupă şi a


rezultatelor lor la cele 5 examene dintr-o sesiune. Pentru siguranţa
introducerii datelor de intrare (nume studenţi şi note) se consideră că se
introduc nu de la tastatură ci dintr-un fişier editat anterior.
A)Descrierea în limbaj natural a algoritmului:
În secţiunea de iniţializare a datelor trebuiesc asignate şi deschise fişierele
folosite: cel de intrare în care sunt editate anterior datele şi cel de ieşire ce urmează
a fi creat în program. Se foloseşte ca fişier de intrare fişierul standard de intrare
“input”. În mod obişnuit, la începutul execuţiei orcărui program, fişierului standard
de intrare I se asignează în mod implicit tastatura teminalului. Acestă asignare
implicită poate fi însă modificată printr-o asignare explicită. Operaţia principală a
algoritmului constă în citirea înformaţiilor despre fiecare student şi scrierea în
fişierul de ieşire a articolului corespunzător. Citirea din fişierul “input”, urmată de
scrierea în fişierul de ieşire se termină în momentul în care nu mai există informaţii
în fişierul “input” deci s-a întâlnit CTRL/Z(eof(input)). Se închid acum fişierele şi
se redeschide pentru citire fişierul creat. Se citeşte fiecare articol şi se afişează la
display (pentru a verifica corectitudinea fişierului creat).
b)Descrierea şi semnificaţia structurilor de date folosite:
Pentru fiecare student se va scrie în fişier un articol care cuprinde
următoarele informaţii: nume, adresa, număr telefon, cele 5 note. Aceste informaţii
sunt descrise de tipul de date “articol”. Adresa este compusă din strada şi număr şi

129
este descrisă de tipul de date “adresa”. Varaibila de fişier “fis” corespunde
fişierului de ieşire ‘fis’. Variabila inf este de tip “articol”.
Tipurile de date folosite sunt deci:
Adresa = record
Strada : string(10);
Număr : integer;
End;
Articol = record
Nume : string(10);
Adr : adresa;
Tel : longint
Note : tip_note;
End;
Tipul “tip_note” este un tablou de 5 elemente întregi.
c)Descrierea algoritmului în Pseudocod
* asignează şi deschide fişierele
* cât timp * nu s-au terminat datele din fişierul de intrare execută
citeşte inf. Nume, inf.adr.strada, inf.adr.număr,
inf.tel, inf.note
scrie * inf în fişierul de ieşire ‘fis’
_()
* închide fişierele
* deschide fişierul ‘fis’
* cât timp * nu s-au terminat articolele din ‘fis’ execută
citeşte * inf din fişierul ‘fis’
scrie inf.nume, inf.adr.strada, inf.adr.număr,
inf.tel, inf.note
_()
stop

d)Programul Pascal este:


Program creareA;
{programul crează un fişier cu informaţii despre studenţi:
- nume pe lungime de 10 caractere;
- strada pe lungime de 10 caractere;
- număr strada;
- număr telefon
- 6 note de tip intreg;
informaţiile se citesc de la terminal sub forma: nume_strada nr_strada nr_telefon
nota1 nota2 nota3 nota4 nota5 nota6 introducerea datelor se termină cu CTRL Z}
const
nrnote=6;
type
tipnote = array[1..nrnote] of integer;
130
adresa = record
strada : string(10);
număr:integer;
end;
articol = record
nume:string(10);
adr:adresa;
tel:longint;
note:tipnote;
end;
var
i : integer;
inf :articol
fis : file of articol;
BEGIN{main}
assign(input,’date’);reset(input);
{datele se pot introduce şi dintr-un fişier date editat anterior}
assign assign(fis, ‘fis’);
rewrite(fis); {datele se colecteza in fisierul ‘fis’};
while not eof (fis) do
begin {se citesc datele linie cu linie pentru fiecare student}
with inf do
begin
read(nume,adr.strada,adr.numar,tel);
for i: = 1 to nrnote do
read(note[i]);
readln;
end;
write(fis,inf); {scrie articolul inf cu informatiile studentului curent}
end;
close(fis);
reset(fis);
while not eof (fis) do
begin {se afiseaza articol cu articol pina la Eof (fis)}
read (fis, inf)
with inf do
begin
write(nume,adr.strada,adr.numar,tel);
for i: = 1 to nrnote do write(note[i], ‘ ’);
end;
writeln;
end;
END.

131
B)Pornind de la fişierul creeat la punctul A) să se creeze un alt fişier
care să cuprindă în plus pentru fiecare student media obţinută precum şi
un indicator boolean pentru promovabilitate (true = promovat, false =
nepromovat).
a)Descrierea algoritmului în limbaj natural:
În secţiunea de iniţializare se deschide pentru citire fişierul ‘fis’ creeat
anterior la punctul a) şi pentru crearea fişierului ‘fismedia’ care va conţine în plus
pentru fiecare student media şi indicatorul de promovabilitate. Se citeşte apoi
secvenţial (articol după articol) fişierul ‘fis’, se calculează media şi indicatorul de
promovabilitate şi se scrie un articol corespunzător în fişierul ‘fismedia’. La
întâlnirea sfârşitului de fişier eof(fis) se închid ambele fişiere; se deschide apoi
pentru citire fişierul ’fismedia’. Afişarea conţinutului fişierului ‘fismedia’ se face
cu o secvenţă asemănătoare afişării ‘fis’ de la punctul A).
b)Descrierea şi semnificaţia structurilor de date folosite.
Se folosesc în plus faţă de structurile de date prezentate la A):
- tipul de date “articol_media” care descrie un articol din fişierul ‘fismedia’
- variabila “infmedia” de tip ‘articolmedia’
c) Programul în limbajul Pascal:
Program creare B;
{programul creeaza un fisier fismedia care contine: nume student, adresa, media}
uses crt;
const
nr note: =6;
type
tpnote: = array[1..nrnote] of interger;
adresa: = record
strada: string[10];
numar: integer;
end;
articol: = record
nume: string[10];
adr: adresa;
tel: longint;
note: tpnote;
end;
articolmedia: = record
art: articol;
media: real;
prom: boolean;
end;
var
fis : file of articol;
fismedia : file of articolmedia;

132
inf : articol;
infmedia: articolmedia;
media : real;
i : integer;
BEGIN{main}
assign(fis, ‘fis’);
reset(fis); {se deschide fisierul din care citim};
assign(fismedia, ‘fmedia’);
rewrite(fismedia); {se deschide fis media pentru scriere}
while not eof (fis) do
begin {se afiseaza media}
read (fis, inf);
whith inf do
begin
media: =0.0;
for i: = 1 to nrnote do
media: =media + note[i];
media: = media / 6;
end;
infmedia.art: =inf;
infmedia.media: = media;
if media > 5 then
infmedia.prom: = true
else
infmedia.prom: = false;
write(fismedia, infmedia);
end;
close(fismedia);
reset(fismedia);
clrscr;
while not eof (fismedia) do
begin {se afiseaza studentii promovati si nepromovati}
read(fismedia,infmedia);
with infmedia.art do
begin
write(nume,adr.strada, ‘ ‘ , adr.numar, ‘ ‘ ,tel) ;
for i: =1 to nrnote do write(‘ ‘, note[i]);
if infmedia.prom then
write(‘ promovat’)
else
write(‘nepromovat’);
writeln(‘media=’,infmedia.media:6:3);
end;
end;
133
END.
c)Folosind fişierul creat la punctul B să se creeze alte două fişiere care
să cuprindă:
1)studenţii promovaţi în ordinea descrescătoare a mediilor
2)studenţii nepromovaţi în ordinea alfabetică.
a)Descrierea algoritmului în limbaj natural:
În secţiunea de iniţializare a datelor se deschide pentru intrare fişierul
‘fismedia’ creat la punctul B şi pentru creare fişierele ‘fism’ şi ‘fisa’ care vor
cuprinde studenţii promovaţi ordonaţi descrescător după medie, respectiv studenţii
nepromovaţi ordonaţi alfabetic. Se citeşte apoi fiecare articol din fişierul ‘fismedia’
şi se completează tablourile ‘tabm’ respectiv ‘taba’cu studenţii promovaţi,
respectiv nepromovaţi. Se ordonează aceste tablouri conform criteriilor indicate.
Cele 2 tablouri se scriu apoi în cele fişiere cerute: ‘fism’ şi ‘fisa’. În final se
afişează cele două fişiere.
b)Descrierea şi semnificaţia structurilor de date folosite:
Apar în plus ca structuri de date tablourile tabm, taba care conţin elemente
de tip ‘articolmedia’.
c)Programul în limbajul Pascal:
Program ordonare; {programul creeaza doua fisiere:
- un fisier fism care contine studentii ordonati in ordine descrescatoare a mediilor
- un fisier fisa care contine studentii ordonati alfabetic }
uses crt;
const nrnote = 6;
nmax = 50;
type
tpnote = array [1..nrnote] of integer;
adresa: = record
strada: string[10];
numar: integer;
end;
articol: = record
nume: string[10];
adr: adresa;
tel: longint;
note: tpnote;
end;
articolmedia: = record
art: articol;
media: real;
prom: boolean;
end;
var
fis : file of articol;

134
fismedia,fism,fisa : file of articolmedia;
inf : articol;
infmedia : articolmedia;
media : real;
i,j,k : integer;
tabm,taba :array [1..nmax] of articol media;
ind : boolean;
BEGIN{main}
assign(fism, ‘fism’); rewrite(fism);{se deschide fism pentru scriere}
assign(fisa, ‘fisa’); rewrite(fisa); {se deschide fisa pentru scriere}
assign(fismedia, ‘fmedia’);
reset(fis); {se deschide fisierul din care citim};
i: =0; j: =0;
while not eof (fismedia) do
begin
read (fismedia, infmedia);
if infmedia.prom then
begin
i: =i + 1;
tabm [i] : = infmedia;
end
else
begin
j: =j + 1;
tabm [j] : = infmedia;
end;
end;
close (fismedia);
repeat {se ordoneaza descrescator studentii in ordinea mediilor}
ind: =true;
for k: =1 to i-1 do
if tabm[k].media < tabm[k+1].media
then
begin
infmedia: =tabm[k];
tabm[i]: = tabm[k+1];
tabm[k+1]: =infmedia;
ind: =false;
end;
until ind;
repeat {se ordoneaza studentii in ordine alfabetica}
ind: =true;
for k: =1 to j-1 do
if taba[k].art.nume < taba[k+1].art.nume
135
then
begin
nfmedia: =taba[k];
taba[i]: = taba[k+1];
taba[k+1]: =infmedia;
ind: =false;
end;
until ind;
for k: =1 to i do
write(fism,tabm[k]);
{se scriu in fisier studenti ordonati dupa nume}
for k: =1 to j do
write(fisa,tabm[k]); {scriu in fis. fisa studenti ordonati
alfabetic}
reset(fism); reset(fisa);
clrscr;
writeln(‘Studentii promovati:’);
while not eof (fism) do
begin {se afiseaza promovatii}
read (fism,infmedia);
with infmedia.art do
begin
write(nume,adr.strada, ‘ ’,adr.numar, ‘ ‘ ,tel );
for i: =1 to nrnote do
write(‘ ‘ , note[i]);
write(‘promovat’);
write(‘media=’,infmedia.media:6:3);
writeln;
end;
end;
writeln(‘Studentii nepromovati:’);
while not eof (fisa) do
begin {se afiseaza promovatii}
read (fisa,infmedia);
with infmedia.art do
begin
write(nume,adr.strada, ‘ ’,adr.numar, ‘ ‘ ,tel );
for i: =1 to nrnote do
write(‘ ‘ , note[i]);
write(‘nepromovat’);
write(‘media=’,infmedia.media:6:3);
end;
writeln;
end;
136
END.

Se dau două fişiere text. Să se concateneze aceste fişiere. Numele


celor două fişiere sursă şi al fişierului destinaţie se citesc de la terminal.
a)Descrierea algoritmului în limbaj natural:
Mai întâi se iniţiază un dialog cu utilizatorul pentru determinarea numelor
fişierelor. În secţiunea de iniţializare a datelor se asignează acestor nume variabile
tip fişier şi se deschide pentru creare fişierul destinaţie. Se copiază apoi linie cu
linie primul fişier sursă în fişierul destinaţie. Când se detecteză sfârşit de linie se
trece la linia nouă în fişierul sursă (readln) şi se înscrie sfârşit de linie (writeln) în
fişierul de ieşire. Acest proces de copiere se termină când se ăntâlneşte sfârşitul
fişierului de intrare (eof) şi se închide acest fişier. Procedeul se repetă apoi identic
pentru al doilea fişier sursă. După copierea celui de-al doilea fişier sursă se închide
şi fişierul destinaţie.
b)Descrierea şi semnificaţia structurilor de date folosite:
Se folosesc variabile de tip fişier (f1, f2, f3) pentru cele trei fişiere folosite în
program. Pentru introducerea numelor fişierelor se introduc variabile de tip
string[nume1, nume2, nume3], iar pentru citirea unei linii caracter cu caracter se
foloseşte variabila tip caracter car.
c)Descrierea algoritmului în Pseudocod:
Pseudocodul acestui algoritm este destul de simplu:
 se citeşte numele fişierelor
 se asignează numele variabilelor tip fişier
 se deschide fişierul destinaţie în creare
 se deschide primul fişier sursă pentru citire
cât timp nu s-a terminat fişierul execută
cât timp nu s-a terminat linia execută
citeşte car din primul fişier sursă
scrie car în fişierul destinaţie
[]
[]
se deschide al doilea fişier sursă pentru citire
cât timp nu s-a terminat fişierul execută
cât timp nu s-a terminat linia execută
citeşte car din al doilea fişier sursă
scrie car în fişierul destinaţie
[]
[]
închide fişierele
d)Programul în limbaj Pascal:
Program copiaza_fisier;
Var
nume1, nume2, nume3 : string[8];

137
f1,f2,f3 : text;
car : char;
BEGIN{MAIN}
Writeln(‘dati numele primului
fisier sursa’);
Readln(nume1);
Writeln(‘dati numele celui de-
al doilea fisier sursa’);
Readln(nume2);
Writeln(‘dati numele fisierului
destinatie’);
Readln(nume3);
assign(f1,nume1);
assign(f2,nume2);
assign(f3,nume3);
rewrite(f3);reset(f1);
while not eof(f1) do
begin
while not eoln(f1) do
begin
read(f1,car);
write(f3,car);
end;
readln(f1);
writeln(f3);
end;
close(f1); reset(f2);
while not eof(f2) do
begin
while not eoln(f2) do
begin
read(f2,car);
write(f3,car);
end;
readln(f2);
writeln(f3);
end;
close(f2);
close(f3);
END.

138

S-ar putea să vă placă și