Sunteți pe pagina 1din 21

0.

INTRODUCERE
Recurena este prezent n lucrrile de matematic destul de timpuriu, cel
mai cunoscut exemplu fiind numerele Fibonacci care formeaz o secven de
numere ntregi. Aceast secven respect o anumit regul recurent: fiecare
numr este suma precedentelor sale dou numere. Excepia de la aceast regul o
reprezint numerele de nceput ale secvenei (0 i 1):
0, 1, 1, 2, 3, 5, 8, 13, 21 34, 55, 89, 144,

Regula recurent este:

Fn=Fn-1 +Fn-2, n>1 cu F0 = 0 i F1 = 1


Secvena a fost numit dup numele italianului Leonardo din Pisa, cunoscut i sub
pseudonimul Fibonacci, n lucrarea Liber Abaci aprut n 1202.
n anii urmtori, s-au dat apoi, n matematic i fizic, nenumrate iruri i
serii de numere folosind definiii recurente, att liniare ct i de alt natur.
Odat cu apariia limbajelor de programare de nivel nalt, FORTRAN fiind
primul limbaj de nivel nalt i dedicat rezolvrii problemelor cu caracter tiinific,
s-a pus problema folosirii acestor recurene. n programare noiunea a suferit o
mic modificare morfologic i semantic: noiunea se numete recursivitate i
nseamn apelul unei subrutine (proceduri sau funcii) din corpul ei de definiie,
deci autoapelare. Limbajul aminitit mai sus nu permitea recursivitatea, dar
urmtorul limbaj ALGOL pe aceai linie cu FORTRAN-ul, a permis folosirea
acestei modaliti de programare. Folosirea recursivitii n programare este
accesibil, n zilele noastre, n majoritatea limbajelor folosite: PASCAL, C++,
JAVA, PYTHON, GROVY, LISP, PROLOG, etc. n programa liceal, la clasele
de profil se folosesc limbajele PASCAL i/sau C/C++, de aceea lucrarea va
exemplifica algoritmii recursivi doar n aceste dou limbaje de programare.
n matematic ntlnim multe alte exemple care se pot defini recursiv:
- irul numerelor naturale (primul este 0, fiecare numr obinndu-se din
precedentul su la care se adun 1);
suma numerelor naturale (iniial suma este zero, apoi suma (n) este
suma
primelor n-1 adunate cu n);
- cmmdc a dou numere naturale att prin scdere ct i prin mprire,
vom reveni
la acest exemplu;

demonstrarea prin metoda induciei matematice a unor propoziii


matematice folosete de cele mai multe ori la pasul de demonstrare
forme de recuren;
- etc.
Exist i fenomene de alt natur care se pot defini recursiv:
- succesiunea zilelor i nopilor;
- construcia unor asambluri pe module;
filmarea cu o camera a unei oglinzi; sau televizarea unei emisiuni cu
filmarea unui
televizor ce transmite aceea emisiune;
- etc.
Primul capitol, va aborda i sper c va clarifica noiunea de recursivitate. Se
vor da nenumrate exemple n PASCAL i C++, nu numai din matematic dar i
probleme pe iruri de caractere, de citiri/afiari de date, etc. Se vor da i clasificri
din diverse puncte de vedere, se va vorbi i despre stiv, structura de dat logic
care permite acest mecanism al recursivitii. Programul apelant este i program
apelat, stiva trebuie gestionat foarte exact; la revenire se preia nu numai contextul
de apel ci i rezultatele intermediare, stocate de asemenea n stiv.
Al 2-lea capitol se va referi la metodologia predrii mecanismului de
recursivitate, trecerea de la algoritmii iterativi la cei recursivi, nefiind banal;
dificulti n ntelegere, exemple simple, lecii cadru de predare, exerciii i
probleme din tematica probei de informatic de la Bacalaureat, etc.

1. RECURSIVITATEA N PROGRAMARE
1.1. Motivaia folosirii recursivitii
Idea subprogramului (procedur sau funcie) care apeleaz un alt
subprogram este deja obinuit n limbajele de programare. Majoritatea
paradigmelor de dezvoltare a softului includ rafinarea problemei n subprobleme
pn cnd acestea din urm se pot concretiza n module, proceduri sau funcii.
Apoi apelul acestor module, proceduri sau funcii se face n mod natural n
procesul rezolvrii problemei iniiale. Deci mecanismul apelrii de subprograme
este folosit n toate limbajele de programare moderne, la baza lui stnd conceptul
de stiv. Implementarea specificaiilor unui limbaj de programare se face de obicei
de compilatorul limbajului respectiv. Fr a intra n prea multe amnunte, stiva se
definete ca o lista liniar care are principiul LIFO (ultimul element intrat n stiv
este primul utilizat i apoi scos din stiv). n stiva folosit de compilator se depune
contextul apelului, n care pe lng parametri de apel, variabilele locale ale
subprogramului, etc. se depune i adresa de revenire. Dac se fac mai multe
apeluri n cascad, atunci se rein n stiv adresele de revenire. La terminrea
apelurilor se revine la fiecare adres din stiv n mod invers depunerii n stiv, etc.
Acest mecanism este ilustrat n cele ce urmeaz. Fie 3(trei) proceduri numite P1,
P2 i P3 i secvena de pseudocod de mai jos:
Procedura P1(...)
Instruciuni
Apel P2()
InstRevP1
Sfarit P1;

Procedura P2(...)
Instruci

Apel P3()
InstRevP2
Instruciuni
Sfarit P2;

Procedura P3(...)
Instruciuni

Sfarit P3;
Instruciuni

Prin InstRevP1 s-a notat instruciunea de revenire din P2, iar prin InstRevP2 sa notat instruciunea de revenire din P3.
La apelul procedurii P2 din P1, stiva are structura:
Parametrii lui P1

Variabilele locale ale lui P1

Adresa instr. InstRevP1

La apelul procedurii P3 din P2, stiva se modific astfel:


Parametrii lui P2
Parametrii lui P1

Variabilele locale ale lui P2


Variabilele locale ale lui P1

Adresa instr. InstRevP2


Adresa instr. InstRevP1

La revenirea din P3 (n P2) stiva i reface prima form, apoi la revenirea


din P2 (n P1) stiva se golete complet.
Fr a intra n alte amnunte amintim c un compilator al unui limbaj de
programare folosete acest mecanism de stiv i n alte procese de traducere a
programului n limbaj main.
S-a pus problema, dac un subprogram nu s-ar putea apela pe el nsui, din
corpul lui de definiie? Raspunsul este pozitiv, i pe parcursul dezvoltrii a noi
limbaje de programare s-au implementat mecanismele de recursivitate. S-a luat
msura ca starea subprogramului din activitatea anterioar autoapelului s poat fi
restaurat la terminarea apelului. Acesta este principala caracteristic prin care
limbajelele recursive se deosebesc de cele nerecursive.
Dup cum se tie unele procese matematice, fizice i de alt natur se pot defini
recurent, cu formule recureniale elegante. S revenim la numerele lui Fibonacci,
cu formula:

Fn = Fn-1 + Fn-2, n>1 cu F0 = 0 i F1 = 1


n [1], se d o formul nerecurenial pentru termenul
generatoare, se obine formula:
Fn

1
5

n
n

1 5
1 5

2
2

Fn folosind funciile
(1)

Pentru a scrie o procedur PASCAL/C++, care determin termenul de ordinul n,


al irului lui Fibonacci, dup formula (1), avem nevoie de calculul puterilor celor
dou numere iraionale. n continuare dm cele dou programe:
Varianta PASCAL:
function Putere(a:real; n:integer):real;
n}
var Put:real;
i :integer;
begin
Put:=1;
for i:=1 to n do
Put:=Put*a;
Putere:=Put;
end;
function FibN(n:integer):longInt;
}
var phi1,phi2
: real;
(1)
}
phi1LaN,phi2LaN : real;
}
begin
phi1:=(1+sqrt(5))/2;
phi2:=(1-sqrt(5))/2;

{determina a la puterea

{determina F(n)
{cele 2 constante din formula
{constantele

la

puterea

phi1LaN:=exp(n*ln(phi1));
puterea}
phi2LaN:=Putere(phi2,n);
}

{phi1>0

si

se

poate

calcula

{phi2<0 si este necesar apelul

{functiei Putere
}
FibN:=trunc((phi1LaN-phi2LaN)/sqrt(5));{formula (1)
}
end;
var i:integer;
begin
writeln;
for i:=0 to 10 do
end.

write(FibN(i),' ');

Execuia programului va tipri primele 11 numere Fibonacci:


0 1 1 2 3 5 8 13 21 34 55

Ca o observaie s remarcm faptul c mai avem nevoie i de funcia


Putere(x,n) pentru calculul xn. n varianta C/C++ nu e necesar s se defineasc
o astfel de functie care sa calculeze xn, pentru c exist o funcie predefinit n
fiierul header math.h. Funcia se numete pow i are prototipul:
double pow

(double x,double y)

- calculeaz x y;

Varianta C/C++:
#include<iostream.h>
#include<math.h>
long FibN(int n)
// determina F(n)
{ float
phi1= (1+sqrt(5.0))/2, // cele 2 constante din formula (1)
phi2= (1-sqrt(5.0))/2,
phi1LaN, phi2LaN;
// constantele la puterea n
phi1LaN= pow(phi1,n);
phi2LaN= pow(phi2,n);
return (phi1LaN-phi2LaN)/sqrt(5.0);
// formula (1)
}
void main()
{ int i;
for (i=0;i<=10;i++)
cout<<FibN(i)<<" ";
}

Execuia programului va tipri primele 11 numere Fibonacci:


0 1 1 2 3 5 8 13 21 34 55

Dup cum se observ calculul termenului F(n)necesit expresii destul de


complexe, calcule cu ridicri la putere, etc. Variantele recursive (folosind recurena
definirii irului lui Fibonacci) n PASCAL i C/C++, care se dau n cele ce
urmeaz, sunt mai simple.

Varianta recursiv n PASCAL:


function fibNRec (n:longint): longint;
begin
if n in [0..1]
then fibNRec:= n
{se returneaza 0 sau 1
}
else fibNRec:= fibNRec(n-2)+fibNRec(n-1){apelul dublu
recursiv }
end;
var i:integer;
begin
for i:=0 to 10 do
write (' ', fibNRec(i));
end.

Execuia programului va tipri primele 11 numere Fibonacci:


0 1 1 2 3 5 8 13 21 34 55

Varianta C/C++:
#include<iostream.h>
long fibNRec (long n)
{ if (n<2) return n;
//se returneaz 0 sau 1
return fibNRec(n-1) + fibNRec(n-2); //apelul dublu recursiv
}
void main (void)
{ int i;
for (i=0;i<=10;i++)
cout <<" "<<fibNRec(i);
}

Execuia programului va tipri primele 11 numere Fibonacci:


0 1 1 2 3 5 8 13 21 34 55

Comparnd variantele iterative cu cele recursive, se observ c cele din


urm sunt mai simple i mai elegante. Evident c exist i variante iterative mai
simple, cu determinarea secvenei Fn,n0 ntr-un tablou, dar atunci, trebuie
declarat tabloul de o dimensiune aprioric destul de mare; sau folosirea a 2(dou)
variabile, a i b care rein doi termeni consecutivi i apoi calcularea sumei celor
dou variabile urmat de deplasarea valorilor, ceva de genul:
a0
Afiseaza (a, );
b1
Afiseaza (b, );
Pentru i2,n executa
Sumaa+b
Afiseaza (Suma, );
ab
bSuma

{primul termen F(0)


{afisare F(0)
{al 2-lea termen F(1)
{afisare F(1)

}
}
}
}

{determinare termen F(i)


{afisare F(i)
{deplasare valori

}
}
}

SfPentru

n varianta recursiv se observ dou aspecte importante:


-definirea unei ieiri n procedura recursiv (cnd se calculeaz direct Fn);
-apelul recursiv la sfritul codului procedurii;
Cele dou aspecte sunt recomandate (primul obligatoriu, altfel am avea un apel
recursiv infinit), de specialitii Kormen, Leiserson, Rivest n [2].
O alt observaie important este c trebuie gndit recursiv rezolvarea i
nu traducerea iterativ ntr-o variant recursiv.

1.2. Clasificarea apelurilor recursive, exemple


Clasificarea apelurilor recursive se poate face din diverse puncte de vedere:
tipul expresiei recurente, numrul de apeluri ntr-o expresie, apel intermediar
recursiv.
Dac formula recurenial este liniar atunci avem recursivitate liniar, n
caz contrar avem recursivitate neliniar. n ambele tipuri de mai sus putem avea
apel simplu recursiv (cnd n formul apare recurena o singur dat, recurena
Fibonacci este dublu liniar) ct i apel multiplu recursiv.
Recurena simpl liniar este ilustrat de calculul factorialului n!=1*2**n.
Formula recurenial este:

1
n * factorial (n 1)

factorial (n)

pentru
pentru

n0
n0

Varianta PASCAL:

function Factorial (n:byte): longint;


begin
if n=0
then Factorial:=1
else Factorial:=n*Factorial(n-1);
end;

Varianta C/C++:

long Factorial(int n)
{ if (n==0)
return 1;
return n*Factorial(n-1);
}

Vom ilustra recurena neliniar i multipl printr-un exemplu mai complex:


calculul numrului de arbori binari cu n noduri notat cu bn.
n=0, b0=1, prin convenie se numr i arborele binar vid, care nu are nici un
nod.
n=1, b1=1, avem un arbore binar cu un nod, nodul rdcin
n=2, b2=2, avem 2 arbori binari, conform schiei:

n=3, b3=5, avem 5 arbori binari, ca n cele ce urmeaz:

Vom demonstra c:
1

1 2n

bn= n 1 C n2n n 1

Vom folosi funcia generatoare, conform [1]:


B(z)=b0+b1z+b2z2+...+bnzn+...

Funcia generatoare este un polinom de grad infinit, avnd drept coeficieni, chiar
termenii irului, bn.
Presupunem c un arbore binar cu n noduri are:
un nod drept rdcin
k
noduri n subarborele stng
n-k-1
noduri n subarborele drept
Figura urmtoare ilustreaz acest fapt:

Dnd lui k valorile 0,1,2,...,n-1 se obine formula de recuren ce


urmeaz:
bn=b0bn-1+b1bn-2+...+bn-1b0

Este o recurena multipl i ptratic (neliniar). Se poate scrie un program


recursiv, dup aceast formul, dar nu e recomandabil, pentru c apelul recursiv ar
fi extrem de mult utilizat i stiva aferent se va depi repede.
n acest caz rezolvarea este matematic n primul rnd i e dat n continuare.
B(z)=b0+b1z+b2z2+...+bnzn+...
B(z)=b0+b1z+b2z2+...+bnzn+...

se nmulete membru cu membru i se obine:

B2(z)=b0+(b0 b1+ b1 b0)z+...+(b0bn+...bnb0)zn+...


B2(z)=b1+b2z+b3z2+...+bn+1zn+... |se nmuleste cu z
zB2(z)= b1z+b2z2+b3z3+...+bnzn+... = B(z)- 1
zB2(z)= B(z)- 1
B(z) =
B(z) =

1 1 4z
, soluia
2z

bun

1 1 4z
1
1
1

1 1 4 z 1 2
1 C1n 2 (4 z ) n C1n 2
(1) n 2 2 n 1 z n

2z
2z
2 z
n0
n0

bn= C1n 21 (1) n 2 2n 1 =...=

1
1 2n
1 (2n)!

C n2n
=
n 1 n
n 1 n! n! n 1

Am obinut ceea ce am dat mai nainte:


1

1 2n

bn= n 1 C n2n n 1

Apelul intermediar recursiv i nu direct (ca i cele care le-am folosit pn acum) se
obine cnd apelul recursiv al unei proceduri P1 nu se face n definiia ei ci ntr-o
alt procedur P2 apelat n prealabil n P1. Apoi din P2 se apeleaz iar P1. Nu
vom exemplifica aceast modalitate, pentru ca o considerm prea dificil pentru
nvmntul preuniversitar.

1.3. Aspecte matematice, formalizare


Cel mai ilustrativ exemplu utilizat pentru recursivitate este definirea
factorialului; relum definirea recursiv:

1
n * factorial (n 1)

factorial (n)

pentru
pentru

n0
n0

Pentru a calcula factorial(n) trebuie s nmulim n cu factorial(n1), care e definit cu ajutorul factorial(n-2),..., pn cnd ajungem la
factorial(0), care e definit explicit avnd valoarea 1. Pentru o astfel de
definiie poate c e potrivit notaie expresia condiional introdus de McCarty
[1], noaie care folosete expresii condiionale de forma:
`
[b1:e1, b2:e2,..., bn-1:en-1, en]

Cu bi,i=1,...,n-1, am notat condiii booleene, care pot fi adevrate sau false,


iar cu ei,i=1,...,n s-au notat expresii (calcule, formule, funcii, etc.)
Evaluarea expresiei condiionale se va face astfel:
- se evalueaz pe rnd condiiile bi, pn cnd gsim primul bi adevrat,
i atunci valoarea expresiei condiionale va fi expresia ei,
corespunztoare lui bi;
- dac nu s-a gsit nici un bi cu valoarea logic adevrat, atunci valoarea
expresiei condiionale va fi valoarea expresiei en.
Revenind la definiia factorialului, ea poate fi transcris n felul urmtor:
factorial(n)=[(n=0):1, n*factorial(n-1)]

Dac extindem definiia pentru toate valorile intregi a lui n avem:


factorial(n)=[(n<=0):1, n*factorial(n-1)]

n acest exemplu se tie numrul de pai, de exemplu pentu factorial(4) se


apeleaz recursiv de 3 ori. Dar n cazul algoritmului lui Euclid de determinare a
celui mai mare divizor comun a dou numere ntregi i pozitive, numrul de
apeluri recursive, nu e aprioric cunoscut; definiia cu ajutorul expresiei
condiionale poate fi:
CMMDC(n,m)=[(m=0):n, CMMDC(m, MODULO(n,m))]

Spre exemplu:

CMMDC(345,1920)=CMMDC(1920,345)=CMMDC(345,195)=CMMDC(195,150
)=
CMMDC(150,45)=CMMDC(45,15)=CMMDC(15,0)=15
Deci apelul recursiv a fost utilizat de 6 ori.

Un alt exemplu este definiia funciei Bessel:


Jn+1(x)=(2*n/x)*Jn(x)-Jn-1(x)

Rescriem n Jn(x) n forma simetric J(n,x) i nlocuim n cu n-1, relaia de


recuren va deveni:
J(n,x)=(2*n/x)*J(n-1,x)-J(n-2,x)

Dac pentru un argument particular x tim valoare lui J0 i J1 atunci putem defini:
J(n,x)=[(n=0):J(0,x), (n=1):J(1,x), ((2*(n-1)/x*J(n-1,x)J(n-2,x)]

Un alt exemplu este funcia Ackermann: ac:NxN N


n 1,

ac ac(m - 1,1),
ac(m - 1, ac(m, n - 1)),

daca m 0
daca n 0
altfel

Definit cu ajutorul expresiei condiionale avem:


ac(m,n)=[(m=0):n+1, (n=0):ac(m-1,1), ac(m-1,ac(m,n-1))]

1.4. Probleme simple


Vom da cteva exemple de proceduri recursive care utilizeaz la intrare un
singur parametru n de tip ntreg i pozitiv i determin:
a) numrul cifrelor sale
b) suma cifrelor numrului
c) produsul cifrelor sale
d) oglinditul su (oglinditul lui 123 este 321);
e) cifra de pe poziia i a unui numr natural.
Aceste rezolvri simple pot s familiarizeze elevul cu modul recursiv de gndire.
Pentru a determina numrul cifrelor lui n ne gndim dac am putea da o formul
recurent, ceva n genul irului Fibonacci:
- pentru n{0,1,2,3,4,5,6,7,8,9} evident numrul de cifre este 1;
- pentru n 10, se poate gndi c numrul de cifre a lui n este 1+
numarul de cifre a numrului obinut din n, din care am tiat ultima
cifr (de fiecare dat se taie cifra unitilor); tierea ultimei cifre se
obine prin mprtirea ntreag la 10.
Exemplu:

NrCifre(123)=
1+(1+NrCifre(1))=1+1+1=3.

1+

NrCifre(12)=

Formula recurent ar putea sa fie:

1
1 NrCifre (n / 10)

NrCifre (n)

0n9
n 10

10

unde prin n/10 am notat ctul ntreg al mpririi n/10, deci n


Varianta Pascal:
type Natural = 0..MaxLongInt;
function NrCifre(n:Natural):Natural;
begin
if n in [0..9]
then NrCifre:=1
else NrCifre:=1 + NrCifre(n div 10);
end;

Varianta C/C++:
long NrCifre(long n)
{ if (n>=0 && n<10)
}

return 1;
return 1 + NrCifre(n/10);

Pentru a determina suma cifrelor gndim analog:


- pentru n{0,1,2,3,4,5,6,7,8,9} evident suma cifrelor este n;
- pentru n 10, se poate gndi c suma cifrelor lui n este ultima cifr +
suma cifrelor numrului obinut din n, din care am tiat ultima cifr (de
fiecare dat se taie cifra unitilor); tierea ultimei cifre se obine prin
mprtirea ntreag la 10 iar ultima cifr se poate obine prin restul
mpririi ntregi a lui n la 10.
Exemplu:

SumaCifre(123)= 3+ SumaCifre(12)= 3+(2+SumaCifre(1))=3+2+1=6.

Formula recurent ar putea sa fie:

n
(n mod 10) SumaCifre ( n / 10)

SumaCifre (n)

0n9
n 10

10

unde prin n/10 am notat ctul ntreg al mpririi n/10, deci n

iar prin (n mod 10) am notat restul mpririi lui n la 10.


Varianta Pascal:
type Natural = 0..MaxLongInt;
function SumaCifre(n:Natural):Natural;
begin
if n in [0..9]
then SumaCifre:= n
else SumaCifre:= n mod 10 + SumaCifre(n div 10);
end;

Varianta C/C++:
long SumaCifre(long n)
{ if (n>=0 && n<10)
}

return n;
return n%10 + SumaCifre(n/10);

Pentru a determina produsul cifrelor gndim analog:


- pentru n{0,1,2,3,4,5,6,7,8,9} evident produsul cifrelor este n;
- pentru n 10, se poate gndi c produsul cifrelor lui n este ultima
cifr * produsul cifrelor numrului obinut din n, din care am tiat
ultima cifr (de fiecare dat se taie cifra unitilor); tierea ultimei cifre
se obine prin mprtirea ntreag la 10 iar ultima cifr se poate obine
prin restul mpririi ntregi a lui n la 10.
Exemplu:

ProdusCifre(123)=
3*(2*ProdusCifre(1))=3*2*1=6.

3*

ProdusCifre(12)=

Formula recurent ar putea s fie:

n
(n mod 10) * Pr odusCifre (n / 10)

Pr odusCifre ( n)

0n9
n 10

10 ;

unde prin n/10 am notat ctul ntreg al mpririi n/10, deci n


iar prin (n mod 10) am notat restul mpririi lui n la 10.
Varianta Pascal

type Natural = 0..MaxLongInt;


function ProdusCifre(n:Natural):Natural;
begin
if n in [0..9]
then ProdusCifre:= n
else ProdusCifre:= n mod 10 + ProdusCifre(n div 10);
end;

Varianta C/C++:
long ProdusCifre(long n)
{ if (n>=0 && n<10)
return n;
return n%10 + ProdusCifre(n/10);
}

Pentru a determina oglinditul cifrelor gndim altfel:


- pentru n{0,1,2,3,4,5,6,7,8,9} evident oglinditul lui n este n;
- pentru n 10, se poate gndi c oglinditul lui n este ultima cifr *
10NrCifre(n/10) adunat cu oglinditul lui n / 10
Exemplu:
+Oglinda(1))=300+20+1=321.

Oglinda(123)=3*102+(Oglinda(12))=300+(2*101

Formula recurent ar putea sa fie:

0n9

Oglinda (n)

(n mod 10) * 10

NrCifre ( n / 10)

Oglinda(n / 10)

n 10

10

unde prin n/10 am notat ctul ntreg al mpririi n/10, deci n

iar prin (n mod 10) am notat restul mpririi lui n la 10.


Varianta Pascal: Dm programul complet care verific dac un numr dat n este
palindrom sau nu.
program Palindrom;
uses fdelay,crt;

type Natural = 0..MaxLongInt;


function NrCifre(n:Natural):Natural;
begin
if n in[0..9] then NrCifre:=1
else NrCifre:=1+NrCifre(n div 10);
end;
function Oglinda (n:Natural): Natural;
var aux:Natural;
begin
if n in [0..9]
then Oglinda:= n
else
begin
aux
:=NrCifre(n div 10);
Oglinda:=trunc((n mod 10)*exp(aux*ln(10))) + Oglinda(n div
10);
end;
end;
var n,nrcif:Natural;
begin
clrscr;
write ('dati n=');
readln(n);
nrcif :=NrCifre(n);
writeln(oglinditul=,Oglinda(n));
if n=Oglinda(n)
then writeln (n,' este palindrom
')
else writeln (n,' nu este palindrom');
readkey;
end.

Execuia programului:
dati n=15249
oglinditul=94251
15249 nu este palindrom

Varianta C/C++: Dm programul complet care verific dac un numr dat n este
palindrom sau nu.
#include <iostream.h>
#include <conio.h>
#include <math.h>
long NrCifre(long n)
{if (n>=0 && n<10)return 1;
return 1+NrCifre(n/10);
}
long Oglinda (long n)
{int aux;
if (n >=0 && n<10)
return n;
else
{aux= NrCifre(n / 10);
return ((n % 10)*pow(10,aux) + Oglinda(n / 10));

}
}
void main()
{long n;
clrscr();
cout<<"dati n=";cin>>n;
cout<<Oglinda(n)<<endl;
if (n==Oglinda(n))
cout<<n<<" este palindrom";
else cout<<n<<" nu este palindrom";
getch();
}

Execuia programului:

dati n=152251
oglinditul=152251
152251 este palindrom

Problema e) Cifra de pe poziia poz (de la dreapta la stnga) a unui numr


natural n poate fi gndit astfel:
- se scad numrul de mpriri ale lui n la 10 din variabila poz; dac
am ajuns la 0 se returneaz (n mod 10)
Varianta Pascal:
program Pozit;
uses fdelay,crt;
type Natural = 0..MaxLongInt;
function Pozitia (n,Poz:Natural): byte;
begin
if Poz=1
then Pozitia:=n mod 10
else
begin
Poz:=Poz-1;
Pozitia:=Pozitia(n div 10,Poz);
end;
end;
var n,Poz:Natural;
begin
write
('dati n=');
readln (n);
write
('a cata cifra =');
readln (Poz);
writeln (cifra este:,Pozitia(n,Poz));
readkey;
end.

Execuia programului:
dati n=15249
a cata cifra =4
cifra este:5

Varianta C/C++:

#include<iostream.h>
#include<conio.h>

int Pozitia (long n,long Poz)


{if (Poz==1)
return n % 10;
return Pozitia(n / 10,--Poz);
}
void main()
{ long n;
int Poz;
clrscr();
cout <<"dati n=";
cin >>n;
cout <<"a cata cifra ="; cin >>Poz;
cout <<Pozitia(n,Poz);
getch();
}

Execuia programului:
dati n=15249
a cata cifra =3
cifra este:2

Algoritmului lui Euclid prin imprire

Varianta Pascal:

program EuclidImpartire;
uses fdelay,crt;
type Natural=1..MaxLongInt;
function Cmmdc (a,b:Natural): Natural;
Begin
if a mod b = 0 then Cmmdc:= b
else Cmmdc:= Cmmdc (b, a mod b)
end;
var x,y:Natural;
begin
clrscr;
write ('dati x,y=');
readln (x,y);
write ('Cmmdc(',x,',',y,')=',Cmmdc (x,y));
readkey
end.

Execuia programului:
dati x,y= 100 12
Cmmdc(100,12)=4

Varianta C/C++:

#include <iostream.h>
#include <conio.h>
long Cmmdc(long a, long b)
{ if (!(a % b)) return b;
else return Cmmdc(b, a % b);
}
void main(void)
{ long x,y;

clrscr();
cout << "dati un numar natural=";
cin >> x;
cout << "dati alt numar natural=";
cin >> y;
cout << "cmmdc(" << x << "," << y << ")=" << Cmmdc (x,y);
}

Execuia programului:
dati un numar natural=100
dati alt numar natural=12
cmmdc(100,12)=4

Algoritmului lui Euclid prin scdere

Varianta PASCAL:

program EuclidScadere;
uses crt;
var x,y:longint;
function Cmmdc (a,b:longint): longint;
Begin
if a = b then Cmmdc:= a
else begin
if a>b then Cmmdc:= Cmmdc (a-b,b)
else Cmmdc:= Cmmdc (a,b-a);
end
end;
begin
clrscr;
write ('dati x,y=');
readln(x,y);
write ('cmmdc(',x,',',y,')=',Cmmdc (x,y));
readkey
end.

Execuia programului:
dati x,y= 1000 12
cmmdc(1000,12)=4

Varianta C/C++:
#include <iostream.h>
#include <conio.h>
long Cmmdc(long a, long b)
{ if (a == b) return a;
if (a>b) return Cmmdc (a-b,b)
return Cmmdc (a,b-a);
}
void main(void)
{ long x,y;
clrscr();
cout << "dati un numar natural="; cin >> x;
cout << "dati alt numar natural="; cin >> y;
cout << "cmmdc(" << x << "," << y << ")=" << Cmmdc (x,y);
}

Execuia programului:

dati un numar natural=1000


dati alt numar natural=12
cmmdc(1000,12)=4