Sunteți pe pagina 1din 95

Culegere probleme de informatica

Cuprins
CUPRINS ................................................................................................................................................ 1

INTRODUCERE .................................................................................................................................... 2

CE ANSE AM S DEVIN UN BUN PROGRAMATOR ?............................................................... 3

LEGILE SUCCESULUI DURABIL (GHIDUL STUDENTULUI NDRTNIC)......................... 6

PROBLEME DE JUDECAT .............................................................................................................. 8


PROBLEME DE PERSPICACITATE............................................................................................................. 8
PROBLEME CU CHIBRITURI .................................................................................................................... 9
PROBLEME DE LOGIC I JUDECAT .................................................................................................... 10
PROBLEME DE LOGIC I JUDECAT CU "TENT INFORMATIC" ......................................................... 12
NOIUNI FUNDAMENTALE DE PROGRAMARE ....................................................................... 15
1.CELE TREI ETAPE ALE REZOLVRII UNEI PROBLEME CU AJUTORUL CALCULATORULUI ..................... 15
2.CUM SE STABILETE CORECTITUDINEA I EFICIENA SOLUIONRII ? .............................................. 15
3. NOIUNILE FUNDAMENTALE ALE PROGRAMRII: ALGORITM, LIMBAJE DE DESCRIERE A
ALGORITMILOR, PROGRAM, LIMBAJE DE PROGRAMARE ...................................................................... 16
3.1. Algoritmul ............................................................................................................................... 16
3.2. Descrierea algoritmilor ........................................................................................................... 17
3.3 Programul ................................................................................................................................ 18
4. SECRETUL NVRII RAPIDE A PROGRAMRII ................................................................................ 19
NOIUNI PRIMARE DE PROGRAMARE N PASCAL I C ....................................................... 20
EXEMPLE DE PROBLEME REZOLVATE................................................................................................... 21
METODA PRACTIC DE NVARE CE GARANTEAZ REZULTATE IMEDIATE ......... 26

PROBLEME SELECIONATE - ENUNURI ................................................................................ 26


PROBLEME PROPUSE SPRE REZOLVARE (PROBLEME DE ANTRENAMENT) ............................................. 26
PROBLEME DE EXAMEN ....................................................................................................................... 28
PROBLEME DIFICILE............................................................................................................................. 30
PROBLEME NESOLUIONATE NC ....................................................................................................... 32
PROBLEME INSOLVABILE ALGORITMIC ................................................................................................ 35
NOIUNI APROFUNDATE DE PROGRAMARE .......................................................................... 37
METODE I STRATEGII DE PROIECTARE A ALGORITMILOR (ALIAS TEHNICI DE PROGRAMARE).............. 37
BACKTRACKING. ................................................................................................................................. 39
GREEDY. ............................................................................................................................................. 42
PROGRAMAREA DINAMIC. ................................................................................................................. 42
BRANCH & BOUND. ............................................................................................................................. 43
RECURSIVITATEA ................................................................................................................................ 44
PROBLEME REZOLVATE I EXERCIII DE PROGRAMARE................................................ 49
PROBLEME ELEMENTARE. EXERCIII DE PROGRAMARE ....................................................................... 49
PROBLEME CE NECESIT BACK-TRACKING .......................................................................................... 66
PROBLEME CU SOLUIE SURPRINZTOARE .......................................................................................... 70
ELEMENTE DE PROGRAMARE A PC - URILOR ....................................................................................... 75
CURIOZITI I TRUCURI DE PROGRAMARE ......................................................................................... 91
CONFRUNTARE DE OPINII: INFORMATIC VERSUS MATEMATIC ............................... 93

BIBLIOGRAFIE, ADRESE I LOCAII DE INTERES PE INTERNET..................................... 95


Introducere
Exist multe culegeri de probleme de informatic ce permit nvarea i perfecionarea n
programare. Prin aceast culegere am ncercat nu doar s sporim aceast mulime cu nc una ci s
oferim un punct de vedere nou, original i incitant. Originalitatea nu este dat de enunurile
problemelor sau de rezolvrile oferite, ci de ideile i sfaturile cu caracter mobilizator pe care le oferim,
precum i de faptul c am introdus cteva capitole cu coninut mai puin obinuit ntr-o culegere de
probleme de programare.
Ni s-a prut mai important ca n aceste vremuri, caracterizate prin cuvintele "m simt ntr-o
permanent criz de timp", s oferim ct mai mult din experiena noastr direct, att cea de
programator ct i cea de profesor de programare. Dei nu credem c exist metode perfecte de predare
sau de nvare a programrii, totui sperm c prin asimilarea informaiilor originale oferite eficiena
procesului de nvare a programrii n limbajele C i Pascal va crete. Este important ca informaiile
suplimentare s fie asimilate gradat i numai n limita "suportabilitii" fiecruia. De aceea, n paginile
ce urmeaz vei gsi i o serie de informaii i sfaturi ce sintetizeaz experiena didactic acumulat ca
profesor de informatic i urmndu-le v asigurm c vei obine succesul n programare.
n primele capitole a fost pus un accent important pe motivarea iniial a celor ce doresc s
nvee programare. n capitolul "Ce anse am s devin un bun programator" snt chiar prezentate cu
sinceritate nzestrrile necesare unui bun programator.
Tot astfel se explic motivul introducerii unui capitol ce conine probleme de judecat.
Rezolvarea acestora pot fi considerate nu doar ca un excelent antrenament al minii ci i ca o bun
ocazie de a aprinde pasiunea pentru informatic i de a ntri motivaia programatorilor nceptori.
Asta nu nseamn c aceast culegere nu le este util i celor care au dobndit deja suficiente
cunotine de programare. Am introdus n ea cteva capitole ce conin informaii mai puin cunoscute.
Unul cuprinde o list de probleme deosebite, unele foarte dificile, altele crora nu li se cunoate nc o
soluie i altele pentru care exist demonstraie riguroas c nu pot fi rezolvate cu ajutorul
calculatorului. Alt capitol cuprinde exemple de programare a PC-urilor: lucrul cu tastatura, mouse-ul,
accesul direct la memoria ecran, etc. Iar unele capitole ca Noiuni aprofundate de programare,
Probleme cu soluie surprinztoare sau Curioziti i trucuri de programare le snt n ntregime
destinate celor care au depit stadiul de nceptor. Probabil c aceste informaii constituie o provocare
destul de substanial chiar i pentru cei avansai n ale programrii.
n concluzie, scopul acestei culegeri nu este doar de a contribui la formarea i specializarea
programatorilor sau pentru aprofundarea tehnicilor de programare, ct mai ales de a le oferi o baz, o
motivaie i o iniiere celor care doresc s fac primii pai n domeniul programrii. Iar acelor
mptimii ai programrii care se simt deja plictisii, stui sau plafonai le promitem c parcurgnd
aceast culegere vor aprofunda cunotinele pe care i le-au nsuit deja i, dac vor avea curajul de "a
se lua de piept" cu unele din problemele nesoluionate nc, li se va reaprinde cu siguran focul
pasiunii pentru programare.
nceptorilor le urm Bun venit n programare i tuturor Mult succes !

2
Ce anse am s devin un bun programator ?

Aceast ntrebare apare deseori n discuiile sincere dintre profesori i studenii lor descurajai
de ntrzierea apariiei unor rezultate care s certifice buna lor calitate ca programatori. Vom ncerca n
rndurile ce urmeaz s rspundem ct mai clar la aceast ntrebare oferind, n plus, o perspectiv
prosptat asupra acestui subiect, prin luarea n considerare a unei serii de factori mai puin utilizai n
procesul didactic contemporan.
Mai nti s vedem ce s-ar putea nelege prin sigtagma bun programator, insisitnd n
continuare doar pe aprofundarea adjectivului bun, fr a mai defini sau detalia ce se nelege printr-un
programator. Vom cita cuvintele recente ale lui Timoty Budd ( profesor la Oregon State University )
care d urmtoarea definiie: Un bun programator trebuie s fie nzestrat cu tehnic, experien,
capacitate de abstractizare, logic, inteligen, creativitate i talent. ntru-totul de acord cu aceast
definiie vom trece n cele ce urmeaz la explicitarea fiecrei caliti.
nainte vom deduce urmtoarea consecin imediat - deosebit de important - ce rezult din
definiia de mai sus: cele apte caliti trebuie s fie prezente toate pentru a se obine calificativul de
bun programator. Deci, prin lipsa sau prin prezena atrofiat a uneia , sau a mai multe din
ingredientele reetei de mai sus, acest calificativ nu mai poate fi atins.

1. Tehnica este desigur o calitate ce poate fi, i este, dobndit doar prin aplicarea asidu (conform
proverbului: exerciiul l face pe maestru) n activitatea concret de programare a tehnicilor de
programare nvate i asimilate de ctre programator n timpul formrii sale profesionale. Nu este
exclus aici posibilitatea obinerii tehnicii de programare nafara unui cadru specializat (ntr-o
facultate de profil ), ci chiar exist posibilitatea obinerii ei prin studiu individual i formaie
proprie (autodidact ).
2. Experiena este perechea geamn a calitii de mai nainte, fr ns a se exclude una pe
cealalt. Nu vom mai repeta cum i n ce condiii poate fi ea obinut ci vom deduce urmtoarea
consecina imediat : nici un programator nceptor nu poate fi numit bun programator ntruct
el nu a avut cnd (adic timpul necesar ) s dobndeasc ambele caliti. Este binecunoscut faptul
c o rubric important ce se cere completat la angajare sau la schimbarea locului de munc este
experiena de programare n ani. Se consider n general c experiena apare abia dup minimum
doi ani de programare. Acest fapt nu trebuie privit ca o descurajare pentru cei mai tineri
programatori ci mai degrab ca pe un motiv de ambiionare i ca o invitaie la rapid
autoperfecionare.
3. Abstractizarea este o trstur a intelectului uman i constituie un dat al oricrui om normal, dar
din pcate(!) este o nsuire prea puin dezvoltat i prea puin folosit de oamenii obinuii. Ea
const din capacitatea de a extrage din context, de a vedea dincolo de suprafaa imediat i de a
putea sesiza structura scheletul ce susine ntreaga reea de detalii ale unei probleme generale.
Pentru a fi un bun programator acest calitate trebuie s fie net amplificat fa de normal
ntruct st la baza oricrui proces de analiz i modelare a problemelor, ct i la baza procesului de
proiectare a soluiilor generale. Absena sau mai exact atrofierea acestei capaciti se constat
practic la studeni prin incapacitatea de a nelege sau de a asimila explicaii, demonstraii sau
modele abstracte ( simplu spus, o acut i permanent lips de chef atunci cnd snt atinse
anumite subiecte ce nu mai au contact direct cu realitatea concret, imediat adic subiecte
abstracte ). Metoda pentru a recpta sau a amplifica aceast capacitate este de a face ct mai des
uz de ea, adic de a o exersa mereu (conform zicalei funcia creeaz organul) ntr-un domeniu
particular, susinut de o motivaie personal puternic. Altfel spus, capacitatea noastr de
abstractizare se va amplifica dac vom ncerca gsirea de soluii la problemele dintr-unul din
domeniile noastre preferate, pentru c rezolvarea acestora va fi automotivat, fcut cu chef i
va prezenta o doz sporit de atractivitate.
4. Logica este o alt calitate intrinsec a oricrui intelect sntos. Ea este absolut necesar att
pentru a putea folosi mecanismele mentale de deducie i inducie logic, ct i pentru a putea
nelege uor, dar n acelai timp corect, cursul firul rou al unei demonstraii sau al unui
raionament ntins pe mai multe pagini. Asemenea tuturor calitilor intrinseci existente n stare
potenial, antrenarea i amplificarea acesteia se face prin exerciiu repetat, prin folosirea ei n mod
curent.Din pcate, doar prin rezolvarea de integrame nu se ajunge la amplificarea logicii
5. Inteligena este una din cele mai de pre caliti intrinseci ale intelectului uman. n cteva cuvinte,
fr a avea pretenia de a da prin acestea o definiie, prin inteligen nelegem capacitatea de a face
(de a stabili) conexiuni sau legturi noi i folositoare (din latinescul inter-legere) ntre idei,
cunotine sau informaii aparent fr legtur. Fa de logic, pe care o considerm ca fiind o

3
calitate bazal, inteligena este o calitate ce se ntinde pe verticala intelectului i are n plus
trstura de a fi mult mai dinamic i mai mobil (chiar fulgertor de rapid) n aciune. Pentru
cultivarea, amplificarea i cizelarea acestei caliti este nevoie de punerea ei la lucru ct mai des
i pe durate tot mai mari de timp. Insatisfacia obinerii unor rezultate rapide sau chiar imediate
este un obstacol ce poate fi depit relativ uor prin antrenarea inteligenei pe un teren cunoscut
i accesibil, adic n domeniul preferat de interes. n acest fel exist sigurana de a fi susinut de
atracia sporit pentru acel domeniu particular ceea ce va conduce prin efort perseverent (dar
susinut de aceast dat cu pasiune !) la apariia rezultatelor ateptate i, implicit, a satisfaciei.
6. Creativitatea este o calitate intrinsec nu numai intelectului uman ci nsi vieii n general. Ea
const, n ultim instan, n capacitatea de a face (de a produce) ceva cu adevrat nou i original.
De aceea am putea afirma c toate organismele vii, prin capacitatea lor de a se opune entropiei,
creeaz mereu ordine din dezordine aducnd n acest fel ceva nou, neateptat. Ceea ce se ateapt
ns de la un bun programator nu este doar acest tip de creativitate (gen: adaptare incontient i
instinctiv) ci o creativitate contient, responsabil, reflectat n adaptarea soluiilor existente sau
chiar inventarea altora noi. n acest sens trebuie s menionm c exist o legtur strns, dovedit
i verificat n practic (chiar dac pare oarecum inexplicabil la prima vedere), ntre creativitate
inteligen fluid curiozitate sublimarea impulsurilor erotice - umor i poft de via.
Cultivarea i amplificarea controlat a oricrora dintre aceste patru trsturi va conduce n mod
automat la amplificarea i dinamizarea creativitii intelectuale.
7. Talentul este singura calitate ce nu poate fi cultivat i amplificat. n accepiunea sa obinuit,
prin talent se nelege o sum de nzestrri native sau o predispoziie personal pentru un anumit
domeniu. Existena talentului este perceput de cel n cauz ca uurin abilitate - dexteritate de
a nva, asimila i aplica toate cunotinele domeniului respectiv, abilitate ce este simit de cel
"talentat" ca un fel de ceva n plus n comparaie cu capacitile celor din jur. Din pcate, n
accepiunea comun se crede c talentul este calitatea suficient care permite oricui atingerea cu
siguran a calificativului bun programator, concepie este infirmat de orice programator cu
experien. Asta nu nseamn c lipsa talentului n programare este permis pentru atingerea
acestui nivel, ns efortul, tenacitatea i rbdarea existente n cantiti mult sporite ntr-o
asemenea situaie de ne-nzestrare cu talent vor permite o apropiere sigur de acest calificativ. Din
pcate, lipsa talentului va aprea la nceput sub forma unei insatisfacii interioare i ca o impresie
acut c lipsesc rezultatele. Reamintim c nsi cuvntul facultate are la origine sensul de
capacitate, potenialitate, nzestrare. Deci, normal ar fi ca alegerea unui student pentru
frecventarea cursurilor unei Faculti s fi fost fcut innd cont de aptitudinile i abilitile celui
n cauz, descoperite n prelabil, adic s se dovedeasc talentat pentru domeniul ales. Acest lucru
este cu att mai important n cazul optrii pentru nvarea programrii, cunoscut fiind ca o
specializare complex i solicitant.

Relund n sintez ideile prezentate, putem spune c:


Pentru a fi un bun programator trebuie s fie prezente urmtorele apte caliti ntr-o form
activ, dinamic: tehnic, experien, capacitate de abstractizare, logic, inteligen,
creativitate i talent.
Dintre toate cele apte caliti necesare programrii de nalt calitate, numai una talentul - nu
este inerent unui intelect sntos. De altfel, prezena talentului nu este absolut necesar
pentru a deveni programator, dar n timp ce absena lui ngreuneaz apropierea de calificativul
bun programator, prezena lui i amplificarea celorlalte caliti este o garanie a succesului, ce
va fi cu siguran obinut, ns nu fr efort, rbdare i perseveren !
Toate celelalte ase caliti excluznd talentul, prezente fiind ntr-o form potenial, trebuiesc
doar cultivate i amplificate. Am prezentat mai sus n detaliu modul de amplificare a fiecreia.
Cheia secret ce conduce cu siguran la declanarea procesului de dinamizare i
amplificare a fiecreia din cele ase caliti inerente este de a avea mereu o motivaie
puternic (de a nva cu chef sau cu tragere de inim !). Acest fapt este posibil dac se
ine cont de necesitatea adaptrii efortului la domeniul preferat al celui n cauz. La modul
concret, este necesar ca toate aplicaiile, problemele, exerciiile, ntrebrile, curiozitile,
inovaiile, descoperirile, spturile, etc., s fie fcute sau s fie alese, la nceput, din
domeniul preferat (hobby-ul), chiar dac acesta nu are la prima vedere legtur cu
programarea. Scopul ce se atinge cu siguran n acest mod n aceast prim faz este acela de
a pune la lucru inteligena, creativitatea, logica, etc., ceea ce va conduce cu siguran la
trezirea i amplificarea rapid a acestor caliti. Acest fapt va permite apoi trecerea la o a doua
faz n care, pe baza acumulrilor calitative obinute, se poate trece la programarea propriu-
zise narmat cu fore proaspete.

4
ncheiem rspunznd ntr-o singur fraz ntrebrii din titlu Ce anse am s devin un bun
programator ? :
dac m simt nzestrat cu talent pentru programare (adic nu m simt inconfortabil la acest
subiect) atunci, mobilizndu-mi voina (motivaia) i amplificndu-mi capacitatea de abstractizare,
logica, inteligena i creativitatea (ce exist n mine ntr-o form potenial), prin practic de
programare voi acumula n timp tehnica i experiena necesare pentru a deveni cu siguran un
bun programator , ns nu fr efort, rbdare i perseveren.

5
Legile succesului durabil (Ghidul studentului ndrtnic)
Cunoate-i Regulile de aur ale studentului mecher ? Dac nu, le putei fi afla la o bere, de la
mecher la mecher. Noi le vom numi "Anti-legile succesului durabil" i vi le prezentm n
continuare doar pentru a putea observa cum fiecare din aceste "legi" este o rsturnare (pervertire) a
adevratelor legi ale succesului.

1. Cel mai important este s termini facultatea i s te vezi cu diploma n mn. Ce conteaz cum ?
Cine mai tie dup-aia ?
2. De ce s-nvei ? i aa majoritatea materiilor snt tembele i n-o s-i foloseasc niciodat n
via. materiile tembele trebuie s fie predate numai pentru ca s ctige i profii o pine.
3. Pune-te bine cu profesorii pn treci examenul. Stai cu ei la o igar n pauz. Las-i pe ei s
vorbeasc. Tu pref-te c eti interesat
4. Ai trecut examenul ? Da ? Atunci restul nu mai conteaz.
5. Nu conteaz dac ai nvat, ce tii sau ct tii. Important este s ai baft la examen, s ai mn
bun sau s mergi "bine pregtit" La puini profi nu se poate copia !
6. Snt examene la care, se tie bine, toat lumea copiaz. Trebuie s fi nebun s-nvei la ele !
7. Notele bune snt numai pentru piloi i tocilari.

Acestor studeni le snt ns complet necunoscute Legile succesului durabil. Ele ar putea fi intuite
doar de acei puini care s-au format i s-au educat n spiritul ideilor ce urmeaz s le explicm n
continuare. Aceste legi ne nva c bazele succesului durabil se pun nc din timpul colii i mai ales
din timpul facultii. i ne mai nva c succesul astfel "start-at" este destinat s dureze o via
ntreag.

1. Cel mai important n facultate este s-i faci o carte de vizit, nu-i suficient s vnezi doar
diploma. Dac vei fi apreciat i vei ajunge s fii considerat capabil sau chiar bun de cadrele
didactice "cu greutate", vei ajunge s fi cunoscut i bine cotat dup absolvire i-i vei gsi un loc
bun de munc. ntotdeauna a fost i va fi nevoie de oameni capabili "pe piaa muncii", nu de
liceniai "piloi", tolomaci sau papagali.
2. Cel mai important lucru n coal este c nvei cum s nvei. Cnd vrei s te recreezi rezolvnd
integrame nu prea conteaz ce din ce domeniu i le-ai ales. Important pentru tine nu este cum, ci
faptul c te destinzi. Tot astfel, n facultate important este nu neaprat ce nvei, ci c nvei! Multe
cunotine le vei uita n primii ani dup absolvire, mai ales cele pe care i le-ai nsuit ntr-o stare
de sforare i ncrncenare, fr plcere. Cel mai important este s nvei de plcere cci numai
aa vei nva cum s nvei. Iar aceasta nu se mai poate uita! i nu vei mai uita nicicnd c ai
resursele i puterea s treci prin fore proprii examenele cele mai grele.
3. Succesul n via se bazeaz pe relaii umane echilibrate. (Acest fapt era cunoscut i pe vremea
regimului partidului comunist romn P.C.R. ns datorit imoralitii generalizate a societii el a
fost aplicat pe invers: astfel, a apela de P.C.R. nsemna atunci s apelezi la Pile, Cunotine i
Relaii.) Deci, cel mai important lucru n coal este s nvei arta de a stabilii relaii umane
prietenoase i de ncredere reciproc. Ceea ce va conta cel mai mult, peste ani, este c ai stabilit
n timpul colii multe prietenii durabile i de ncredere care te vor mbogii astfel pentru toat
viaa. n plus, nu uita: i profesorii snt oameni. Au i ei nevoie de prieteni.
4. Colegii snt martori i devin cei mai exigeni judectori ai trsturilor tale de caracter.
Examenul, indiferent de materie sau disciplin, cu emoiile i peripeiile lui este n sine o lecie
complet. Nu conteaz att dac l-ai luat sau dac l-ai picat, ci conteaz cum! Conteaz ce fel de
om eti n astfel de situaii, cnd tocmai i construieti cartea de vizit sau blazonul. Nu uita c
nu te afli doar n faa profesorilor ci eti tot timpul nconjurat de colegii care te judec, chiar dac
ie nu-i spun. Pentru c aa cum te compori acum n examen, aa te vei comporta toat viaa.
5. Examenele grele snt cele care i pot forma un caracter puternic. Ceea ce este important n
examen, ca i n situaiile de via, este ncrederea n reuit i stpnirea de sine chiar dac n-ai
nvat toat materia. Dac ai nvat destul ca s te simi stpn pe tine atunci ai trecut
examenul ! Chiar acesta a fost rostul lui, ce dac i-a dat not mic! Crezi c, dup ce vei trece
examenul, peste zece ani i vei mai aminti cu ce not ?
6. Cei cu un caracter slab i vicios se vor da la un moment dat n vileag. Cei care copiaz nu-i dau
seama c ei i infecteaz caracterul. i nici ct de grave snt consecinele infectrii cu
microbul ctigului imediat obinut prin furt. Oare se vor mai putea debarasa vreodat de acest
viciu tentant ? Dar de cunoscutele "efecte secundare": sentimentul de nesiguran fr o fiuic n
buzunar, atracia irezistibil pentru aruncarea privirii mprejur, prerea de ru c Ce prost snt,

6
puteam s copiez tot !, etc. cnd vor mai scpa ? Cei care se obinuiesc s copieze, att ct vor
tri, vor fi jumtate om-jumtate fiuic. Ca n vechile bancuri cu miliieni
7. Oricine este acum apt s nvee i s-i nsueasc pentru ntreaga sa via Legea efortului. Pe
profesori i impresioneaz cel mai tare efortul depus i-l vor aprecia cu note maxime. Ei supra-
noteaz pe cei care vor, snt bine intenionai, dar nc nu pot. Profesorii cunosc adevrul
exprimat n Legea omului de geniu (legea lui Einstein): Geniul este compus 99% din
transpiraie i 1% din inspiraie. Profesorii adevrai se strduiesc s noteze mai ales calitatea
uman i profesional a studentului. Reinei: dac studentul a fost prietenos, activ i deschis n
timpul anului colar i a depus un efort constant pentru a se perfeciona, fapt ce nu a scpat
ochiului atent al profesorului, examenul devine n final pentru el o formalitate

Multe vorbe i preri pot fi auzite pe aceast tem n familie, n pauze la coal sau la barul
preferat. Ct snt ele de adevrate ? S-ar putea da oare o definiie precis pentru succesul n via ?
Noi nu cunoatem o astfel de definiie, tim doar c exist o multitudine de preri i opinii, unele
profund contradictorii. Este ns de bun sim s credem c se poate numi de succes acea via care
este plin de satisfacii, bucurii i visuri mplinite. Acea via care s-i merite din plin exclamaia:
Asta da, via ! ?
Regula de aur a succesului durabil este: nva s-i construieti singur viaa. i apoi, dac ai
nvat, apuc-te fr ntrziere s-i faci viaa fericit.
Studenia, prin entuziasmul, optimismul i idealismul ei, este o perioad optim pentru a nva
cum s-i faci o via de succes ! Atenie, muli i-au dat seama prea trziu c studenia a fost pentru ei
n multe privine ultimul tren

7
Probleme de judecat

Oferim n cele ce urmeaz o selecie de probleme ce nu necesit cunotine de matematic


avansate (doar nivelul gimnazial) dar care pun la ncercare capacitatea de judecat, inspiraia i
creativitatea gndirii. Rezolvarea acestor probleme constituie un bun antrenament pentru creterea
capacitii de gndire creativ precum i a fluiditii gndirii. Credem c nu degeaba aceste dou
trsturi snt considerate cele mai importante semne ale tinereii minii.
Problemele, selectate din multiple surse, nu au putut fi grupate n ordinea dificultii mai ales
datorit diversitii i varietii lor. Ele au fost doar separate n cteva categorii a cror nume vrea s
sugereze un anumit mod de gndire pe care l-am folosit i noi n rezolvarea lor. Cele cu un grad mai
mare de dificultate au fost marcate cu un semn (sau mai multe semne) de exclamare.
Criteriul principal pe baza cruia s-a fcut aceast selecie a fost urmtorul: fiecare problem
cere n rezolvarea ei un minimum de inventivitate i creativitate. Majoritatea problemelor te pun
"fa n fa cu imposibilul", aa c rezolvarea fiecrei probleme necesit depirea unor "limitri ale
gndirii" plus un minimum de originalitate n gndire. Tocmai de aceea, pentru rezolvarea lor este
nevoie de efort, putere de concentrare i perseveren. Zis ntr-un singur cuvnt: este necesar i un strop
de pasiune.
Considerm c eforturile consecvente ale celor care vor rezolva aceste probleme vor fi din plin
rspltite prin plcerea "minii biruitoare" i prin amplificarea calitilor urmtoare: capacitate sporit
de efort intelectual, putere de concentrare mrit i prospeime n gndire.
V dorim mult succes !

Probleme de perspicacitate

1. tiind c o sticl cu dop cost 1500 lei i c o sticl fr dop cost 1000 lei, ct cost un dop ?

2. tiind c un ou cost 1000 lei plus o jumtate de ou, ct cost un ou ?

3. Ce numr lipsete alturi de


ultima figur:
3 4 2 ?

4. Lui Popescu nici prin gnd nu-i trecea s foloseasc toate mijloacele pe care le avea la ndemn ca
s lupte mpotriva adversarilor tendinei contra neintroducerii micrii anti-fumat. Care este poziia
lui Popescu: este pentru sau contra fumatului ?

5. mprirea "imposibil". S se mpart numrul 12 n dou pri astfel nct fiecare parte s fie 7.

6. 9 puncte. S se secioneze toate cele 9 mici discuri cu o linie frnt nentrerupt (fr a ridica
creionul de pe hrtie) compus din 4 segmente. (!) Dar din trei segmente, este posibil ?

7. Trei cutii. n trei cutii identice snt nchise trei perechi de fructe: fie o pereche de mere, fie o
pereche de pere, fie o pereche format dintr-un mr i o par. Pe cele trei cutii snt lipite trei
etichete: "dou mere", "dou pere" i, respectiv, "un mr i o par". tiind c nici una din etichete
nu corespunde cu coninutul cuitei nchise pe care se afl, s se afle care este numrul minim de
extrageri a cte un fruct pentru a se stabili coninutul fiecrei cutii.

8. n ce direcie merge autobuzul din desenul alturat ?

8
9. (!) ntreruptoarele. Pe peretele alturat uei ncuiate de la intrarea unei ncperi, se afl trei
ntreruptoare ce corespund cu cele trei becuri de pe plafonul ncperii n care nu putem intra.
Acionnd oricare din ntreruptoare, dunga de lumin care apare pe sub u ne asigur c niciunul
din cele trei becuri nu este ars. Cum putem afla, fr a ptrunde n ncpere, care ntreruptor
corespunde cu care bec ?

10. (!!) Cine mut ultimul ctig. Doi juctori dispun de o mas de joc de form circular sau ptrat
i de un numr mare de monezi identice. Ei mut plasnd pe masa de joc n spaiul neocupat, fr
suprapunere, cte o moned alternativ pn cnd unul dintre juctori, care pierde n acest caz, nu
mai poate plasa nicieri o moned. S se arate c primul juctor are o strategie sigur de ctig.

11. (!!!) Iepurele i robotul-vntor. ntr-o incint nchis (un gen de aren) se afl un iepura i un
robot-vntor nzestrat cu cleti, mijloc de deplasare, calculator de proces i ochi electronici.
tiind c viteza de deplasare a robotului-vntor este constant i de zeci de ori mai mare dect a
iepuraului, ce anse mai are iepuraul de a scpa ?

12. Cntarul defect. Avnd la dispoziie un cntar gradat defect care greete constant cu aceeai
valoare (cantitate necunoscut de grame), putem s cntrim ceva determinndu-i corect greutatea ?

13. Jocul dubleilor (inventat de Carroll Lewis). tiind c trecerea de la un cuvnt cu sens la altul cu
sens este permis doar prin modificarea unei singure litere odat (de exemplu: UNU UNI
ANI ARI GRI GOI DOI ) se cere: Dovedii c IARBA este VERDE i c MAIMUA a
condus la OMENIRE, facei din UNU DOI, schimbai ROZ-ul n ALB, punei ROUGE pe OBRAZ
i facei s fie VARA FRIG.

14. mpturirea celor 8 ptrate. mpturii iniial n opt o foaie dreptunghiular dup care desfacei-o
i nsemnai fiecare din cele opt zone dreptunghiulare obinute (marcate de pliurile de ndoire) cu o
cifr de la 1 la 8. Putei mpturi foaia astfel obinut reducnd-o de opt ori (la un singur
dreptunghi sau ptrat) astfel nct trecnd cu un ac prin cele opt pliuri suprapuse acesta s le
perforeze exact n ordinea 1, 2, 3, , 8 ? ncercai aceste dou configuraii:

1 8 7 4
2 3 6 5

1 8 2 7
4 5 3 6

15. Problem pentru cei puternici. ncercai s mpturii de 8 ori, pur i simplu, o coal de hrtie (de
fiecare dat linia de ndoire este "n cruce" peste cea dinainte). Este posibil ? (!)Determinai ce
dimensiuni ar trebui s aib foaia la nceput pentru a putea fi mpturit de 8 ori.

16. Este posibil ca un cal s treac prin toate cele 64 de ptrele ale unei table de ah, ncepnd dintr-
un col i terminnd n colul diagonal opus ?

17. ntr-un atelier exist 10 ldie ce conin fiecare piese cu greutatea de 100 grame, cu excepia uneia
din ldie ce conine piese avnd grutatea de 90 grame. Putei preciza care este ldia cu pricina,
folosind un cntar doar pentru o singur dat ?

Probleme cu chibrituri

1. (!) Eliminnd un singur b de chibrit ceea ce rmne n faa ochilor este un elipsoid!

9
2. (!) 9 bee. S se aeze 9 bee de chibrit astfel nct ele s se ntlnesc la vrf tot cte trei n ase
vrfuri distincte.

3. De la 4 la 3. n figura ce conine 4 ptrate, mutnd 4 bee s se obin o figur ce conine doar 3


ptrate.

4. 6 = 2 ? Mutnd doar un singur b de chibrit s se restabileasc egalitatea:

5. Problema ariilor ntregi. Putei aeza 12 chibrituri astfel nct ele s formeze contururile unor
poligoane ce au aria ntreag egal cu 5, (!!) 4, 3, 2, (!!!) 1 ? Se subnelege c un chibrit poate fi
asimilat cu un segment de lungime 1 i c nu exist nici o dificultate de a forma "din ochi"
unghiuri drepte.

Probleme de logic i judecat

1. Substituirea literelor. Subtituii literele cu cifre astfel nct urmtoarele adunri s fie corecte:
GERALD + DONALD = ROBERT ; FORTY + TEN + TEN = SIXTY ; BALON + OVAL =
RUGBY.

2. Test de angajare la Microsoft. Patru excursioniti ajung pe malul unui ru pe care doresc s-l
traverseze. ntruct s-a noptat i ei dispun doar de o singur lantern, ei pot s treac rul cel mult
cte doi laolalt. tiind c, datorit diferenelor de vrst i datorit oboselii, ei ar avea individual
nevoie pentru a traversa rul de 1, 2, 8 i 10 minute, se cere s se decid dac este posibil
traversarea rului n aceste conditii n doar 17 minute ?

3. (!) Imposibil. S se taie toate cele 16 segmente ale figurii urmtoare cu o singur linie curb
continu i care nu se intersecteaz cu ea nsi.

4. (!) Problema "ochilor albatri". Sntem martorii urmtorului dialog ntre dou persoane X i Y.
<< X: Eu am trei copii. Produsul vrstei lor este 36 iar suma vrstei lor este egal cu numrul de
etaje al blocului din vecini de mine. l tii, nu-i aa ? Y: Desigur. Dar numai din ct mi-ai spsus nu
pot s deduc care este vrsta copiilor ti. X: Bine, atunci afl c cel mare are ochi albatrii.>>
Putei afla care este vrsta celor trei copii ?

5. Problema clugrului budhist. ntr-o diminea, exact la rsritul soarelui, un clugr budhist
pornete de la templul de la baza muntelui pentru a ajunge la templul din vrful muntelui exact la
apusul soarelui, unde el se roag toat noaptea. A doua zi el pornete din vrf pe aceei crare, tot
la rsritul soarelui, pentru a ajunge la templul de la baza muntelui exact la apusul soarelui. S se
arate c a existat un loc pe traseu n care clugrul s-a aflat n ambele zile exact la aceai or.

6. Vinul n ap i apa n vin. Dintr-o sticl ce conine un litru de ap este luat un pahar (un decilitru)
ce este turnat pest un litru de vin. Vinul cu apa se amestec bine dup care se ia cu acelai pahar o

10
cantitate egal de "vin cu ap" ce se toarn napoi peste apa din sticl. Avem acum mai mult ap
n vin dect vin n ap, sau invers ?

7. (!!!!) Cuiele n echilibru. Avem la dispoziie 7 cuie normale, cu capul obinuit. nfigem unul
vertical n podea (sau ntr-o plac de lemn). Se cere s se aeze cele 6 cuie rmase n echilibru
stabil pe capul cuiului vertical, fr ca niciunul din cele ase cuie s ating podeaua.

8. (!!) igrile tangente. Este posibil s aezm pe mas ase igri astfel nct fiecare s se ating cu
fiecare (oricare dou s fie tangente) ? (!!!) Dar apte igri ?

9. (!) Problema celor 12 nelepi (n variant modern). Managerul unei mari companii dorete s
pun la ncercare inteligena i puterea de judecat a celor 12 membrii ai consiliului su de
conducere. Lund 12 cri de joc, unele de pic i altele de caro, el le aeaz cte una pe fruntea
fiecrui consilier astfel nct fiecare s poat vedea crile de pe frunile celorlali dar nu i pe a sa.
Managerul le cere celor care consider c au pe frunte o carte de caro (diamond) s fac un pas n
fa, altfel ei nu vor mai putea face parte din consiliu. Dup ce i repet cererea de apte ori, timp
n care niciunul din cei 12 consilieri nu face nici o micare (ci doar se privesc unii pe alii), toi
consilierii care au ntr-adevr pe frunte o carte de caro ies deodat n fa. Putei deduce ci au ieit
i cum i-au dat ei seama ce carte este aezat pe fruntea lor ?

10. Pianjenul i musca. Pe peretele lateral al unei hale cu dimensiunile de 40 x 12 x12 metri, pe linia
median a peretelui lateral i exact la 1 metru de tavan, se afl un pianjen. Pe peretele lateral
opus, tot pe linia median i exact la 1 metru de podea, se afl o musc amorit. Care este distana
cea mai scurt pe care pianjenul o are de parcurs de-a lungul pereilor pentru a se nfrupta din
musc ?

11. Rifi i Ruf. Cei doi iubii Rifi i Ruf, din nordica ar Ufu-Rufu, locuiesc n sate diferite aflate la
distana de 20 km unul de altul. n fiecare diminea ei pornesc exact deodat (la rsrit) unul spre
cellalt spre a se ntlni i a se sruta confrom obiceiului nordic: nas n nas. ntr-o diminea o
musc rtcit pornete exact la rsritul soarelui de pe nasul lui Rifi direct spre nasul lui Ruf, care
o alung trimind-o din nou spre nasul lui Rifi, .a.m.d. ..., pn cnd ea sfrete tragic n
momentul "srutului" celor doi. tiind c Rifi se deplaseaz cu 4 km/or, Ruf cu 6 km/or iar
musca zboar cu 10 km/or, se cere s se afle ce distan a parcurs musca n zbor de la rsrit i
pn n momentul tragicului ei sfrit.

12. O anti-problem de ah. n urmtoarea configuraie a pieselor pe o tabl de ah se cere s nu dai


mat dintr-o mutare ! (Albul atac de jos n sus. Legenda: P-pion, N-nebun, R-rege, T-turn, C-cal.
Alturat fiecrei piese este scris culoarea sa, alb-a sau negru-n.)

N R T
Na Ra Ta
T N
Tn Na
T
Ta
N P P
Nn Pn Pn
P R P
Pa Rn Pa
P P P
Pn Pa Pn
P P P
Pa Pa Pa
C C
Ca Ca

13. Bronx contra Brooklyn. Un tnr, ce locuiete n Manhattan n imediata apropiere a unei staii de
metrou, are dou prietene, una n Brooklyn i cealalt n Bronx. Pentru a o vizita pe cea din
Brooklyn el ia metroul ce merge spre partea de jos a oraului, n timp ce, pentru a o vizita pe cea

11
din Bronx, el ia din acelai loc metroul care merge n direcie opus. Metrourile spre Brooklyn i
spre Bronx intr n staie cu aceei frecven: din 10 n 10 minute fiecare. Dar, dei el coboar n
staia de metrou n fiecare smbt la ntmplare i ia primul metrou care vine (nedorind s
"favorizeze" pe nici una din prietenele sale), el a constatat c, n medie, el merge n Brooklyn de 9
ori din 10. Putei gsi o explicaie logic a fenomenul ?

14. (!!) Problema celor 12 bile. n faa noastr se afl 12 bile identice ca form, vopsite la fel, dar una
este cu siguran fals, ea fiind fie mai grea, fie mai uoar, fiind fcut dintr-un alt material.
Avem la dispoziie o balan i se cere s determinm doar prin 3 cntriri care din cele 12 bile este
fals preciznd i cum este ea: mai grea sau mai uoar. (!!!) Mai mult, putei determina care este
numrul maxim de bile din care prin 4 cntriri cu balana se poate afla exact bila fals i cum este
ea ?

15. (!) Problema celor 2 perechi de mnui. Aflat ntr-o situaie ce implic intervenia de urgen, un
medic chirurg constat c are la dispoziie doar 2 perechi de mnui sterile dei el trebuie s
intervin rapid i s opereze succesiv 3 bolnavi. Este posibil ca cele trei operaii de urgen s se
desfoare n condiii de protecie normale cu numai cele 2 perechi de mnui ? (Sngele fiecruia
din cei 3 pacieni, precum i mna doctorului nu trebuie s conduc la un contact infecios.)

16. (!!) Problema frnghiei prea scurte. O persoan ce are asupra ei doar un briceag i o frnghie
lung de 30 metri se afl pe marginea unei stnci, privind n jos la peretele vertical de 40 metri aflat
sub ea. Frnghia poate fi legat doar n vrf sau la jumtatea peretelui (la o nlime de 20 metri de
sol) unde se afl o mic platform de sprijin. Cum este posibil ca persoana aflat n aceast situaie
s ajung teafr jos cobornd numai pe frnghie, fr a fi nevoit s sar deloc punndu-se astfel n
pericol ?

17. Problema lumnrilor neomogene. Avem la dispoziie chibrite i dou lumnri care pot arde
exact 60 minute fiecare ns, ele fiind neomogene, nu vor arde cu o vitez constant. Cum putem
msura precis o durat de 45 minute ?

18. (!!) O jumtate de litru. Avem n faa noastr un vas cilindric cu capacitatea de 1 litru, plin ochi
cu ap. Se cere s msurm cu ajutorul lui litru de ap, fr a ne ajuta de nimic altceva dect de
minile noastre.

19. (!) S vezi i s nu crezi. Privii urmtoarele dou figuri: prin reaezarea decupajelor interioare ale
primeia se obine din nou aceeai figur dar avnd un ptrel lips ! Cum explicai "minunea" ?

Probleme de logic i judecat cu "tent informatic"

1. (!!!) Decriptarea scrierii ncifrate. Se dau urmtoarele numere mpreun cu denumirile lor
cifrate:
5 nabivogedu
6 nagevogedu
10 nabivobinaduvogedu
15 nabivonagevogedunaduvogedu
20 nabivogenagevogenaduvogedu
25 nabivonabivobinagevogedunagevogenaduvogedu
30 nabivodunanabivobiduvogedu
50 nabivonabivonabivogedunagevogenaduvogedunanabivobiduvogedu
60 nabivonagevogedunagevogenanabivobiduvogedu
90 nabivonaduvogedunagevodunanabivobiduvogedu

12
100 nabivonabivobinagevogenaduvogedunagevodunanabivobiduvogedu

13
Care este regula de ncifrare? Ce numere reprezint urmtoarele coduri cifrate:
nagevonagevogedunanabivobiduvogedu;
nagevonaduvogedunanabivobiduvogedu;
naduvogenanabivobiduvogedu;
nanabivogeduvogedu;
nabivonabivonaduvogedunagevonagevogedunanabivobiduvogedu;
nanagevobiduvogedu?
ncifrai numerele 256 i 1024 prin acest metod.

2. (!!!) Altfel de codificare binar a numerelor. Descoperii metoda de codificare binar a


numerelor folosit n continuare:

1 1 20 101010
2 10 25 1000101
3 11 30 1010001
5 110 40 10001001
10 1110 50 10100100
15 10010 60 100001000
Putei spune ce numere snt codificate prin 100, 101, 1000, 1111, 10000 i 11111 ? Putei
codifica numerele 70, 80, 90, 100, 120, 150 i 1000 ?

3. (!!!) Problema dialogului perplex. Exist dou numere m i n din intervalul [2..99] i dou
persoane P i S astfel nct persoana P tie produsul lor, iar S tie suma lor. tiind c ntre P i S a
avut loc urmtorul dialog:
"Nu tiu numerele" spune P.
"tiam ca nu tii" rspunde S, "nici eu nu tiu."
"Acuma tiu !" zice P strlucind de bucurie.
"Acum tiu i eu" optete satisfcut S.
s se determine toate perechile de numere m i n ce "satisfac" acest dialog (snt soluii ale problemei).

4. (!!!!) mpturirea celor 8 ptrate. mpturii iniial n opt o foaie dreptunghiular dup care
desfacei-o i nsemnai fiecare ptrel obinut cu o cifr de la 1 la 8. Proiectai un algoritm i
realizai un program care, primind configuraia (numerotarea) celor 8 ptrele, s poat decide
dac se poate mpturi foaia astfel obinut reducnd-o de opt ori (la un singur ptrat) astfel nct
trecnd cu un ac prin cele opt foi suprapuse acesta s le perforeze exact n ordinea 1, 2, 3, , 8.

5. (!!!!) Problema fetelor de la pension. Problema a aprut pe vremea cnd fetele nvau la pension
fr ca prin prezena lor bieii s le tulbure educaia. Pedagoaga fetelor unui pension de 15 fete a
hotart ca n fiecare dupa-amiaz, la ora de plimbare, fetele s se plimbe n cinci grupuri de cte
trei. Se cere s se stabileasc o programare a plimbrilor pe durata unei sptmni (apte zile) astfel
nct fiecare fat s ajung s se plimbe numai o singur dat cu oricare din celelalte paisprezece
(oricare dou fete s nu se plimbe de dou ori mpreun n decursul unei sptmni).

14
Noiuni fundamentale de programare

Programarea este disciplina informatic ce are ca scop realizarea de programe care s


constituie soluiile oferite cu ajutorul calculatorului unor probleme concrete. Programatorii snt acele
persoane capabile s implementeze ntr-un limbaj de programare metoda sau algoritmul propus ca
soluie respectivei probleme, ce se preteaz a fi soluionat cu ajutorul calculatorului. Dup nivelul de
implicare n efortul de rezolvare a problemelor specialitii n programare pot fi mprii n diverse
categorii: analiti, analiti-programatori, ingineri-programatori, simpli programatori, etc. Cu toii au
ns n comun faptul c fiecare trebuie s cunoasc ct mai bine programare i s fie capabil, nu doar s
citeasc, ci chiar s scrie codul surs, adic programul propriu-zis. Din acest punct de vedere
cunotinele de programare snt considerate ABC-ul informaticii i snt indispensabile oricrui
profesionist n domeniu.

1.Cele trei etape ale rezolvrii unei probleme cu ajutorul calculatorului

n rezolvarea sa cu ajutorul calculatorului orice problem trece prin trei etape obligatorii:
Analiza problemei, Proiectarea algoritmului de soluionare i Implementarea algoritmului ntr-un
program pe calculator. n ultima etap, sub acelai nume, au fost incluse n plus dou subetape
cunoscute sub numele de Testarea i ntreinerea programului. Aceste subetape nu lipsesc din ciclul
de via a oricrui produs-program ce se respect dar , pentru simplificare, n continuare ne vom
referi doar la primele trei mari etape.
Dac etapa implementrii algoritmului ntr-un program executabil este o etap exclusiv
practic, realizat n faa calculatorului, celelalte dou etape au un pronunat caracter teoretic. n
consecin, primele dou etape snt caracterizate de un anumit grad de abstractizare. Din punct de
vedere practic ns, i n ultim instan, criteriul decisiv ce confer succesul rezolvrii problemei este
dat de calitatea implementrii propriuzise. Mai exact, succesul soluionrii este dat de performanele
programului: utilitate, vitez de execuie, fiabilitate, posibiliti de dezvoltare ulterioare, lizibilitate, etc.
Cu toate acestea este imatur i neprofesional strategia programatorilor nceptori care, neglijnd
primele dou etape, sar direct la a treia fugind de analiz i de componenta abstract a efortului de
soluionare. Ei se justific cu toii prin expresii puerile de genul: Eu nu vreau s mai pierd vremea cu
teoria, am s fac programul cum tiu eu. Ct vreme nu va face altcineva altul mai bun dect al meu,
nu am de ce s-mi mai bat capul !.

2.Cum se stabilete corectitudinea i eficiena soluionrii ?

Este adevrat c ultima etap n rezolvarea unei probleme implementarea este decisiv i
doveditoare, dar primele dou etape au o importan capital. Ele snt singurele ce pot oferi rspunsuri
corecte la urmtoarele ntrebri dificile: Avem certitudinea c soluia gsit este corect ? Avem
certitudinea c problema este complet rezolvat ? Ct de eficient este soluia gsit ? Ct de departe
este soluia aleas de o soluie optim ?
S menionm n plus c literatura informatic de specialitate conine un numr impresionant
de probleme capcan pentru nceptori, i nu numai pentru ei. Ele provin majoritatea din realitatea
imediat dar pentru fiecare dintre ele nu se cunosc soluii eficiente. De exemplu, este dovedit teoretic
c problema, aparent banal pentru un calculator, a proiectrii Orarului optim ntr-o instituie de
nvmnt (coal, liceu, facultate) este o problem intratabil la ora actual (toate programele care s-
au realizat pn acum nu ofer dect soluii aproximative fr a putea spune ct de aproape sau de
departe este soluia optim de orar).
Ci dintre programatorii nceptori n-ar fi surprini s afle c problema att de simpl (ca
enun), a crei soluionare tocmai au abandonat-o, este de fapt o problem dovedit teoretic ca fiind
intratabil sau chiar insolvabil algoritmic ? Partea proast a lucrurilor este c, aa cum ciupercile
otrvite nu pot fi cu uurin deosebite de cele comestibile, tot astfel problemele netratabile pot fi cu
uurin confundate cu nite probleme uoare la o privire rapid i lipsit de experien.
Dac ar fi s sintetizm n cte un cuvnt efortul asupra cruia se concentreaz fiecare din cele
trei etape analiza, proiectarea i implementarea cele trei cuvinte ar fi: corectitudine, eficien i
impecabilitate. Etapa de analiz este singura care permite dovedirea cu argumente riguroase a

15
corectitudinii soluiei, iar etapa de proiectare este singura care poate oferi argumente precise n
favoarea eficienei soluiei propuse.
n general problemele concrete din informatic au n forma lor iniial sau n enun o
caracteristic pragmatic, fiind foarte ancorate n realitatea imediat. Totui ele conin n formularea lor
iniial un grad mare de eterogenitate, diversitate i lips de rigoare. Fiecare dintre aceste defecte
este un obstacol major pentru demonstrarea corectitudinii soluiei. Rolul esenial al etapei de analiz
este acela de a transfera problema de pe nisipurile mictoare ale realitii imediate de unde ea
provine ntr-un plan abstract, adic de a o modela. Acest univers paralel abstract este dotat cu mai
mult rigoare i disciplin intern, avnd legi precise, i poate oferi instrumentele logice i formale
necesare pentru demonstrarea riguroas a corectitudinii soluiei problemei. Planul abstract n care snt
transportate toate problemele de informatic este planul sau universul obiectelor matematice iar
corespondentul problemei n acest plan va fi modelul matematic abstract asociat problemei.
Demonstrarea corectitudinii proprietilor ce leag obiectele universului matematic a fost i este sarcina
matematicienilor. Celui ce analizeaz problema din punct de vedere informatic i revine sarcina (nu
tocmai uoar) de a dovedi printr-o demonstraie constructiv c exist o coresponden precis (o
bijecie !) ntre prile componente ale problemei reale, dezasamblat n timpul analizei, i prile
componente ale modelului abstract asociat. Odat descoperit, formulat precis i dovedit, aceast
perfect oglindire a problemei reale n planul obiectelor matematice ofer certitudinea c toate
proprietile i legturile ce exist ntre subansamblele modelului abstract se vor regsii precis (prin
reflectare) ntre prile interne ale problemei reale, i invers. Atunci, soluiei abstracte descoperite cu
ajutorul modelului matematic abstract i va corespunde o soluie real concretizat printr-un algoritm ce
poate fi implementat ntr-un program executabil.
Aceasta este calea general de rezolvare a problemelor i oricine poate verifica acest fapt. De
exemplu, ca i exerciiu, ncercai s demonstrai corectitudinea (adic s se aduc argumente precise,
clare i convingtoare n favoarea corectitudinii) metodei de extragere a radicalului nvat nc din
coala primar (cu grupare cifrelor numrului n grupuri cte dou, etc) sau a algoritmului lui Euclid
de determinare a celui mai mare divizor comun a dou numere prin mpriri ntregi repetate. Desigur
nu pot fi acceptate argumente copilreti de forma: Algoritmul este corect pentru c aa l-am nvat!
sau Este corect pentru c aa face toat lumea ! din moment ce nu se ofer o argumentaie
matematic riguroas.
Ideea central a etapei a doua proiectarea unui algoritm de soluionare eficient poate fi
formulat astfel: din studiul proprietilor i limitelor modelului matematic abstract asociat problemei
se deduc limitele inferioare ale complexitii minimale (efortului minimal obligatoriu) inerente
oricrui algoritm ce va soluiona problema n cauz. Complexitatea intern a modelului abstract i
complexitatea soluiei abstracte se va reflecta imediat asupra complexitii reale a algoritmului, adic
asupra eficienei de soluionare a problemei. Acest fapt permite prognosticarea nc din aceast faz
faza de proiectare a algoritmului de soluionare a eficienei practice, msurabil ca durat de
execuie, a programului.

3. Noiunile fundamentale ale programrii: algoritm, limbaje de descriere a algoritmilor,


program, limbaje de programare

3.1. Algoritmul

Se tie c la baza oricrui program st un algoritm (care, uneori, este numit metod de
rezolvare). Noiunea de algoritm este o noiune fundamental n informatic i nelegerea ei, alturi de
nelegerea modului de funcionare a unui calculator, permite nelegerea noiunii de program
executabil. Vom oferi n continuare o definiie unanim acceptat pentru noiunea de algoritm:

Definiie. Prin algoritm se nelege o mulime finit de operaii (instruciuni) elementare care
executate ntr-o ordine bine stabilit (determinat), pornind de la un set de date de intrare dintr-un
domeniu de valori posibile (valide), produce n timp finit un set de date de ieire (rezultate).

Cele trei caracteristici eseniale ale unui algoritm snt:

1. Determinismul dat de faptul c ordinea de execuie a instruciunilor algoritmului este bine


precizat (strict determinat).

16
Acest fapt d una din calitile de baz a calculatorului: el va face ntotdeauna ceea ce i s-a cerut
(prin program) s fac, el nu va avea iniiative sau opiuni proprii, el nu-i permite s
greeasc nici mcar odat, el nu se va plictisi ci va duce programul la acelai sfrit indiferent
de cte ori i se va cere s repete acest lucru. Nu aceeai situaie se ntmpl cu fiinele umane
(Errare humanum est). Oamenii pot avea n situaii determinate un comportament non-
deterministic (surprinztor). Acesta este motivul pentru care numeroi utilizatori de calculatoare
(de exemplu contabilii), datorit fenomenului de personificare a calculatorului (confundarea
aciunilor i dialogului simulat de programul ce ruleaz pe calculator cu reaciile unei
personaliti vii), nu recunosc perfectul determinism ce st la baza executrii oricrui program pe
calculator. Exprimndu-se prin propoziii de felul: De trei ori i-am dat s fac calculele i de
fiecare dat mi-a scos aceleai valori aiurea! ei i trdeaz propria viziune personificatoare
asupra unui fenomen determinist.
2. Universalitatea dat de faptul c, privind algoritmul ca pe o metod automat (mecanic) de
rezolvare, aceast metod are un caracter general-universal. Algoritmul nu ofer o soluie
punctual, pentru un singur set de date de intrare, ci ofer soluie pentru o mulime foarte larg (de
cele mai multe ori infinit) de date de intrare valide. Aceasta este trstura de baz care explic
deosebita utilitate a calculatoarelor i datorit acestei trsturi sntem siguri c investiia financiar
fcut prin cumprarea unui calculator i a produsului-soft necesar va putea fi cu siguran
amortizat. Cheltuiala se face o singur dat n timp ce programul pe calculator va putea fi
executat rapid i economicos de un numr orict de mare de ori, pe date diferite !
De exemplu, metoda (algoritmul) de rezolvare nvat la liceu a ecuaiilor de gradul doi:
ax2+bx+c=0, se aplic cu succes pentru o mulime infinit de date de intrare: (a,b,c)\{0}xx.
3. Finitudinea pentru fiecare intrare valid orice algoritm trebuie s conduc n timp finit (dup un
numr finit de pai) la un rezultat. Aceast caracteristic este analog proprietii de convergen a
unor metode din matematic: trebuie s avem garania, dinainte de a aplica metoda (algoritmul),
c metoda se termin cu succes (ea converge ctre soluie).
S observm i diferena: n timp ce metoda matematic este corect chiar dac ea converge ctre
soluie doar la infinit (!), un algoritm trebuie s ntoarc rezultatul dup un numr finit de pai. S
observm deasemenea c, acolo unde matematica nu ofer dovada, algoritmul nu va fi capabil s o
ofere nici el. De exemplu, nu este greu de scris un algoritm care s verifice corectitudinea
Conjecturii lui Goldbach: Orice numr par se scrie ca sum de dou numere prime, dar, dei
programul rezultat poate fi lsat s ruleze pn la valori extrem de mari, fr s apar nici un
contra-exemplu, totui conjectura nu poate fi astfel infirmat (dar nici afirmat!).

3.2. Descrierea algoritmilor

Dou dintre metodele clasice de descriere a algoritmilor snt denumite Schemele logice i Pseudo-
Codul. Ambele metode de descriere conin doar patru operaii (instruciuni) elementare care au fiecare
un corespondent att schem logic ct i n pseudo-cod.
n cele ce urmeaz vom nira doar varianta oferit de pseudo-cod ntruct folosirea schemelor
logice s-a redus drastic n ultimii ani. Schemele logice mai pot fi ntlnite sub numele de diagrame de
proces n anumite cri de specialitate inginereti. Avantajul descrierii algoritmilor prin scheme logice
este dat de libertatea total de nlnuire a operaiilor (practic, sgeata care descrie ordinea de execuie,
pleac de la o operaie i poate fi trasat nspre orice alt operaie). Este demonstrat matematic riguros
c descrierea prin pseudo-cod, dei pare mult mai restrictiv (operaiile nu pot fi nlnuite oricum, ci
trebuie executate n ordinea citirii: de sus n jos i de la stnga la dreapta), este totui perfect
echivalent. Deci, este dovedit c plusul de ordine, rigoare i simplitate pe care l ofer descrierea prin
pseudo-cod nu ngrdete prin nimic libertatea programrii. Totui, programele scrise n limbajele de
asamblare, care snt mult mai compacte i au dimensiunile mult reduse, nu ar putea fi descrise altfel
dect prin scheme logice.

1. Atribuirea var:=expresie;

2. Intrare/Ieire Citete var1, var2, var3, ;


Scrie var1, var2, var3, ; sau Scrie expresia1, expresia2, expresia3,;

3. Condiionala - Dac <condiie_logic> atunci instruciune1 [altfel instruciune2];

17
4. Ciclurile Exist (din motive de uurin a descrierii algoritmilor) trei tipuri de instruciuni de
ciclare. Ele snt echivalente ntre ele, oricare variant de descriere putnd fi folosit n locul
celorlalte dou, cu modificri sau adugiri minimale:

Repet instruciune1, instruciune2, pn cnd <condiie_logic>;

Ct timp <condiie_logic> execut instruciune;

Pentru var_contor:=val_iniial pn la val_final execut instruciune;

n cazul ciclurilor, grupul instruciunilor ce se repet se numete corpul ciclului iar condiia
logic care (asemenea semaforului de circulaie) permite sau nu reluarea execuiei ciclului este
denumit condiia de ciclare sau condiia de scurt-circuitare (dup caz). Observm c ciclul de tipul
Repet are condiia de repetare la sfrit ceea ce are ca i consecin faptul c corpul ciclului se execut
cel puin odat, n mod obligatoriu, nainte de verificarea condiiei logice. Nu acelai lucru se ntmpl
n cazul ciclului de tipul Ct timp, cnd este posibil ca instruciunea compus din corpul ciclului s nu
poat fi executat nici mcar odat. n plus, s mai observm c ciclul de tipul Pentru pn la
conine (n mod ascuns) o instruciune de incrementare a variabilei contor.
n limba englez, cea pe care se bazeaz toate limbajele actuale de programare acestor
instruciuni, exprimate n limba romn, le corespund respectiv: 2. Read, Write; 3. If-Then-Else; 4.
Repeat-Until, Do-While, For. S observm c, mai ales pentru un vorbitor de limb englez,
programele scrise ntr-un limbaj de programare ce cuprinde aceste instruciuni este foarte uor de citit i
de neles, el fiind foarte apropiat de scrierea natural. Limbajele de programare care snt relativ
apropiate de limbajele naturale snt denumite limbaje de nivel nalt (high-level), de exemplu limbajul
Pascal, spre deosebire de limbajele de programare mai apropiate de codurile numerice ale
instruciunilor microprocesorului. Acestea din urm se numesc limbaje de nivel sczut (low-level), de
exemplu limbajul de asamblare. Limbajul de programare C are un statut mai special el putnd fi privit,
datorit structurii sale, ca fcnd parte din ambele categorii.
Peste tot unde n pseudo-cod apare cuvntul instruciune el poate fi nlocuit cu oricare din cele
patru instruciuni elementare. Aceast substituire poart numele de imbricare (de la englezescul brick-
crmid). Prin instruciune se va nelege atunci, fie o singur instruciune simpl (una din cele patru),
fie o instruciune compus. Instruciunea compus este format dintr-un grup de instruciuni delimitate
i grupate n mod precis (ntre acolade { } n C sau ntre begin i end n Pascal).
Spre deosebire de pseudo-cod care permite doar structurile noi formate prin imbricarea
repetat a celor patru instruciuni (crmizi) n modul precizat, schemele logice permit structurarea n
orice succesiune a celor patru instruciuni elementare, ordinea lor de execuie fiind dat de sensul
sgeilor. Repetm c dei, aparent, pseudo-codul limiteaz libertatea de descriere doar la structurile
prezentate, o teorem fundamental pentru programare afirm c puterea de descriere a pseudo-
limbajului este aceeai cu cea a schemelor logice.
Forma de programare care se bazeaz doar pe cele patru structuri se numete programare
structurat (spre deosebire de programarea nestructurat bazat pe descrierea prin scheme logice).
Teorema de echivalen a puterii de descriere prin pseudo-cod cu puterea de descriere prin schem
logic afirm c programarea structurat (aparent limitat de cele patru structuri) este echivalent cu
programarea nestructurat (liber de structuri impuse). Evident, prin ordinea, lizibilitatea i fiabilitatea
oferit de cele patru structuri elementare (i asta fr a ngrdi libertatea de exprimare) programarea
structurat este net avantajoas. n fapt, limbajele de programare nestructurat (Fortran, Basic) au fost
de mult scoase din uz, ele (limbajele de asamblare) snt necesare a fi folosite n continuare doar n
programarea de sistem i n programarea industrial (n automatizri).

3.3 Programul

Prin program se nelege un ir de instruciuni-main care snt rezultatul compilrii


algoritmului proiectat spre rezolvarea problemei dorite ce a fost descris ntr-un limbaj de programare
(ca i cod surs).
Etapele realizrii unui program snt:
Editarea codului surs, etap ce se realizeaz cu ajutorul unui program editor de texte rezultatul
fiind un fiier Pascal sau C, cu extensia .pas sau .c (.cpp)

18
Compilarea, etapa de traducere din limbajul de programare Pascal sau C n limbajul intern al
micro-procesorului, i este realizat cu ajutorul programului compilator Pascal sau C i are ca
rezultat un fiier obiect, cu extensia .obj (n limbajul C) sau .exe (n limbajul Pascal)
Link-editarea, etap la care se adaug modului obiect rezultat la compilare diferite module
coninnd subprograme i rutine de bibliotec, rezultnd un fiier executabil (aceast etap este
comasat n Turbo Pascal sau Borland Pascal cu etapa de compilare), cu extensia .exe
Execuia (Run), etapa de lansare n execuie propriu-zis a programului obinut, lansare realizat de
interpretorul de comenzi al sistemului de operare (command.com pentru sistemele DOS+Windows)
Observm c aceste patru (sau trei, pentru Turbo Pascal) etape snt complet independente n timp
unele de altele i necesit utilizarea a patru programe ajuttoare: Editor de texte, Compilator Pascal sau
C, Link-editor i Interpretorul de comenzi al S.O. n cazul mediilor de programare integrate (Turbo sau
Borland) comandarea acestor patru programe ajuttoare precum i depanarea erorilor de execuie este
mult facilitat.
Deasemenea, merit subliniat faptul c n timp ce fiierul text Pascal sau C, ce conine codul surs,
poate fi transportat pe orice main (calculator) indiferent de micro-procesorul acesteia urmnd a fi
compilat "la faa locului", n cazul fiierului obiect acesta nu mai poate fi folosit dect pe maina
(calculatorul) pentru care a fost creat (datorit instruciunilor specifice micro-procesorului din care este
compus). Deci, pe calculatoare diferite (avnd micro-procesoare diferite) vom avea nevoie de
compilatoare Pascal sau C diferite.
n plus, s remarcm faptul c fiierele obiect rezultate n urma compilrii pot fi link-editate (cu
grij !) mpreun chiar dac provin din limbaje de programare diferite. Astfel, un program rezultat (un
fiier .exe sau .com) poate fi compus din module obiect care provin din surse diferite (fiiere Pascal, C,
asamblare, etc.).

4. Secretul nvrii rapide a programrii

Exist posibilitatea nvrii rapide a programrii ?


Desigur. Experiena predrii i nvrii programrii ne-a dovedit c exist metode diferite de
nvare a programrii, mai rapide sau mai lente, mai temeinice sau mai superficiale. Din moment ce se
dorete nvarea rapid a programrii nseamn c, pentru cel ce dorete aceasta, problemele ce i
ateapt rezolvarea cu ajutorul calculatorului snt importante sau stringente. Am putea chiar presupune
c soluionarea lor rapid este un deziderat mai important dect nvarea programrii. Tocmai de aceea,
fiind contieni de acest fapt, vom prezenta n continuare una din cele mai rapide metode de nvare a
programrii.
S observm mai nti c pentru nvarea unei limbi strine este necesar comunicarea i
vorbirea intens a acelei limbi. Cu toii am putut constata c dac exist o motivaie sau nevoie
puternic de a comunica n acea limb, cel puin pentru o perioad de timp, procesul de nvare a ei
este foarte rapid. De exemplu, dac ne aflm ntr-o ar strin sau dac dorim apropierea de o persoan
strin (mai ales dac este atrgtoare i de sex opus) categoric vom constata c am nvat mult mai
iute limba respectiv. i aceasta datorit faptului c efortul de nvare a fost mascat n spatele efortului
(intens motivat!) de a comunica i de a ne face cunoscute inteniile i gndurile.
La fel, pentru nvarea rapid i cu uurin a programrii efortul trebuie ndreptat, nu spre
silabisirea limbajului de programare, ci spre rezolvarea de probleme i spre scrierea direct a
programelor de soluionare a acestora. Concentrndu-ne asupra problemelor ce le soluionm nici nu
vom observa cnd i n ce fel am nvat s scriem programe. La urma urmei, programarea este doar un
instrument, doar o unealt de scris, i nu un scop n sine. Dac vrei iute s nvei s scrii, conteaz
cum sau n ce mn ii stiloul ?
Nu trebuie deloc neglijat i un al doilea "factor secret". Aa cum meseria nu se nva, ci se
fur, tot astfel programarea se poate nva mult mai uor apelnd la ajutorul unui profesor sau a unui
specialist. Acesta, prin experiena i cunotinele sale de specialitate ne poate ajuta s pim alturi de
el pe crri bttorite i ntr-un ritm susinut.
n concluzie, ntr-o descriere plastic i metaforic, metoda secret cea mai rapid de
ascensiune n programare este metoda privirii concentrate spre vrf, cu ghidul alturi i pe crri
bttorite.

19
Noiuni primare de programare n Pascal i C

n spiritul celor spuse mai sus, vom introduce acum "ntr-un ritm alert", prin exemple
concrete, noiunile elementare de programare n limbajele Pascal i C (n paralel). Vom pleca de la
prezentarea structurii generale a unui program iar apoi vom trece la prezentarea celor patru structuri-
instruciuni elementare coninute n psedo-limbajul de descriere a algoritmilor. Vom avea n plus grij
de a precede descrierea fiecrei structuri elementare de liniile de declarare a tipului variabilelor
implicate. Peste tot vor apare linii de comentariu (ignorate de compilator). n limbajul Pascal
comentariile snt cuprinse ntre acolade {comentariu}, pe cnd n C ele snt cuprinde ntre construcia
de tipul /* comentariu*/ sau apar la sfritul liniei precedate de dou slash-uri //comentariu.

Structura unui program


Program Nume_de_Program; {aceast linie poate s // linii de incluziuni de fiiere header
lipseasc}
{ Zona de declaraii constante, variabile, proceduri // declaraii de variabile i funcii externe (globale)
i funcii }
BEGIN void main(void){
{ Corpul programului format din instruciuni // declaraii de variabile locale
terminate cu punct-vigul ; Corpul programului
poate fi privit ca o instruciune compus } // corpul programului format din instruciuni
END. terminate cu punct-vigul ;
(Orice se va scrie dup punct va fi ignorat de ctre }
compilator)

Exemplu : Exemplu :
Program Un_Simplu_Test; #include <stdio.h>
Const e=2.68;
Var x:real; int e=2.68;
BEGIN float x;
x:=1./2+e*(1+e); void main(void){
Writeln(Rezultatul este:,x); x=1./2+e*(1+e);
END. printf(Rezultatul este %f:,x);
}
Atribuirea : var:=expresie;
#include <math.h> // declar constanta M_PI
Var i,j:integer;perimetrul:real; int i,j; float perimetrul;
.. ..
j:=2000 div 15; { mprire ntreag obligatorie } j=2000 / 15; // mprire ntreag implicit !!
i:=i+(j-1)*Sqr(2*j+1); { Sqr (Square) funcia de i+=(j-1)* (2*j+1)*(2*j+1); // n C avem operatorul
ridicare la ptrat } // de adunare + nainte de egal = ; funcia putere n
perimetrul:=2*PI*i; { PI constant real // C este pow(x,y)
implicit } perimetrul=2*M_PI*i;
Intrare/Ieire :
Citete var1, var2, var3, ;
Scrie var1, var2, var3, ;
Sau
Scrie expresia1, expresia2, expresia3,;
#include <math.h> // declar constanta M_PI
Var i,j:integer;perimetrul:real; int i,j; float perimetrul;
.. ..
Readln(i,j); { citirea variabilelor i i j } scanf(%i %i,&i,&j); // %i %i este descriptorul
Perimetrul:=2*PI*i; de format de citire, & este operatorul de adresare
Writeln(Raza=,i:4, Perimetrul=,perimetrul:6:2, perimetrul=2*M_PI *i;
Aria=, PI*Sqr(i):6:2); printf(Raza=%4i Perimetrul= %6.2f Aria=
{ perimetrul si aria fiind valori reale, se afiseaza cu %6.2f,i,perimetrul,M_PI*i*i); // %6.2f
descriptorul de format de afisare :6:2 pe 6 poziii descriptorul de format de afisare a unei valori
de ecran cu rotunjit la 2 zecimale } reale(flotante) pe 6 poziii rotunjit la 2 zecimale

20
Condiionala :
Dac <condiie_logic> atunci instruciune1 [altfel instruciune2];
Var i,j,suma:integer; int i,j,suma;
.. ..
If i <= 2*j+1 then suma:=suma+i if (i<=2*j+1) suma+=i
else suma:=suma+j; else suma+=j;
Ciclul de tipul Repeat-Until:
Repet instruciune1, instruciune2, pn cnd <condiie_logic>;
Var i,j,suma:integer; int i,j,suma;
.. ..
suma:=0;i:=1; suma=0;i=1;
Repeat do
suma:=suma+i; i:=i+1; suma+=i;
Until i>100; while (i++<100);
Ciclul de tipul Do-While:
Ct timp <condiie_logic> execut instruciune;
Var i,j,suma:integer; int i,j,suma;
.. ..
suma:=0;i:=1; suma=0;i=1;
While i<=100 do begin while (i++<100)
suma:=suma+i; i:=i+1; suma+=i;
End;
Ciclul de tipul For (cu contor):
Pentru var_contor:=val_iniial pn la val_final execut instruciune;
Var i,j,suma:integer; int i,j, suma;
.. ..
suma:=0; for(suma=0,i=1;i<=100;i++)
For i:=1 to 100 do suma+=i;
Suma:=suma+i;

Exemple de probleme rezolvate

Prezentm n continuare, spre iniiere, cteva exemple de probleme rezolvate. Vom oferi
programul rezultat att n limbajul de programare Pascal ct i n limbajul C. Deasemenea, fiecare
program va fi precedat de o scurt descriere a modului de elaborare a soluiei.

1. Se citesc a,b,c coeficienii reali a unei ecuaii de gradul II. S se afieze soluile ecuaiei.

Descrierea algoritmului:
- ecuaia de gradul II este de forma ax2+bx+c=0
-presupunnd c a 0 calculm determinantul ecuatiei delta=b*b-4*a*c
- dac delta >= 0 atunci ecuaia are soluiile reale x1,2=(-bdelta)/(2*a)
- dac delta < 0 atunci ecuaia are soluiile complexe z1=(-b/(2*a), (-delta)/(2*a)), z1=(-b/(2*a), -(-
delta)/(2*a))

Program Ecuatie_grad_2; { varianta Pascal }


Var a,b,c,delta:real;

BEGIN
Write('Introd. a,b,c:');Readln(a,b,c);
delta:=b*b-4*a*c;
If delta>=0 then
Begin
Writeln('x1=',(-b-sqrt(delta))/(2*a):6:2);
Writeln('x2=',(-b+sqrt(delta))/(2*a):6:2);

21
End
else Begin
Writeln('z1=(',-b/(2*a):6:2, , , -sqrt(-delta))/(2*a):6:2, ));
Writeln('z2=(', -b/(2*a):6:2, , , sqrt(-delta))/(2*a):6:2, ));
End
Readln;
END.

// versiunea C

#include <stdio.h>
#include <math.h>

float a,b,c; // coeficientii ecuatiei de gradul II


float delta;

void main(){
printf("Introd.coefic.ecuatiei a b c:");scanf("%f %f %f",&a,&b,&c);
delta=b*b-4*a*c;
if (delta>=0) {
printf("Sol.reale: x1=%6.2f, x2=%6.2f",(-b+sqrt(delta))/2./a,(-b-sqrt(delta))/2./a);
} else {
printf("Sol.complexe: x1=(%6.2f,%6.2f), x2=(%6.2f,%6.2f)",-b/2./a,sqrt(-delta)/2./a,-b/2/a,-sqrt(-
delta)/2./a);
}
}

2. S se determine dac trei numere a,b,c reale pot reprezenta laturile unui triunghi. Dac da, s
se caculeze perimetrul i aria sa.

Descrierea algoritmului:
- condiia necesar pentru ca trei numere s poat fi lungimile laturilor unui triunghi este ca cele trei
numere s fie pozitive (condiie implicit) i suma a oricror dou dintre ele s fie mai mare dect cel
de-al treilea numr
- dup condiia este ndeplinit vom calcula perimetrul i aria triunghiului folosind formula lui Heron
s=sqrt(p(p-a)(p-b)(p-c)) unde p=(a+b+c)/2.

Program Laturile_Unui_Triunghi; { Pascal }


Var a,b,c,s,p:real;

function laturi_ok:boolean;
begin
laturi_ok:= (a>0) and (b>0) and (c>0) and (a+b>c) and (a+c>b) and (b+c>a) ;
end;

BEGIN
write('introduceti laturile');readln(a,b,c);
IF laturi_ok then
begin
p:=(a+b+c)/2;
s:=sqrt(p*(p-a)*(p-b)*(p-c));
writeln('Aria=',s:5:2);
writeln(Perimetrul=,2*p:5:2);
end
else writeln('Nu formeaza triunghi');
readln;
END.

// versiunea C

22
#include <stdio.h>
#include <math.h>

float a,b,c,s,p;

int validare_laturi(float a,float b,float c){


return( (a>0)&&(b>0)&&(c>0)&&(a+b>c)&&(b+c>a)&&(a+c>b));
}

void main(void){
printf(Introd.laturile a b c:);scanf(%f %f %f,&a,&b,&c);
if (validare_laturi(a,b,c)){
p=(a+b+c)/2;s=sqrt(p*(p-a)*(p-b)*(p-c));
printf(Aria=%6.2f, Perimetrul=%6.2f,s,2*p);
}
}

3. Se citete n ntreg. S se determine suma primelor n numere naturale.

Descrierea algoritmului:
- vom oferi varianta n care suma primelor n numere naturale va fi calculata cu una dintre instructiunile
repetitive cunoscute(for,while ,repeat) fr a apela la formula matematic cunoscut S(n)=n*(n+1)/2

Program Suma_n; { Pascal }


Var n,s,i:word;

BEGIN
Writeln(Introduceti limita n=);Readln(n);
s:=0;
For i:=1 to n do s:=s+i;
Writeln(s=,s);
Readln;
END.

// versiunea C

#include <stdio.h>

int n,s;

void main(void){
printf(Introd. n:); scanf(%i,&n);
for(;n>0;n--)s+=n;
printf(S(n)=%i,s);
}

4. Se citete valoarea ntreag p. S se determine daca p este numr prim.

Descrierea algoritmului:
- un numr p este prim dac nu are nici un divizor nafar de 1 i p cu ajutorul unei variabile contor d
vom parcurge toate valorile intervalului [2.. p]; acest interval este suficient pentru depistarea unui
divizor, cci: d1 | p p = d1*d2 (unde d1 < d2) d1 d1*d2 = p iar d2 d1*d2 = p

Program Nr_prim; { Pascal }


Var p,i:word;
prim:boolean;

BEGIN
write('p=');readln(p);
prim:=true;

23
for i:=2 to trunc(sqrt(p)) do
if n mod i=0 then prim:=false;
prim:=true;
if prim then
write(p,' este nr prim')
else
write(p,' nu e nr prim');
END.

// versiunea C (optimizat !)

#include <stdio.h>
#include <math.h>

int p,i,prim;

void main(void){
printf(Introd. p:); scanf(%i,&p);
for(i=3, prim=p % 2; (i<=sqrt(p))&&(prim); i+=2)
prim=p % i;
printf(%i %s nr.prim, p, (prim ? este: nu este));
}

5. Se citete o propoziie (ir de caractere) terminat cu punct. S se determine cte vocale i cte
consoane conine propoziia.

Program Vocale;
Var sir:string[80];
Vocale,Consoane,i:integer;

BEGIN
Write(Introd.propozitia terminata cu punct:);Realn(sir);
i:=1;Vocale:=0;Consoane:=0;
While sir[i]<>. do begin
If Upcase(sir[i]) in [A,E,I,O,U] then Inc(Vocale)
else If Upcase(sir[i]) in [A..Z] then Inc(Consoane);
Inc(i);
end;
Writeln(Vocale:,Vocale, Consoane:, Consoane, Alte caractere:,i-Vocale-Consoane);
END.

// versiunea C

#include <stdio.h>
#include <ctype.h>

int i,vocale=0,consoane=0;
char c,sir[80];

void main(void){
printf("Introd.propozitia terminata cu punct:");gets(sir);
for(i=0;sir[i]!='.';i++)
switch (toupper(sir[i])){
case 'A':
case 'E':
case 'I':
case 'O':
case 'U': vocale++; break;
default: if (isalpha(sir[i])) consoane++;
}

24
printf("Vocale:%i, Consoane:%i, Alte car.:%i", vocale, consoane, i-vocale-consoane);
}

25
Metoda practic de nvare ce garanteaz rezultate imediate

Dac cele spuse mai sus cu privire la secretul nvrii rapide a programrii, acum nu ne mai
rmne dect s ncepem s aplicm practic ideile prezentate. Pentru aceasta, avem la dispoziie
urmtoarea metod care garanteaz cu siguran rezultate. Iat-o, pe pai:

1. se citete i se nelege ct mai bine exemplul de problem rezolvat (se poate ncepe chiar cu
primul exemplu de mai sus)
2. se acoper (se ascunde) soluia i se ncearc reproducerea ei din memorie (reinventarea soluiei)
pe calculator
3. numai n cazuri excepionale se poate apela (se poate trage cu ochiul) la soluie

Oricare dintre noi poate recunoate aici metoda pe care o aplic copiii din primele clase primare:
metoda trasului cu ochiul la rezultatul aflat la spatele manualului sau al culegerii de probleme. Din
moment ce metoda este verificat i garantat (am folosit-o i noi cndva), de ce ne-ar fi ruine s-o
aplicm acum din nou ?
Iat n continuare o list de probleme de "antrenament" care au majoritea rezolvarea ntr-unul
din capitolele urmtoare. Este numai bine pentru a ncepe s aplicm metoda oferit chiar acum !

Probleme selecionate - Enunuri

Probleme propuse spre rezolvare (probleme de antrenament)

1. Se citesc a, b, c trei variabile reale.


S se afieze maximul i minimul celor trei numere.
S se afieze cele trei numere n ordine cresctoare.
S se determine dac cele trei numere pot reprezenta laturile unui triunghi. Dac da, s se
determine dac triunghiul respectiv este isoscel, echilateral sau oarecare.
S se determine dac cele trei numere pot reprezenta laturile unui triunghi. Dac da, s se
determine mrimile unghiurilor sale i dac este ascuit-unghic sau obtuz-unghic.
S se afieze media aritmetic, geometric i hiperbolic a celor trei valori.

2. Se citete n o valoare ntreag pozitiv.


S se determine dac n este divizibil cu 3 dar nu este divizibil cu 11.
S se determine dac n este ptrat sau cub perfect.
S se afieze primele n ptrate perfecte.
S se determine numrul cuburilor perfecte mai mici dect n.
S se gseasc primul numr prim mai mare dect n.
S se afieze primele n numere prime: 2, 3, 5, 7,, p n.
S se determine toate numerele de 4 cifre divizibile cu n.
S se determine suma cifrelor lui n.
S se afieze rsturnatul lui n. (Ex: n=1993 => n_rsturnat =3991).
S se afieze urmtorul triunghi de numere:
1
12
123
..
123n

3. Se citesc m, n dou variabile ntregi pozitive.


S se determine toate ptratele perfecte cuprinse ntre m i n, inclusiv.
S se determine toate numerele prime cuprinse ntre m i n.
S se determine toate numerele de 4 cifre care se divid att cu n ct i cu m.
S se determine c.m.m.d.c. al celor dou numere folosind algoritmul lui Euclid.

26
4. S se calculeze u20 , u30 , u50 ai irului cu formula recursiv un=1/12un-1+1/2un-2 pentru n>=2 i
u0=1, u1=1/2.

5. Se citete n gradul unui polinom i irul an, an-1, , a1, a0 coeficienilor unui polinom P.
Se citete x, s se determine P(x).
Se citesc x i y, s se determine dac polinomul P schimb de semn de la x la y.
Se citete a, s se determine restul mpririi lui P la x-a.

6. Se citesc m, n gradele a dou polinoame P i Q, i coeficienii acestora. S se determine polinomul


produs R=PxQ.

7. Se citete o propoziie (ir de caractere) terminat cu punct.


S se determine cte vocale i cte consoane conine propoziia.
S se afieze propoziia n ordine invers i cu literele inversate (mari cu mici).
S se afieze fiecare cuvnt din propoziie pe cte o linie separat.
S se afieze propoziia rezultat prin inserarea n spatele fiecrei vocale v a irului pv
(vorbirea gineasc).

8. Se citete m, n dimensiunea unei matrici A=(ai,j)mxn de valori reale.


Se citesc l, c. S se afieze matricea obinut prin eliminarea liniei l i a coloanei c.
Se citete n ntreg pozitiv, s se afieze matricea obinut prin permutarea circular a liniilor
matricii cu n poziii.
S se determine suma elementelor pe fiecare linie i coloan.
S se determine numrul elementelor pozitive i negative din matrice.
S se determine linia i coloana n care se afl valoarea maxim din matrice.
S se determine linia care are suma elementelor maxim.

9. Se citesc m, n, p i apoi se citesc dou matrici A=(ai,j)mxn i B=(bj,k)nxp.S se determine matricea


produs C=AxB.

10. Se citete un fiier ce conine mai multe linii de text.


S se afieze linia care are lungime minim.
S se afieze liniile care conin un anumit cuvnt citit n prealabil.
S se creeze un fiier care are acelai coninut dar n ordine invers.

27
Probleme de examen

1. Se citete x o valoarea real. S se determine radical(x) cu 5 zecimale exacte pe baza irului


convergent xn=1/2 (xn-1+x / xn-1) cu x0>0 arbitrar ales.
2. Se citete x o valoarea real i k un numr natural. S se determine radical de ordinul k din x cu 5
zecimale exacte pe baza irului convergent xn=1/k ( (k-1) xn-1+x / xn-1k-1) cu x0>0 arbitrar ales.
3. S se determine c.m.m.m.c. a dou numere m, n citite.
4. Se citete n, s se determine toate perechile (x, y) care au cmmmc(x,y)=n.
5. Se citesc a, b, c ntregi pozitive, s se determine toate perechile ntregi (x, y) care conduc la
egalitatea c=ax+by.
6. Se citete n o valoare ntreag pozitiv. S se determine toate descompunerile n diferen de
ptrate a lui n.
7. S se determine toate tripletele (i, j, k) de numere naturale ce verific relaia i2+j2+k2=n unde n se
citete.
8. Se citete n, s se afieze toate numerele pitagoreice mai mici sau egale cu n.
9. Se citete n, s se determine toate numerele perfecte mai mici dect n. (Un numr este perfect dac
este egal cu suma divizorilor si, ex. 6=1+2+3.)
10. Se citete n, s se afieze toate numerele de n cifre, formate numai cu cifrele 1 i 2 i care se divid
cu 2n.
11. Se citete n, s se afieze toate numerele de n cifre care adunate cu rsturnatul lor dau un ptrat
perfect.
12. Se citete n ntreg pozitiv, s se afieze n transcris n baza 2.
13. Se citete n ntreg pozitiv scris n baza 2, s se afieze n transcris n baza 10.
14. Se citete n ntreg pozitiv, s se afieze n n transcripia roman. (Ex: 1993=MCMXCIII , unde
M=1000, D=500, C=100, L=50, X=10, V=5, I=1.)
15. Se citete n, s se afieze descompunerea acestuia n factori primi.
16. Se citesc m, n numrtorul i numitorul unei fracii. S se simplifice aceast fracie.
17. Se citete n, s se afieze toate posibilitile de scriere a lui n ca sum de numere consecutive.
18. Se citete n i k, s se afieze n ca sum de k numere distincte.
19. Se citete n, s se determine o alegere a semnelor + i astfel nct s avem relaia 12(n+1)
n=0, dac ea este posibil.
20. Se citete n i irul de valori reale x1, x2, , x n-1, xn ordonat cresctor. S se determine distana
maxim ntre dou elemente consecutive din ir.
21. Se citete n gradul unui polinom i irul xn, xn-1, , x1 soluiilor reale a unui polinom P. S se
determine irul an, an-1, , a1, a0 coeficienilor polinomului P.
22. Se citesc dou iruri de valori reale x1, x2, , x n-1, xn i y1, y2, , y m-1, ym ordonate cresctor. S
se afieze irul z1, z2, , z n+m-1, zn+m rezultat prin interclasarea celor dou iruri.
23. Un ir de fracii ireductibile din intervalul [0,1] cu numitorul mai mic sau egal cu n se numete ir
Farey de ordinul n. De exemplu, irul Farey de ordinul 5 (ordonat cresctor) este: 0/1, 1/5, , 1/3,
2/5, , 3/5, 2/3, , 4/5, 1/1. S se determine irul Farey de ordinul n, cu n citit.
24. Se citete n i S o permutare a mulimii {1, 2, , n}. S se determine numrul de inversiuni i
signatura permutrii S.
25. Se citete n i S o permutare a mulimii {1, 2, , n}. S se determine cel mai mic numr k pentru
care Sk={1, 2, , n}.
26. Fie M={1, 3, 4, } mulimea numerelor obinute pe baza regulii R1, i a regulii R2 aplicate de un
numr finit de ori: R1) 1M R2) Dac xM atunci y=2x+1 i z=3x+1 aparin lui M. Se citete n,
s se determine dac n aparine mulimii M fr a genera toate elementele acesteia mai mici dect
n.
27. Se citete n, k i o matrice A=(ai,j) nxn ptratic. S se determine Ak.
28. Se citete n i o matrice A=(ai,j) nxn ptratic. S se determine d determinantul matricii A.
29. Se citete n i cele n perechi (xi, yi) de coordonate a n puncte Pi n plan. S se determine care dintre
cele n puncte poate fi centrul unui cerc acoperitor de raz minim.
30. S se determine, cu 5 zecimale exacte, rdcina ecuaiei x3+x+1=0 care exist i este unic n
intervalul [-1,1].
31. Se citete n i irul de valori reale x1, x2, , x n-1, xn. S se determine poziia de nceput i
lungimea celui mai mare subir de numere pozitive.
32. Se citete n, s se afieze binomul lui Newton: (x+y)n.

28
33. Se citete n, s se afieze binomul lui Newton generalizat: (x1+x2++xp)n=n!/(n1!n2!np!)
x1n1x2n2xpnp pentru n1+n2++np=n i ni>0, i=1,p.
34. Se citete n, s se determine descompunerea lui n ca sum de numere Fibonacci distincte. (F n=Fn-
1+Fn-2 pentru n>1 i F1=1, F0=0).
35. Avem la dispoziie urmtoarele trei operaii care se pot efectua asupra unui numr n: O1) i se
adaug la sfrit cifra 4; O2) i se adaug la sfrit cifra 0; O3) dac n este par se mparte la 2. S se
afieze irul operaiilor care se aplic succesiv, pornind de la 4, pentru a obine un n care se citete.
36. Fie funcia lui Ackermann definit astfel: A(i,n)=n+1 pentru i=0; A(i,n)=A(i-1,1) pentru i>0 i
n=0; A(i,n)=A(i-1,A(i,n-1)) pentru i>0 i n>0. Care este cea mai mare valoare k pentru care se
poate calcula A(k,k) ?
37. S se determine suma tuturor numerelor formate numai din cifre impare distincte.
38. Scriei o funcie recursiv pentru a determina c.m.m.d.c. a dou numere m i n.
39. Scriei o funcie recursiv pentru a calcula an pe baza relaiei an=(ak)2 pentru n=2k, i an=a(ak)2
pentru n=2k+1.
40. Scriei o funcie recursiv pentru a determina prezena unui numr x ntr-un ir de valori reale x1,
x2, , x n-1, xn ordonate cresctor folosind algoritmul cutrii binare.
41. Scriei o funcie recursiv pentru a determina o aezare a 8 turnuri pe o tabl de ah astfel nct s
nu se atace ntre ele. (Tabla de ah va fi reprezentat printr-o matrice ptratic de 8x8).
42. S se determine peste ci ani data de azi va cdea n aceeai zi a sptmnii.
43. Avem la dispoziie un fiier ce conine numele, prenumele i media tuturor studenilor din grup.
S se afieze studentul cu cea mai mare medie.
S se afieze toi studenii bursieri.
S se afieze studentul care are media cea mai apropiat de media aritmetic a mediilor pe
grup.
S se afieze toi studenii din prima jumtate a alfabetului.
S se afieze toi studenii n ordine invers dect cea din fiier.
S se creeze un fiier catalog care s conin aceleai informaii n ordinea alfabetic a
numelui.
44. Avem la dispoziie dou fiiere ce conin numele, prenumele i media tuturor studenilor din cele
dou grupe ale anului n ordinea descresctoare a mediilor.
S se afieze toi studenii din ambele grupe care au media mai mare dect media anului.
S se creeze prin interclasare un fiier totalizator care conine toi studenii anului n ordinea
descresctoare a mediilor.

29
Probleme dificile

Dup cum se poate bnui, informatica conine i ea, la fel ca matematica, o mulime de
probleme foarte dificile care i ateapt nc rezolvarea. Asemnarea cu matematica ne intereseaz mai
ales n privina unui aspect "capcan" asupra cruia dorim s atragem atenia aici.
Enunurile problemelor dificile sau foarte dificile de informatic este, n 99% din cazuri, foarte
simplu i poate fi citit i neles de orice student. Acest fapt consituie o capcan sigur pentru cei
ignorani. Dac n matematic lucrurile nu stau aa, asta se datoreaz numai faptului c studiul
matematicii are vechime i problemele, mpreun cu dificultile lor, snt ceva mai bine cunoscute. n
informatic nu avem ns aceeai situaie. Ba chiar se ntmpl c probleme foarte dificile snt
amestecate n culegerile de probleme de informatic printre probleme uoare, mai ales datorit lipsei de
cultur de specialitate a autorilor.
Acest capitol i propune s pun n gard n privina dificultii problemelor oferind o mic
iniiere n acest domeniu (mai multe se pot afla studiind Complexitatea algoritmilor i dificultatea
problemelor). Deasemeni el i propune s umple lacuna ce mai exist nc la ora actual n cultura de
specialitate.
Dificultatea problemelor de programare a cror enunuri urmeaz este considerat maxim de
teoreticienii informaticii (ele se numesc probleme NP-complete). Nu v lsai pclii de faptul c le-ai
ntlnit n unele culegeri de programare. Ele snt depite n dificultate doar de problemele insolvabile
algoritmic ! Dar n ce const dificultatea lor ?
Spre deosebire de matematic, dificultatea problemelor de informatic nu este dat de faptul
c nu se cunoate un algoritm de rezolvare a lor, ci datorit faptului c nu se cunoate un algoritm
eficient (!) de rezolvare a lor. Existena unei metode de proiectare a algoritmilor att de general valabil,
cum este metoda back-tracking, face ca prea puine probleme cu care ne putem ntlni s nu aib o
soluie. Dar, ntruct n cazul metodei back-tracking, cutarea soluiei se face ntr-un mod exhaustiv (se
caut "peste tot", pentru ca s fim siguri c nu lsm nici o posibilitate neexplorat), durata cutrii are
o cretere exponenial-proporional cu dimesiunea datelor de intrare. De exemplu, timpul de cutare
care depinde de valoarea de intrare n poate avea o expresie de forma T(n)=c2n secunde, unde c este un
factor de proporionalitate ce poate varia, s zicem, de la c=12.5 cnd algoritmul este executat pe un
calculator sau c=62.8 cnd el este rulat pe un calculator de cinci ori mai performant. Dar, indiferent de
calculator, pentru n=100 avem 2100=(210)10(103)10=1030, deci timpul msurat n secunde are ordinul de
mrime mai mare de 30. Cea mai larg estimare pentru vrsta Universului nostru nu depete 20 mild.
ani ceea ce transformat n secunde conduce la un ordin de mrime mai mic de 20. Deci, chiar i pentru
valori mici ale lui n (de ordinul sutelor) am avea de ateptat pentru gsirea soluiei de 10 miliarde de ori
mai mult dect a trecut de la Big Bang ncoace ! Pot fi n aceast situaie considerate astfel de programe
ca rezolvri rezonabile, doar pentru c ele gsesc soluia n cazurile n care n=2, 3, 4, , 10 ?
Exemplele urmtoare snt doar cteva, uor de ntlnit "din greeal", dintr-o list cunoscut ce
conine la ora actual peste ase sute de astfel de probleme. Pentru fiecare din aceste probleme nu li se
cunosc alte soluii dect inutilii algoritmi de gen back-tracking. n list apare des noiunea de graf, aa
c o vom introduce n continuare ct mai simplu cu putin: printr-un graf se nelege o mulime de
vrfuri i o mulime de muchii care unesc unele vrfuri ntre ele. Orice hart (schematizat) rutier,
feroviar sau de trafic aerian reprezint desenul unui graf.

1. Problema partiionrii sumei. Fie C un ntreg pozitiv i d1, d2, , dn o mulime de n valori ntregi
pozitive. Se cere s se gseasc o partiionare a mulimii d1, d2, , dn astfel nct suma elementelor
partiiei s fie exact C.
2. Problema rucsacului. Avem un rucsac de capacitate ntreag pozitiv C i n obiecte cu
dimensiunile d1, d2, , dn i avnd asociate profiturile p1, p2, , pn (n caz c ajung n rucsac). Se
cere s se determine profitul maxim ce se poate obine prin ncrcarea rucsacului (fr ai depi
capacitatea).
3. Problema colorrii grafului. S se determine numrul minim de culori (numrul cromatic)
necesar pentru colorarea unui graf astfel nct oricare dou vrfuri unite printr-o muchie (adiacente)
s aib culori diferite.
4. Problema mpachetrii. Presupunnd c dispunem de un numr suficient de mare de cutii fiecare
avnd capacitatea 1 i n obiecte cu dimensiunile d1, d2, , dn, cu 0<di<1, se cere s se determine
numrul optim (cel mai mic) de cutii necesar pentru mpachetarea tutror celor n obiecte.
5. Problema comisului voiajor. (varianta simplificat) Dndu-se un graf (o hart), se cere s se
gseasc un circuit (un ir de muchii nlnuite) care trece prin fiecare vrf o singur dat.

30
Majoritatea acestor probleme apar ca probleme centrale la care se reduc n ultim instan
problemele concrete ale unor domenii capitale ale economiei i industriei, cum snt de exemplu
planificarea investiiile, planificarea mprumuturilor i ealonarea plii dobnzilor, alocarea i
distribuirea resurselor primare (mai ales financiare), etc. Pentru nici una din aceste probleme strategice
nu se cunoate un algoritm optim de rezolvare, ci doar soluii aproximative. Dac s-ar cunoate
algoritmii de soluionare optim atunci majoritatea sectoarelor i proceselor macro- i micro-economice
ar putea fi conduse n timp real i optim (!!) cu calculatorul, fr a mai fi necesar prezena uman.
Un exemplu cert de domeniu care s-a dezvoltat extraordinar i n care rolul soft-ului a fost
esenial este chiar domeniul construciei de calculatoare, mai ales domeniul proiectrii i asamblrii de
micro-procesoare. Dac ai vzut c schema electronic intern de funcionare a unui microprocesor din
familia Pentium, dac ar fi desenat clasic, ar ocupa o plan de dimensiuni 5x5 metri (!), nu mai avei
cum s v ndoii de faptul c numai un soft de proiectare i cablare performant mai poate controla i
stpni super-complexitatea rezultat. Puin lume tie ns c astfel de programe de proiectare
performante au putut s apar numai datorit faptului c problema ce st n spatele funcionrii lor,
problema desenrii grafurilor planare, nu se afl pe lista de mai sus a problemelor foarte dificile ale
informaticii !

31
Probleme nesoluionate nc

Aa cum s-a putut constata n capitolul anterior, exist multe probleme n informatic pentru
care nc nu se cunosc soluii eficiente. n continuare vom oferi o list de probleme nesoluionate nc.
De fapt, ele apar mai ales n matematic, fiind cunoscute sub numele de conjecturi, i au toate ca
specific un fapt care este de mare interes pentru programatori. Incertitudinea asupra lor ar putea fi
definitiv nlturat nu numai prin demonstraie matematic ci i cu ajutorul formidabilei puteri de
calcul a computerelor. Astfel, fiecare din aceste conjecturi numerice ar putea fi infirmat (concluzia ar
fi atunci c conjectura este fals) dac i s-ar gsi un contraexemplu. Este necesar doar s se gseasc
un set de numere pentru care propoziia respectiv s fie fals. Ori, acest efort nu este la ndemna
niciunui matematician dar este posibil pentru un programator nzestrat i pasionat. El nu are dect s
scrie un program eficient i s pun calculatorul s caute un contra-exemplu.
Atragem atenia asupra unui aspect important. Fiecare problem conine aceeai capcan ca i
n problemele capitolului anterior: algoritmii de cutare a contra-exemplelor pot fi concepui rapid,
relativ simpli i cu efort de programare redus (de exemplu, prin trei-patru cicluri for imbricate sau
printr-o soluie gen back-tracking) dar ei vor deveni n scurt timp total ineficieni i vor conduce la
programe mari consumatoare de timp. De aceea, v sugerm s tratai cu mult atenie problemele din
acest capitol. Dup prerea noastr, abordarea acestui tip de probleme cere din partea programatorului
un anumit grad de miestrie !
Rezolvnd numai una dintre ele vei fi recompensai pe msur: riscai s devenii celebri !

1. Conjectura lui Catalan. Singurele puteri naturale succesive snt 8=23 i 9=32.

Observaie: ntr-o exprimare matematic riguroas, singura soluie n numere naturale m, n, p, q a


ecuaiei nm+1=pq este n=2, m=3, p=3 i q=2.
Comentariu: avem irul numerelor naturale 1, 2, 3, 4, 5,; ncercuind toate puterile de gradul 2: 1, 4, 9,
16, 25, apoi toate cele de gradul 3: 1, 8, 27, 64, 125, apoi cele de grad 4, 5, vom constata c
singurele dou numere ncercuite alturate snt 8 i 9 ! Adic puterile obinute, cu ct snt mai mari, cu
att au tendina s se "mprtie" i s se "distaneze" unele de altele tot mai tare. n mod misterios, ele
nu-i suport vecintatea unele cu altele !

2. Conjectura cutiei raionale. Nu se cunoate existena unei cutii paralelipipedice avnd lungimile
celor trei laturi, ale celor trei diagonale ale feelor i a diagonalei principale ntregi.

Observaie: ntr-o exprimare matematic riguroas, nu se cunoate s existe trei ntregi a, b, c astfel nct
a2+b2, b2+c2 , c2+a2 i a2+b2+c2 s fie toate patru ptrate perfecte.
Comentariu: n multe subdomenii ale construciilor ,de exemplu s ne gndim la stlpii de nalt
tensiune ridicai pe vrfuri nalte de munte i asamblai n ntregime "la faa locului" numai din bare
mbinate cu uruburi (fr sudur), este de mare interes ca dintr-un numr ct mai mic de subansamble
simple (un fel de "crmizi") s se asambleze obiecte mari cu ct mai multe configuraii. Evident,
dimensiunile obiectelor rezultate vor avea mrimea ca o combinaie ntreag ale dimensiunilor
subansamblelor iniiale. Dup cum rezult ns din conjectur, se pare c este imposibil s se
construiasc scheletul ntrit (pe diagonale) al unei cutii paralelipipedice din bare de lungimi tipizate.
Cel puin una din diagonale necesit ajustarea lungimii unei bare !

3. Problema umplerii ptratului unitate. ntrebare: este posibil ca mulimea dreptunghiurilor de


forma 1/k x 1/(k+1), pentru fiecare k ntreg pozitiv, s umple n ntregime i fr suprapuneri
ptratul unitate, de latur 1x1 ?

Observaie: este evident c suma infinit a ariilor dreptunghiurilor este egal cu aria ptratului unitate.
Avem k>01/(k(k+1))=k>0(1/k-1/(k+1))=1.
Comentariu: aparent, descoperirea dezvoltrilor n serie pare s fi plecat de la unele evidente propieti
geometrice, uor de sesizat chiar din desene simple n care valorilor numerice li se asociaz segmente
de lungimi corespunztoare. Iat ns o surpriz n aceast situaie: suma seriei numerice este evident
analitic ns reprezentarea geometric a "fenomenului" este "imposibil" !

4. Conjectura fraciilor egiptene (atribuit lui Erds i Graham). Orice fracie de forma 4/n se
descompune ca sum de trei fracii egiptene (de forma 1/x).

32
Observaie: ntr-o exprimare matematic riguroas, pentru orice n natural exist trei valori naturale, nu
neaprat distincte, x, y, i z astfel nct 4/n=1/x+1/y+1/z.
Comentariu: este nc un mister motivul pentru care egiptenii preferau descompunerea faciilor numai
ca sum de fracii egiptene. Descoperiser ei aceast descompunere minimal a fraciilor de forma 4/n ?
Dar mai ales, ce procese fizice reale erau astfel mai bine modelate ? nclinm s credem c exist o
legtur ntre fenomenele fizice ondulatorii, transformata Fourier i fraciile egiptene !

5. Problema punctului raional. Exist un punct n plan care s se afle la o distan raional de
fiecare din cele patru vrfuri ale ptratului unitate ?

Observaie: dac considerm un ptrat unitate avnd vrfurile de coordonate (0,0), (1,0), (0,1) i (1,1)
atunci se cere gsirea unui punct (x,y) astfel nct x2+y2, (x-1)2+y2, x2+(y-1)2 i (x-1)2+(y-1)2 s fie toate
patru ptrate perfecte. Atenie, x i y nu este obligatoriu s fie ntregi ! Acest fapt ridic foarte serioase
probleme la proiectarea unui algoritm de cutare a unui astfel de punct (x,y).
Comentariu: la fel ca i n cazul cutiei raionale, se pare c exist limitri serioase i neateptate n
ncercarea de optimizare a numrului de subansamble necesare pentru construierea scheletelor sau
cadrelor de susinere. Se pare c cele dou dimensiuni pe care geometria plan se bazeaz conduce la o
complexitate inerent neateptat de mare !

6. Problema sumei de puteri. Care este suma seriei de inverse de puteri


1/1+1/23+1/33+1/43+1/53+ ?

Observaie: se cere s se spun ctre ce valoare converge seria k>01/k3 sau k>0k-3. Se tie c n cazul n
care n locul puterii a 3-ia (cu minus) punem puterea a 2-a (cu minus) seria converge la 2/6, n cazul
n care n locul puterii a 3-ia punem puterea a 4-a seria converge la 4/90.
Comentariu: dei pare a fi o problem de analiz matematic pur deoarece ni se cere s gsim expresia
sintetic i nu cea numeric aproximativ a sumei seriei, exist ns uluitoare descoperiri asemntoare
ale unor formule de analiz numeric sau chiar dezvoltri n serie (cea mai celebr fiind cea a lui
cifrelor hexazecimale ale lui ) fcute cu ajutorul calculatorului prin calcul simbolic ! Mai multe
amnunte gsii la adresa corespunztoare de Internet pe care am trecut-o n ultimul capitol.

7. Problema ecuaiei diofantice de gradul 5. Exist a, b, c, and d ntregi pozitivi astfel nct
a5+b5=c5+d5 ?

Observaie: Se cunoate c n cazul n care puterea este 3 avem soluia: 1 3+123=93+103 iar n cazul n
care puterea este 4 avem soluia: 1334+1344=594+1584 .
Comentariu: cutarea unor algoritmi generali de rezolvare a ecuaiilor diofantice a condus la importante
descoperiri n matematic dar i n informatic. De exemplu, celebrul matematician Pierre Fermat,
strnit fiind de problemele coninute n lucrarea Arithmetika a matematicianului antic Diofant din
Alexandria (de unde i numele ecuaiilor diofantice), a descoperit n 1637 faimoasa sa teorem:
Ecuaia diofantic xn+yn=zn nu admite soluie pentru n>2. Dar tot n aceeai perioad a descoperit i
faptul c cea mai mic soluie a ecuaiei diofantice x2 - 109*y2 = 1 este perechea x=158 070 671 986
249 i y= 15 140 424 455 100. Dumneavoastr ncercai doar s verificai aceast soluie fr ajutorul
calculatorului i v vei putea da seama de performanele pe care le-a realizat Fermat ! n informatic
este acum cunoscut i demonstrat c este imposibil s se construiasc un algoritm general pentru
rezolvarea ecuaiilor diofantice !

8. Problema celor 13 orae. Putei localiza 13 orae pe o planet sferic astfel nct distana minim
dintre oricare dou dintre ele s fie ct mai mare cu putin ?

Observaie: de fapt nu se cunoate ct de mult poate fi mrit distana


minimal ce se obine dintre cele 78 de distane (date de cele 78=C 213 de
mperecheri posibile de orae).
Comentariu: dac s-ar cere localizarea a doar 12 puncte pe sfer, nu este
greu de artat c aezarea care ndeplinete condiia cerut este n vrfurile
unui icosaedru (vezi figura alturat). n acest caz, distana minim
maximizat este egal cu latura icosaedrului. Este greu de crezut c n cazul
descoperirii aezrii a 13 puncte pe sfer se poate porni tocmai de la
icosaedru ! Evident c n rezolvarea aplicativ-practic a acestui tip de probleme nesoluionate
geometric pn n prezent rolul programatorului poate fi capital. La ora actual pentru astfel de situaii

33
se ofer soluii aproximative. Acestea constau din algoritmi care ncearc s aproximeze ct mai exact
soluia optim ntr-un timp rezonabil de scurt. Evident c n aceste condiii algoritmii de cutare
exhaustiv (gen back-tracking) snt cu totul exclui !

9. Conjectura lui Collatz. Se pleac de la un n ntreg pozitiv. Dac n este par se mparte la doi; dac
n este impar se nmulete cu trei i i se adun unu. Repetnd n mod corespunztor doar aceti doi
pai se va ajunge ntotdeauna la 1 indiferent de la ce valoare n se pornete ?

Observaie: de exemplu, pornind de la n=6 obinem n 8 pai irul valorilor: 6, 3, 10, 5, 16, 8, 4, 2, 1.
Comentariu: valoarea final 1 este ca o "gaur neagr" care absoarbe n final irul obinut. "Raza" de-a
lungul creia are loc "cderea" n gaura neagr 1 este dat mereu de irul puterilor lui 2: 2, 4, 8, 16, 32,
64, cu ultima valoare de forma 3k+1, adic 4, 16, 64, 256, . Se pare c valorile obinute prin cele
dou operaii nu pot "s nu dea" nicicum peste acest ir care le va face apoi s "cad n gaura neagr" 1!

10. Problema nscrierii ptratului. Dndu-se o curb simpl nchis n plan, vom putea ntotdeauna
gsi patru puncte pe curb care pot s constituie vrfurile unui ptrat ?

Observaie: n cazul curbelor nchise regulate (ce au axe de simetrie: cerc, elips, ovoid) nu este greu de
artat prin construire efectiv c exist un ptrat ce se "sprijin" pe curb. Pare ns de nedovedit
acelai fapt n cazul unor curbe nchise foarte neregulate ! Gsirea celor patru puncte, ntr-o astfel de
situaie, este de neimaginat fr ajutorul calculatorului !
Comentariu: o consecin surprinztoare a acestei conjecturi este faptul c pe orice curb de nivel
(curb din teren care unete punctele aflate toate la aceai altitudine) am putea gsi patru puncte de
sprijin pentru o platform ptrat (un fel de mas) perfect orizontal, de mrime corespunztoare. Acest
fapt ar putea s explice ampla rspndire a meselor cu patru picioare (!?) n detrimentul celor cu trei:
dac i caui poziia, cu siguran o vei gsi i o vei putea aeza pe toate cele patru picioare, astfel masa
cu patru picioare va oferi o perfect stabilitate i va sta perfect orizontal, pe cnd cea cu trei picioare
dei st acolo unde o pui din prima (chiar i nclinat) nu ofer aceeai stabilitate.

n sperana c am reuit s v strnim interesul pentru astfel de probleme nesoluionate nc i


care snt grupate pe Internet n liste cuprinznd zeci de astfel de exemple (vezi adresa oferit n ultimul
capitol), ncheiem acest capitol cu urmtoarea constatare: descoperirile deosebite din matematica
actual au efecte rapide i importante nu numai n matematic ci i n informatic. S oferim doar un
singur exemplu de mare interes actual: algoritmii de ncriptare/decriptare cu cheie public, att de
folosii n comunicaia pe Internet, se bazeaz n ntregime pe proprietile matematice ale divizibilitii
numerelor prime.
Ceea ce este interesant i chiar senzaional este faptul c n informatic nevoia de programe
performante a condus la implementarea unor algoritmi care se bazeaz pe cele mai noi descoperiri din
matematic, chiar dac acestea snt nc n stadiul de conjecturi! De exemplu, pentru acelai domeniu al
criptrii cu cheie public exist deja algoritmi de primalitate senzaional de performani care se bazeaz
pe Ipoteza (conjectura) lui Riemman. (Mai multe amnunte putei gsi la adresele de Internet pe care le
oferim n ultimul capitol.)
Este acest fapt legitim ? Ce ncredere putem avea n astfel de programe ? Dup prerea noastr
putem acorda o total ncredere acestor algoritmi dar numai n limitele "orizontului" atins de
programele de verificare a conjecturii folosite. Dac programul de verificare a verificat conjectura
numeric pe intervalul 1- 1030 atunci orizontul ei de valabilitate este 1030. Domeniile numerice pe care
le pot acoperi calculatoarele actuale snt oricum foarte mari i implicit ofer o precizie suficient pentru
cele mai multe calcule cu valori extrase din realitatea fizic.

34
Probleme insolvabile algoritmic

Am introdus acest capitol special din dou motive. Primul motiv, pentru a trezi interesul i
pasiunea pentru informatic celor care pot acum s vad ct de deosebite snt descoperirile i rezultatele
din acest domeniu. Al doilea motiv, pentru ai pune n gard pe cei care, n entuziasmul lor exagerat, i
nchipuie c pot programa calculatorul s fac orice treab sau s rezolve orice problem. Aa cum am
vzut i n capitolul ce trateaz despre problemele dificile ale informaticii, enunurile problemelor
foarte dificile sau chiar insolvabile snt foarte simple i pot uor constitui o capcan pentru
necunosctori.
n continuare vom oferi spre edificare doar cteva exemple, urmnd ca prin studiul
Complexitii algoritmilor i a dificultii problemelor s se aprofundeze acest domeniu fascinant dar
att de uor de confundat (poi s dai de aceste probleme chiar i din greeal !?) i care este pcat s fie
tratat ntr-un mod superficial.

1. Problema Stopului. Nu exist un algoritm universal valabil prin care s se poat decide dac
execuia oricrui algoritm se oprete vreodat sau nu.

Comentariu: acesta este cel dinti i cel mai celebru exemplu de problem insolvabil. Demonstraia
riguroas a acestui fapt a fost dat pentru prima dat n 1936 de inventatorul calculatorului actual
matematicianul englez Alan Mathison Turing. Odat existnd aceast demonstraie, multe din
urmtoarele probleme insolvabile algoritmic s-au redus la aceasta. Implicaiile practice, teoretice i
filozofice ale problemei Stopului snt foarte importante att pentru informatic ct i pentru matematic.
Astfel, dou consecine strategice ale problemei Stopului snt: 1. nu poate exista un calculator orict de
puternic cu ajutorul cruia s se poat decide asupra comportamentului viitor al oricrui alt calculator
de pe glob; 2. nu poate s existe n matematic o metod general de demonstrare inductiv-logic a
propoziiilor matematice (se nchide n acest fel o mai veche cutare a matematicienilor i logicienilor
cunoscut sub numele de Entscheidungs Problem sau Problema deciziei).

2. Problema ecuaiilor diofantice. Nu exist o metod general (un algoritm) de aflare a soluiilor
ntregi ale unui sistem de ecuaii diofantice.

Comentariu: sistemele de ecuaii diofantice snt sistemele de ecuaii algebrice de mai multe variabile cu
coeficieni ntregi i crora li se caut soluii ntregi. De exemplu, a fost nevoie de ajutorul
calculatorului pentru a se descoperi cea mai mic soluie a ecuaiei diofantice p4+q4+r4=s4 i care este
cvadrupletul p=95600, q=217519, r=414560, s=422461 (infirmndu-se n acest fel "conjectura" lui
Leonard Euler care n 1796 a presupus c aceast ecuaie diofantic nu are soluii ntregi). Aceast
problem ce cere o metod general de rezolvare a ecuaiilor diofantice este cunoscut sub denumirea
de Problema a 10-a a lui Hilbert.

3. Problema acoperirii planului (Problema pavajului sau Problema croirii). Fiind dat o mulime
de forme poligonale, nu exist o metod general (un algoritm) care s decid dac cu aceste
forme este posibil acoperirea complet a planului (fr suprapuneri i goluri).

Comentariu: n practic este mult mai important problema croirii care cere s se decupeze fr
pierderi un set ct mai mare de forme date (croiuri) dintr-o bucat iniial de material orict de mare.
Este deasemenea demonstrat c problema rmne insolvabil algoritmic chiar i atunci cnd formele
poligonale snt reduse la poliomine (un fel de "mozaicuri") care se formeaz doar pe o reea
rectangular caroiat. Iat cteva exemple de mulimi formate dintr-o singur poliomin i, alturat,
rspunsul la ntrebarea dac cu ele se poate acoperi planul sau nu:

DA NU DA

4. Problema irurilor lui Post. Se dau dou mulimi egale de iruri finite de simboluri ce snt
mperecheate astfel: un ir dintr-o mulime cu irul corespunztor din a doua mulime. Nu exist

35
un algoritm general prin care s se decid dac exist o ordine de concatenare a irurilor
(simultan din cele dou mulimi) astfel nct cele dou iruri lungi pereche rezultate s fie identice.

Comentariu: de exemplu, fie A={ 101, 010, 00 } i B={ 010, 10, 001 } cele dou mulimi de iruri de
simboluri (pentru uurin au fost alese simbolurile binare 1 i 0). Perechile corespunztoare de iruri
snt 1.(101,010), 2.(010,10) i 3.(00,001). Observm c irurile pereche pot avea lungimi diferite (ca n
perechile 2 i 3). n continuare, pentru a vedea cum se procedeaz, cele dou iruri pereche rezultante
prin concatenare le vom scrie unul deasupra celuilalt sesiznd cum avanseaz procesul de egalizare a
lor. Punctele snt intercalate doar pentru a evidenia perechile, ele nu contribuie la egalitate, iar
comentariile ne aparin:

00. Concatenarea poate ncepe doar cu 00.101. Obligatoriu urmeaz perechea 1-a
001. perechea a 3-a,00 de "sus" 001 de "jos" 001.010. singura care ncepe cu 1 "sus".
00.101.00. Dac am continua cu perechea 00.101.010 nu s-ar obine rezultatul final
001.010.001. a 3-a 001.010.10 oferit de perechea 2-a !

5. Problema cuvintelor "egale". Se d un anumit numr de "egaliti" ntre cuvinte. Bazndu-ne pe


aceste "egaliti" se pot obine unele noi substituind apariiile cuvintelor dintr-o parte a egalului cu
cele din cealalt parte. Nu exist un algoritm general de a decide dac un cuvnt oarecare A poate
fi "egal" cu un altul B.

Comentariu: de exemplu, fie urmtoarele cinci egaliti (citii-le n limba englez) EAT=AT, ATE=A,
LATER=LOW, PAN=PILLOW i CARP=ME. Este CATERPILLAR egal cu MAN ? Iat irul
egalitilor iterate care ne poate oferi rspunsul: CATERPILLAR = CARPILLAR =CARPILLATER
=CARPILLOW= CARPAN= MEAN= MEATEN= MATEN= MAN.
Dar de la CARPET putem ajunge la MEAT ? ntruct se vede c numrul total de A-uri plus W-uri i
M-uri nu se poate modifica prin nici o substituie i ntruct CARPET are un A (adic numrul asociat
este 1) iar MEAT are un A i un M (deci 2), rezult c aceast egalitate nu este permis.
Mai mult, se tie c exist liste particulare de cuvinte pentru care nu poate exista un algoritm ce decide
dac dou cuvinte snt egale sau nu. Iat o astfel de list de apte egaliti: AH=HA, OH=HO, AT=TA,
OT=TO, TAI=IT, HOI=IH i THAT=ITHT.

Numrul problemelor cunoscute ca fiind insolvabile algoritmic este destul de mare. Cele mai
multe probleme provin din matematic, subdomeniul matematicii care studiaz aceste probleme se
numete Matematica nerecursiv. De aceea ele pot fi ntlnite mai ales sub numele de probleme
nedecidabile sau probleme nerecursive, n enunul lor cuvntul algoritm fiind nlocuit mai ales cu
cuvintele metod general.
Studierea acestui domeniu a creat condiii pentru apariia de noi direcii de cercetare prin care
se ncearc explicarea raionamentelor matematice ba chiar se ncearc descoperirea limitelor raiunii
umane n general. Unii oameni de tiin contemporani, cum este celebrul matematician-fizician englez
Roger Penrose, depun eforturi mari pentru a oferi o demonstraie matematic riguroas pentru ipoteza
c, n cele din urm i n esen, raionamentele umane nu snt algoritmice, nici mcar cele matematice.
Dup prera lui Penrose mintea uman nu poate fi asimilat cu un calculator ci este mai mult dect att
i nu vor putea exista vreodat calculatoare sau roboi mai inteligeni dect oamenii! n ultimul capitol
oferim titlurile crilor recent aprute ce trateaz despre acest fascinant subiect .

36
Noiuni aprofundate de programare

Metode i strategii de proiectare a algoritmilor (alias tehnici de


programare)

n rezolvarea sa cu ajutorul calculatorului orice problem trece prin trei etape obligatorii:
Analiza problemei, Proiectarea algoritmului de soluionare i Implementarea algoritmului ntr-un
program pe calculator. n ultima etap, sub acelai nume, au fost incluse n plus dou subetape
cunoscute sub numele de Testarea i ntreinerea programului. Aceste subetape nu lipsesc din ciclul
de via a oricrui produs-program ce se respect dar , pentru simplificare, n continuare ne vom
referi doar la cele trei mari etape..
Dac etapa implementrii algoritmului ntr-un program executabil este o etap exclusiv
practic, realizat n faa calculatorului, celelalte dou etape au un caracter teoretic pronunat. n
consecin, primele dou etape snt caracterizate de un anumit grad de abstractizare. Din punct de
vedere practic i n ultim instan criteriul decisiv ce confer succesul rezolvrii problemei este dat de
calitatea implementrii propriuzise. Mai precis, succesul soluionrii este dat de performanele
programului: utilitate, vitez, fiabilitate, manevrabilitate, lizibilitate, etc. Este imatur i neprofesional
strategia programatorilor nceptori care neglijnd primele dou etape sar direct la a treia, fugind de
analiz i de componenta abstract a efortului de soluionare. Ei ofer cu toii aceeai justificare: Eu
nu vreau s mai pierd vremea cu , am s fac programul cum tiu eu. Pn cnd nu o s fac cineva
altul mai bun dect al meu, pn atuncinu am cu cine sta de vorb !.
Este adevrat c ultima etap n rezolvarea unei probleme implementarea este ntr-adevr
decisiv i doveditoare, dar primele dou etape au o importan capital. Ele snt singurele ce pot oferi
rspunsuri la urmtoarele ntrebri dificile: Avem certitudinea c soluia gsit este corect ? Avem
certitudinea c problema este complet rezolvat ? Ct de eficient este soluia gsit ? Ct de departe
este soluia aleas de o soluie optim ?
S menionm n plus c literatura de specialitate conine un numr impresionant de probleme
capcan pentru nceptori i nu numai. Ele snt toate inspirate din realitatea imediat dar pentru
fiecare dintre ele nu se cunosc soluii eficiente n toat literatura de profil. Exist printre ele chiar unele
probleme extrem de dificile pentru care s-a demonstrat riguros c nu admit soluie cu ajutorul
calculatorului. (Mai precis, s-a demonstrat c ele nu admit soluie prin metode algoritmice, n spiritul
tezei Turing-Church). Ci dintre programatorii nceptori n-ar fi surprini s afle c problema att de
simpl (ca enun) a crei soluionare tocmai au abandonat-o este de fapt o problem dovedit ca fiind
intratabil sau chiar insolvabil algoritmic ? Partea proast a lucrurilor este c, aa cum ciupercile
otrvite nu pot fi cu uurin deosebite de cele comestibile, tot astfel problemele netratabile pot fi cu
uurin confundate cu nite probleme uoare la o privire rapid i lipsit de experien.
S nelegem mai nti care este cheia ce conduce la rspunsuri pentru ntrebrile de mai sus
iar apoi vom trece la prezentarea metodelor clasice de proiectare a soluiilor. Aceste metode de
proiectare a algoritmilor-soluie snt cunoscute n literatura de specialitate sub numele de tehnici de
programare i snt considerate metode sau instrumente soft eficiente i cu arie larg de aciune.
Dac ar fi s sintetizm n cte un cuvnt efortul asupra cruia se concentreaz fiecare din
primele dou etape analiza i proiectarea acestea ar fi: corectitudine i eficien. Etapa de analiz
este singura care permite dovedirea cu argumente riguroase a corectitudinii soluiei, iar etapa de
proiectare este singura care poate oferi argumente precise n favoarea eficienei soluiei propuse.
n general problemele de informatic au n forma lor iniial sau n enun o caracteristic
pragmatic. Ele snt foarte ancorate n realitatea imediat i aceasta le confer o anumit asemnare.
Totui ele au n forma iniial un grad mare de eterogenitate, diversitate i lips de rigoare. Fiecare
dintre aceste atribute negative este un obstacol major pentru demonstrarea corectitudinii soluiei.
Rolul esenial al etapei de analiz este deci acela de a transfera problema de pe nisipurile mictoare
ale realitii imediate de unde ea provine ntr-un plan abstract, adic de a o modela. Acest univers
paralel este dotat cu mai mult rigoare i disciplin intern, avnd legi precise, i poate oferi
instrumentele logice i formale necesare pentru demonstrarea riguroas a corectitudinii soluiei
problemei.
Planul abstract n care snt transportate toate problemele este planul sau universul obiectelor
matematice. Acest univers al matematicii este unanim acceptat (de ce ?!) iar corespondentul problemei
n acest plan va fi modelul matematic abstract asociat problemei. Demonstrarea corectitudinii
proprietilor ce leag obiectele universului matematic a fost i este sarcina matematicienilor. Celui ce
analizeaz problema din punct de vedere informatic i revine sarcina (nu tocmai uoar) de a dovedi
printr-o demonstraie constructiv c exist o coresponden precis (bijectiv) ntre prile

37
componente ale problemei reale, dezasamblat n timpul analizei, i prile componente ale
modelului abstract asociat. Odat descoperit, formulat precis i dovedit, aceast perfect oglindire
a problemei reale n planul obiectelor matematice ofer certitudinea c toate proprietile i legturile
ce exist ntre subansamblele modelului abstract se vor regsii precis (prin reflectare) ntre prile
interne ale problemei reale, i invers. Atunci, soluiei abstracte descoperit cu ajutorul modelului
matematic abstract i va corespunde o soluie real concretizat printr-un algoritm ce poate fi
implementat ntr-un program executabil.
Aceasta este calea general de rezolvare a problemelor i orice poate verifica. Ca i exerciiu,
s se demonstreze corectitudinea (s se aduc argumente precise, clare i convingtoare n favoarea
corectitudinii) metodei de extragere a radicalului nvat nc din coala primar sau a algoritmului lui
Euclid de determinare a celui mai mare divizor comun a dou numere prin mpriri ntregi repetate.
Argumentele elevilor de forma: Este corect pentru c aa ne-a nvat doamna profesoar! sau Este
corect pentru c aa face toat lumea ! snt normale att timp ct nu li se ofer o argumentaie
matematic riguroas.
Ideea central a etapei a doua proiectarea uni algoritm de soluionare eficient poate fi
formulat astfel: din studiul proprietilor i limitelor modelului matematic abstract asociat problemei
se deduc limitele inferioare ale complexitii minimale (efortului minimal obligatoriu) inerente
oricrui algoritm ce va soluiona problema n cauz. Complexitatea intern a modelului abstract i
complexitatea soluiei abstracte se va reflecta imediat asupra complexitii reale a algoritmului, adic
asupra eficienei, de soluionare a problemei. Acest fapt permite prognosticarea nc din aceast faz
faza de proiectare a algoritmului de soluionare a eficienei practice, msurabil ca durat de
execuie, a programului.
Aceast coresponden exact ntre complexitatea modelului abstract i complexitatea
algoritmului de soluionare ofer cheia unor demonstraii riguroase a imposibilitii existenei soluiei
prin metode algoritmice pentru o list ntreag de probleme (cum ar fi de exemplu Problema a 10-a a
lui Hilbert, formulat nc din 1900).
Detailnd cele prezentate deja, vom construi n continuare cadrul teoretic general pentru
nelegerea strategiilor de proiectare a algoritmilor.
Creterea impresionant a puterii de calcul a calculatoarelor i-a obligat pe informaticienii
ultimilor treizeci de ani s nu se mai eschiveze de la abordarea problemelor dificile cu caracter
algoritmic din diverse domenii care au intrat n atenia matematicienilor nc de la nceputul acestui
secol. De altfel, astfel de probleme cu soluii algoritmice nu constituiau neaprat o noutate pentru
matematicienii nceputului de secolul. nc de pe vremea lui Newton matematicienii i-au pus, de
exemplu, problema descoperirii unor metode precise (adic algoritmi!) de determinare n pai de
aproximare succesiv a soluiei unei ecuaii ce nu poate fi rezolvat prin radicali. Dar boom-ul
dezvoltrii tehnicii de calcul din a doua jumtate a secolului a creat posibilitatea abordrii unor
probleme cheie pentru anumite domenii strategice (de exemplu, controlul i dirijarea sateliilor pe
orbit, probleme de planificare sau optimizare n economie, etc.) care se reduc n fapt la soluionarea
eficient a unor probleme de optimizare matematic prin metode iterative (algoritmi).
Spre deosebire de aceste probleme a cror succes n soluionare a fost total i cu consecinele
ce se vd, exist ns o serie de probleme dificile inspirate din realitate care se cer imperios rezolvate
eficient cu ajutorul calculatorului.
Principal caracteristic a acestora este c, datorit generalitii lor sau datorit dificultii
ascunse, n literatura de specialitate nu exist metode iterative eficiente de rezolvare a lor i nu se tie
dac ele admit astfel de soluii. Singurul fapt ce poate fi stabilit dinainte n cazul soluionrii unor astfel
de probleme este spaiul n care soluia trebuie cutat. Ceea ce trebuie atunci construit este o
strategie corect i ct mai general de cutare a soluiei (soluiilor) n acel spaiu de cutare a
soluiilor.
Exemplu concret: exist o clas ntreag de probleme ce cer implicit s se genereze toate
obiectele unei mulimi (cum ar fi problema generrii tuturor permutrilor unei mulimi cu n elemente).
n acest caz este cunoscut dinainte proprietatea ce trebuie s o ndeplineasc fiecare soluie ca s fie un
obiect al spaiului de cutare a soluiilor. Efortul de soluionare va fi redus atunci la aflarea, cutarea
sau generarea pe baza proprietii respective a tuturor obiectelor posibile, fr ns a lsa vreunul pe
dinafar.
Modelul matematic abstract cel mai general care permite modelarea acestui tip de probleme
este graful. Un graf este un obiect matematic riguros care, simplificat, poate fi privit ca fiind o
diagram format din noduri unite prin sgei (muchii). De exemplu, orice hart feroviar sau rutier
poate fi privit ca un graf cu mulimea nodurilor format din localiti iar mulimea muchiilor format
din rutele de transport directe dintre localitile respective. Graful permite descrierea legturilor i a
relaiilor ce exist ntre diferite obiecte abstracte reprezentate prin noduri. Experiena arat c acest

38
model matematic abstract este cel mai general i cel mai potrivit pentru descrierea unui spaiu de
cutare a soluiilor unei probleme. n cazul spaiului de cutare, nodurile snt soluiile posibile
(ipotetice). Dou noduri n graf vor fi unite prin sgei (muchii) dac cele dou soluii posibile au n
comun o aceeai proprietate. Muchiile grafului snt punile ce vor permite algoritmului trecerea de la
un nod la altul, de la o soluie ipotetic la alta, n timpul procesului de cutare a soluiei (sau a tuturor
soluiilor). Rezult c strategiile cele mai generale de cutare a soluiei (soluiilor) pe modelul abstract
asociat problemei snt reductibile la metodele generale de traversare a unui graf.
Ordinea de traversare a grafului determin precis arborele de traversare a grafului. Acest
arbore este de fapt un subgraf particular al grafului iniial, avnd acelai numr de noduri i ca rdcin
vrful iniial de pornire. Cele dou metode clasice de traversare a unui graf (cutare ntr-un graf) poart
n literatura de specialitate numele: BreathFirstSearch (BFS) i DepthFirstSearch (DFS), respectiv
Traversarea n lime (sau traversarea pe nivele) i Traversarea n adncime (traversarea labirintic)
a grafului. Ambele metode stau la baza celei mai cunoscute strategii de proiectare a algoritmilor
(impropriu denumit tehnic de programare): BackTracking respectiv cutare (traversare) n spaiul de
cutare a soluiilor (a grafului) cu revenire pe urma lsat.

Iat un exemplu de graf (7 noduri i 10 arce-sgei) i ordinea sa de traversare prin cele dou
metode:
4 4 4
2 2 2

1 5 7 1 5 7 1 5 7

3 3 3
6 6 6

Ordinea de parcurgere a celor 7 vrfuri ale grafului, innd cont i de sensul dat de sgei, este
n cazul DFS (n adncime): 1,2,4,5,6,3,7 aa cum se vede din arborele parcurgerii n adncime. Din
fiecare nod se continu cu nodul (nevizitat nc) dat de prima alegere posibil: de exemplu, din 4 se
continu cu 5 (ales n favoarea lui 7). Se poate observa cum din nodul 3, nemaiexistnd continuare, are
loc o revenire pe pista lsat pn n nodul 6 de unde se continu parcurgerea n adncime cu prima
alegere posibil. n cazul BFS (n lime) ordinea de traversare este: 1,2,3,4,5,7,6 aa cum se poate
vedea n arborele parcurgerii n lime. n aceast situaie, dintr-un nod snt vizitai toi vecinii
(nevizitai nc), iar apoi se face repet acelai lucru pentru fiecare nod vecin, n ordinea vizitrii. Se
observ cum nodul 7 este vizitat naintea nodului 6, fiind vecin cu nodul 4. (De fapt, aceasta se explic
prin faptul c distana de la 1 la 7 este mai mic cu o unitate dect distana de la 1 la 6.) Putem spune c
n cazul traversrii n lime ordinea de traversare este dat de deprtarea nodurilor fa de nodul de
start.

Iat cum arat procedura general DepthFirstSearch (DFS) de traversare a unui graf descris
n pseudo-cod n varianta recursiv:

Procedura DFS(v:nod);
Viziteaz v;
Marcheaz v; // v devine un nod vizitat //
Ct timp (exist w nemarcat nod adiacent lui v) execut DFS(w);

S nu uitm c aceast procedur poate fi privit ca scheletul pe care se construiete


orice procedur backtracking recursiv.

BackTracking.
Pentru a preciza mai exact n ce const aceast metod, vom relua pe un exemplu concret cele
spuse deja. Avem urmtoarea problem: se cere generarea tuturor permutrilor unei mulimi de n
elemente ce nu conin elementul x (dat dinainte) pe primele dou poziii. Conform celor afirmate, este
suficient s construim modelul abstract - graful - (mai precis arborele) tuturor permutrilor celor n
elemente. Apoi, printr-o parcurgere exhaustiv a nodurilor sale, prin una din metodele BFS sau DFS, s
pstrm numai acele noduri ce verific n momentul vizitrii condiia impus (lipsa lui x de pe
primele dou poziii).
Observm c aceast metod necesit folosirea n scopul memorrii dinamice a drumului
parcurs (n timpul cutrii soluiei) a mecanismului de stiv, fapt sugerat chiar de numele ei: tracking,

39
adic nregistrarea pistei parcurse. Acest mecanism de stiv, care permite att memorarea pistei ct i
revenirea back-tracking-ul, este unul din mecanismele de baz ce este folosit pe scar larg n
procedurile de gestiune dinamic a datelor n memorie. n plus, exist unele cazuri particulare de
probleme n care soluia cutat se obine n final prin vrsarea ntregului coninut al stivei i nu doar
prin nodul ultim vizitat, aflat n vrful stivei.

Exemplul cel mai potrivit de problem ce necesit o strategie de rezolvare backtracking este
Problema Labirintului: se cere s se indice, pentru o configuraie labirintic dat, traseul ce conduce
ctre ieirea din labirint. Iat un exemplu sugestiv:

9 8 7 6
10 1 5
11 2 3 4
12 13 14 15

Observai cum, dup 15 pai, este necesar o revenire (backtracking) pn la csua 6, de unde
se continu pe o alt pist. Pista fals a fost memorat n stiv, element cu element, iar revenirea se
va realiza prin eliminarea din stiv tot element cu element. Cnd n vrful stivei reapare csua cu
numrul 6, stiva ncepe din nou s creasc memornd elementele noului drum. n final stiva conine n
ntregime soluia: drumul corect ctre ieirea din labirint.

6 7
1 5 8
2 3 4 9
1
0
n consecin, indiferent de forma particular ce o poate lua sau de modul n care este citit
n final soluia, esenialul const n faptul c backtracking-ul este o metod de programare ce conine
obligatoriu gestiune de stiv. Lipsa instruciunilor, explicite sau transparente, de gestionare a stivei
ntr-un program (de exemplu, lipsa apelului recursiv), este un indiciu sigur de recunoatere a faptului c
acel algoritm nu folosete metoda sau strategia de rezolvare BackTracking.
Tot o metod back-tracking este i metoda de programare cunoscut sub numele programare
recursiv. Ea este mai utilizat dect metoda clasic BackTracking, fiind mai economicoas din punctul
de vedere al minimizrii efortului de programare. Aceast metod se reduce la construirea, n mod
transparent pentru programator, a arborelui apelurilor recursive, traversarea acestuia prin apelarea
recursiv (repetat) i efectuarea aciunilor corespunztoare n momentul vizitrii fiecrui nod al
arborelui. Apelarea recursiv constituie motorul vehiculului de traversare i are doar rolul de a
permite traversarea arborelui. Gestionarea stivei apelurilor recursive i revenirea - back-tracking-ul
rmne n sarcina mediului de programare folosit i se efectueaz ntr-un mod mascat pentru
programator. Din acest punct de vedere, programatorului i revine sarcina scrierii corecte a
instruciunii de apel recursiv i a instruciunii ce scurt-circuiteaz bucla infinit a apelurilor recursive.
Singurele instruciuni care fac treab, n sensul rezolvrii propriuzise a problemei respective, snt cele
cuprinse n corpul procedurii.

De exemplu, iat cum arat n limbajul de programare Pascal procedura general de generare a
permutrilor n varianta recursiv i arborele de generare a permutrilor mulimii {1,2,3} (n=3), pe
nivele:

Procedure Permut(k:byte;s:string); { k nivelul n arbore, s - irul}


Var i:byte;tmp:char;
Begin
If k=n then begin { scurt-circuitarea recursivitii}
For i:=1 to n do Write(s[i]); { prin afiarea permutrii }
Write(';'); { urmat de un punct-virgul }
end else
For i:=k to n do begin { singurele instruciuni ce fac treab }
tmp:=s[i];s[i]:=s[k];s[k]:=tmp; { snt for-ul i cele trei atribuiri }
Permut(k+1,s); { apelul recursiv ce permite parcugerea }
end; { arbor. de generare a celor n! permutri}
End;

Nivelele arborelui (rsturnat pe orizontal)

40
--------------------------------------------
0 1 2 3
--------------------------------------------
2 ---- 3 Fiecare nivel al arborelui corespunde unei poziii n irul
permutrilor. Astfel, pe prima
1 <
3 ---- 2 poziie (nivelul 1) pot fi oricare din cele trei elemente: 1, 2, 3. Pe
poziia urmtoare pot
/
1 ---- 3 fi oricare din celelalte dou elemente rmase: 2, 3; 1, 3; 1, 2. Pe al treilea nivel i
ultimul
Start -- 2 <
3 ---- 1 vor fi numai elementele rmase (cte unul). Generarea permutrilor
const n construirea
\
1 ---- 2 i parcurgerea arborelui permutrilor: odat ajuni cu parcurgerea
la un capt din dreapta
3 <
2 ---- 1 vom afia de fiecare dat drumul de la rdcin la frunza
terminal.

Observm c arborele permutrilor este identic cu arborele apelurilor recursive i c controlul


i gestiunea stivei se face automat, transparent fa de programator. Instruciunilor de control (din
background) le revine sarcina de a pstra i de a memora, de la un apel recursiv la altul, string-ul s ce
conine permutrile. Dei aceast procedur recursiv de generare a permutrilor pare o variant de
procedur simpl din punctul de vedere al programatorului, n realitate, ea conine ntr-un mod ascuns
efortul de gestionare a stivei: ncrcarea-descrcarea stringului s i a ntregului k. Acest efort este
preluat n ntregime de instruciunile incluse automat de mediul de programare pentru realizarea
recursivitii.

Avantajul metodei back-tracking este faptul c efortul programatorului se reduce la doar trei
sarcini:
1. construirea grafului particular de cutare a soluiilor
2. adaptarea corespunztoare a uneia din metodele generale de traversare-vizitare a grafului n situaia
respectiv (de exemplu, prin apel recursiv)
3. adugarea instruciunilor ce fac treab care, fiind apelate n mod repetat n timpul vizitrii
nodurilor (grafului soluiilor posibile), rezolv gradat problema, gsind sau construind soluia.
Aciunea de revenire ce d numele metodei, backtracking - revenire pe pista lsat, este
inclus i este efectuat de subalgoritmul de traversare a grafului soluiilor posibile. Acest subalgoritm
are un caracter general i face parte din zestrea oricrui programator. n cazul particular n care graful
soluiilor este arbore, atunci se poate aplica ntotdeauna cu succes metoda programrii recursive care
conduce la un cod-program redus i compact.

Prezentm din nou procedura general DepthFirstSearch (DFS) de traversare a unui graf n
varianta recursiv (ce construiete de fapt arborele de traversare a grafului avnd ca rdcin nodul de
pornire) pentru a pune n eviden cele spuse.
Procedura DFS(v:nod);
Viziteaz v; { aici vor fi acele instruciuni care fac treab }
Marcheaz v; // v devine un nod vizitat // { poate s lipseasc n anumite implementri }
Ct timp (exist w nemarcat nod adiacent lui v)
execut DFS(w); { apelul recursiv este motorul vehiculului }
{ ce permite parcurgerea grafului i gestiunea stivei de revenire }

Exist situaii n care, la unele probleme, putem ntlni soluii tip-backtracking fr ns a se


putea sesiza la prima vedere prezena grafului de cutare asociat i aciunea de traversare a acestuia, ci
doar prezena stivei. O privire mai atent ns va conduce obligatoriu la descoperirea arborelui de
cutare pe graful soluiilor, chiar dac el exist doar ntr-o form mascat. Acest fapt este inevitabil i
constituie esena metodei cutare (generare) cu revenire pe pista lsat.
Back-tracking-ul, metod general i cu o larg aplicabilitate, fiind reductibil n ultim
instan la traversarea spaiului -grafului de cutare- a soluiilor, are marele avantaj c determin cu
certitudine toate soluiile posibile, cu condiia ca graful asociat de cutare a soluiilor s fie corect. Dar

41
ea are marele dezavantaj c necesit un timp de execuie direct proporional cu numrul nodurilor
grafului de cutare asociat (sau numrul cazurilor posibile). n cele mai multe cazuri acest numr este
exponenial (en) sau chiar mai mare, factorial (n!), unde n este dimensiunea vectorului datelor de
intrare. Acest fapt conduce la o durat de execuie de mrime astronomic fcnd ntr-un astfel de caz
algoritmul complet inutilizabil, chiar dac el este corect teoretic. (De exemplu, dac soluionarea
problemei ar necesita generarea tuturor celor 100! permutri (n=100), timpul de execuie al
algoritmului depete orice imaginaie.) n astfel de situaii, n care dimensiunea spaiului de cutare-
generare a soluiilor are o astfel de dependen n funcie de n (fiind o funcie de ordin mai mare dect
funcia polinomial), este absolut necesar mbuntirea acestei metode sau nlocuirea ei. Nu este ns
necesar (i de multe ori nici nu este posibil!) abandonarea modelului abstract asociat - graful
soluiilor posibile, cu calitile i proprietile sale certe - ci este necesar doar obinerea unei durate de
execuie de un ordin de mrime inferior printr-o alt strategie de parcurgere a spaiului de cutare.

Greedy.
n strategia backtracking cutarea soluiei, adic vizitarea secvenial a nodurilor grafului
soluiilor cu revenire pe urma lsat, se face oarecum orbete sau rigid, dup o regul simpl care s
poat fi rapid aplicat n momentul prsirii unui nod vizitat. n cazul metodei (strategiei) greedy
apare suplimentar ideea de a efectua n acel moment o alegere. Dintre toate nodurile urmtoare posibile
de a fi vizitate sau dintre toi paii urmtori posibili, se alege acel nod sau pas care asigur un
maximum de ctig, de unde i numele metodei: greedy = lacom. Evident c n acest fel poate s
scad viteza de vizitare a nodurilor adic a soluiilor ipotetice sau a soluiilor pariale prin
adugarea duratei de execuie a subalgoritmului de alegere a urmtorului nod dup fiecare vizitare a
unui nod. Exist ns numeroi algoritmi de tip greedy veritabili care nu conin subalgoritmi de alegere.
Asta nu nseamn c au renunat la alegerea greedy ci, datorit scurtturii descoperite n timpul etapei
de analiz a problemei, acei algoritmi efectueaz la fiecare pas o alegere fr efort i n mod optim a
pasului (nodului) urmtor. Aceast alegere, dedus n etapa de analiz, conduce la maximum de
profit pentru fiecare pas i scurteaz la maximum drumul ctre soluia cutat.
Aparent aceast metod de cutare a soluiei este cea mai eficient, din moment ce la fiecare
pas se trece dintr-un optim (parial) ntr-altul. Totui, ea nu poate fi aplicat n general ci doar n cazul
n care exist certitudinea alegerii optime la fiecare pas, certitudine rezultat n urma etapei anterioare
de analiz a problemei. Ori, dezavantajul este c, la majoritatea problemelor dificile, etapa de analiz
nu poate oferi o astfel de pist optim ctre soluie. Un alt dezavantaj al acestei strategii este c nu
poate s conduc ctre toate soluiile posibile ci doar ctre soluia optim (din punct de vedere a
alegerii efectuate n timpul cutrii soluiei), dar poate oferi toate soluiile optime echivalente.

Programarea dinamic.
Este o metod sau strategie ce i propune s elimine dezavantajele metodei recursive care, n
ultim instan, am vzut c se reduce la parcurgerea n adncime a arborelui apelurilor recursive (adic
backtracking). Aceast metod se apropie ca idee strategic de metoda Greedy, avnd ns unele
particulariti.
Pentru a o nelege este necesar evidenierea dezavantajului major al recursivitii. El const din
creterea exagerat i nerentabil a efortului de execuie prin repetarea ineficient a unor pai.
Urmrind arborele apelurilor recursive se observ repetarea inutil a unor cazuri rezolvate anterior,
calculate deja nainte pe alt ramur a arborelui. Metod eminamente iterativ, programarea dinamic
elimin acest dezavantaj prin rsturnarea procedeului de obinere a soluiei i implicit a arborelui
apelurilor recursive. Printr-o abordare bottom-up (de la baz spre vrf) ea reuete s elimine operaiile
repetate inutil n cazul abordrii top-down (de la vrf spre baz).
Cu toii am nvat c, dac vrem s calculm cu mna o combinare sau un tabel al
combinrilor, n loc s calculm de fiecare dat combinri de n luate cte k pe baza definiiei recursive:
C(n,k)=C(n-1,k-1)+C(n-1,k) cnd n,k>0, sau, C(n,k)=1 cnd k=0 sau n=k, este mult mai eficient s
construim Triunghiul lui Pascal, pornind de la aceeai definiie a combinrilor.

C(4,2)
C(3,1) + C(3,2)
C(2,0) + C(2,1) C(2,1) + C(2,2)
1 C(1,0) + C(1,1) C(1,0) + C(1,1) 1
1 1 1 1

42
1
11
121
1331
14641
..
Observai cum n arborele apelurilor recursive apar apeluri n mod repetat pentru calculul
aceleai combinri. Acest efort repetat este evitat prin calcularea triunghiului lui Pascal n care fiecare
combinare va fi calculat o singur dat.
n mod asemntor, aceeai diferen de abordare va exista ntre doi algoritmi de soluionare a
aceleai probleme, unul recursiv backtracking - i altul iterativ - proiectat prin metoda programrii
dinamice.

Dezavantajele acestei metode provin din faptul c, pentru a ine minte paii gata calculai i a
evita repetarea calculrii lor (n termeni de grafuri, pentru a evita calcularea repetat a unor noduri pe
ramuri diferite ale arborelui apelurilor recursive), este nevoie de punerea la dispoziie a extra-spaiului
de memorare necesar i de un efort suplimentar dat de gestiunea de memorie suplimentar.

Branch & Bound.


Este strategia cea mai sofisticat de proiectare a algoritmilor. Ea a aprut datorit existenei
problemelor pentru care soluia de tip backtracking poate necesita un timp astronomic de rulare a
programului. n rezolvarea acestor probleme apare o asemenea penurie de informaii nct modelul
abstract asociat problemei - graful de cutare a soluiilor nu poate fi precizat n avans, din etapa de
analiz. Singura soluie care rmne este includerea unui subalgoritm suplimentar ce permite
construirea acestui graf pe parcurs, din aproape n aproape. Apariia acelui subalgoritm suplimentar d
numele metodei: branch&bound.
Este posibil compararea algoritmului branch&bound cu un robot ce nva s se deplaseze
singur i eficient printr-un labirint. Acel robot va fi obligat s-i construiasc n paralel cu cutarea
ieirii o hart (un graf !) a labirintului pe care va aplica apoi , pas cu pas, metode eficiente de obinere a
drumului cel mai scurt.
La strategia de cutare a soluiei n spaiul (graful) de cutare - backtracking, fiecare pas urma
automat unul dup altul pe baza unei reguli ncorporate, n timp ce la strategia greedy alegerea pasului
urmtor era fcut pe baza celei mai bune alegeri. n cazul acestei strategii branch&bound, pentru
pasul urmtor algoritmul nu mai este capabil s fac vreo alegere pentru c este obligat mai nti s-i
determine singur nodurile vecine ce pot fi vizitate. Numele metodei, branch=ramific i
bound=delimiteaz, provine de la cele dou aciuni ce in locul aciunii de alegere de la strategia
Greedy. Prima aciune este construirea sau determinarea prin ramificare a drumurilor de continuare, iar
a doua este eliminarea continurilor (ramurilor) ineficiente sau eronate. Prin eliminarea unor ramuri,
poriuni ntregi ale spaiului de cutare a soluiei rmnnd astfel dintr-o dat delimitate i izolate.
Aceast strategie de delimitare din mers a anumitor regiuni ale spaiului de cutare a soluiilor este
cea care permite reducerea ordinului de mrime a acestui spaiu. Soluia aceasta este eficient doar dac
ctigul oferit prin reducerea spaiului de cutare (scznd efortul suplimentar depus pentru
determinarea i eliminarea din mers a continurilor ineficiente) este substanial.
Soluiile de tip backtracking, avnd la baz un schelet att de general (algoritmul de traversare
a grafului de cutare a soluiilor) snt relativ simplu de adaptat n rezolvarea unor probleme. Poate
acesta este motivul care a condus pe unii programatori lipsii de experien la convingerea fals c
Orice este posibil de rezolvat prin backtracking.
La ora actual, lista problemelor pentru care nu se cunosc dect soluii exponeniale, total
nerezonabile ca durat de execuie a programului de soluionare, cuprinde cteva sute de probleme, una
mai celebr ca cealalt. Reamintim doar de banala (dar agasanta) Problem a Orarului unei instituii
de nvmnt care nu admite o soluie backtracking datorit duratei astronomice de ateptare a soluiei.
Datorit totalei lor ineficiene n execuie, soluiile backtracking obinute dup o analiz i o
proiectare la prima mn (brute-force approach, n limba englez) ajung s fie reanalizate din nou cu
mai mult atenie. Se constat atunci c modelul abstract asociat problemei, fie este prea srac n
informaii pentru determinarea grafului de cutare a soluiilor, fie conduce la un graf de cutare avnd
dimensiunea nerezonabil (exponenial sau factorial, fa de dimensiunea n a vectorului de intrare).
Singura soluie care rmne n aceast situaie la dispoziie este ca aceste soluii s fie reproiectate prin
metoda branch&bound.

43
Un exemplu uor de neles de problem branch&bound l ofer Problema General a
Labirintului. Spre deosebire de Problema Labirintului prezentat anterior (care admitea o soluie de tip
backtracking), n varianta extins a acestei probleme, numrul direciilor posibile de urmat la fiecare
pas poate fi orict de mare, iar obstacolele pot avea orice form i dimensiune. n acest caz, singura
posibilitate este construirea din mers a spaiului de cutare a soluiei. Astfel, pentru determinarea
unui drum de ieire din labirint sau a drumului cel mai scurt (dac este posibil determinarea acestuia n
timp rezonabil!) este obligatorie adoptarea strategiei branch&bound.
Oferim n continuare o situaie concret, ilustrat. Sesizai c obstacolele, avnd forme i
dimensiuni diferite, nu pot fi ocolite dect pe un traseu razant sau pe un traseu ce urmeaz contorul
exterior al acestora. Acest fapt complic mult problema i impune luarea unor decizii la faa locului,
n momentul ntlnirii i ocolirii fiecrui obstacol, ceea ce impune o strategie de rezolvare de tip
branch&bound ramific i delimiteaz:




&

Dei aceast strategie poate s creasc uneori surprinztor de mult eficiena algoritmilor de
soluionare (din nerezonabili ca timp de execuie ei pot ajunge rezonabili, datorit reducerii dimensiunii
exponeniale a spaiului de cutare a soluiei), aplicarea ei este posibil doar printr-un efort suplimentar
n etapa de analiz i n cea de proiectare a algoritmului. Dezavantajul major al acestei metode const
deci n efortul major depus n etapa de analiz a problemei (analiz care ns se va face o singur dat
i bine!) i efortul suplimentar depus n etapa proiectrii algoritmului de soluionare.

Din experiena practic este cunoscut faptul c, pentru a analiza o problem dificil un analist
poate avea nevoie de sptmni sau chiar luni de zile de analiz, n timp ce algoritmul de soluionare
proiectat va dura, ca timp de execuie, doar cteva zeci de minute. Dac programul obinut nu este
necesar a fi rulat dect o dat, aceasta este prea puin pentru a se amortiza costul mare al analizei i
proiectrii sale. n acea situaie, soluia branch&bound este nerentabil i, probabil c ar fi mai ieftin
strategia backtracking de soluionare, chiar i cu riscul de a obine o execuie (singura de altfel) a
programului cu durata de o sptmn (ceea ce poate s nsemne totui economie de timp).

Recursivitatea

Aa cum am amintit deja, aceast metod de programare poate fi privit ca form particular
de exprimare a metodei Back-Tracking. Cu toate acestea, cei ce cunosc istoria informaticii i originile
programrii tiu c aceast metod are totui un caracter special. Aceste lucruri dorim s le evideniem
n continuare.
nc nainte de apariia primului calculator i, deci implicit a oricrei tehnici de programare,
unii matematicieni erau profund preocupai de noiunea de calculabilitate. Aceast noiune i putea
ajuta n efortul lor deosebit de a fundamenta noiunea elementar de algoritm sau metod automat de
calcul. n paralel, cele mai valoroase rezultate le-au obinut latino-americanul Alonso Church i
englezul Alan Turing. n timp ce Turing a introdus pentru algoritm modelul matematic abstract
cunoscut sub numele de Maina Turing (care st la bazele modelului actual de calculator), Church a
fundamentat noiunea de metod de calcul sau calculabilitatea pe funciile recursive. Astfel, teza lui
Church afirma c orice funcie definit pe domeniul numerelor naturale este calculabil dac i numai
dac ea este recursiv. Dei aparatul teoretic folosit de Church era n ntregime matematic (se baza
numai pe funcii numerice naturale), lui nu i-a fost greu s demonstreze c orice algoritm nenumeric se
reduce la funcii recursive i la mulimi recursive de numere naturale (pe baza unor codificri riguros
alese).
Acest din urm rezultat este cel care ne intereseaz pe noi i noi l vom reformula fr ai
afecta valabilitatea: orice algoritm poate fi rescris printr-un algoritm recursiv (limbajul de programare
Lisp se bazeaz n ntregime pe acest fapt). Chiar dac nu constituie o demonstraie riguroas,
urmtoarea echivalen practic (descris n pseudo-cod) este deosebit de convingtoare: orice
instruciune de ciclare este echivalent cu un apel recursiv de subprogram sau funcie.

44
Varianta iterativ-cu ciclu Varianta cu apel recursiv
contor:=val_init; Funcie_Recursiv(contor){
Repet Dac contor<val_final atunci
Corp_ciclu; Corp_ciclu;
Incrementeaz(contor); Funcie_Recursiv(contor+1);
Pn cnd contor=val_final; }

Funcie_Recursiv(val_init); // apelul iniial al
funciei

Observm c n cazul variantei recursive condiia de scurt-circuitare a recursivitii este


echivalenta condiiei de scurt-circuitare a ciclului. Gestiunea contorului se face n acest caz n back-
ground, prin mecanismul de stiv sistem.
Putem astfel concluziona: toi algoritmii iterativi pot fi nlocuii prin algoritmi recursivi.
Avantajul celor recursivi este dat de scderea dimensiunilor programelor i de creterea lizibilitii.
Avantajul celor iterativi este viteza mrit de execuie prin gestionarea local a parametrilor de ciclare
(eliminndu-se astfel toate instruciunile push i pop pentru gestionarea stivei).
Spre edificare, v oferim n continuare cteva probleme clasice (simple) rezolvate n C prin
metoda recursiv. n capitolul cu probleme ce necesit back-tracking vei gsi i alte soluii recursive
(n C) ale unor probleme ceva mai dificile; astfel se vor putea sesiza mai bine avantajele acestei metode
"naturale" de programare. (ntruct am considerat acest capitol ca fiind destul de "tehnic", prezentm n
continuare doar variantele de program n limbajul C, ce este considerat mai "tehnic" dect limbajul
Pascal.)

1. S se copieze un ir de caractere ntr-altul.

#include <stdio.h>

char *sir1="primul",*sir2="al doilea";

void strcopy(char *sursa,char *dest){


if ((*dest++=*sursa++)==NULL) return;
else strcopy(sursa,dest);
}
void main(void){
printf("\nInainte, sirul sursa:%s, sirul destinatie:%s",sir1,sir2);
strcopy(sir1,sir2);
printf("\nSi dupa, sirul sursa:%s, sirul destinatie:%s",sir1,sir2);
}

2. S se afieze primele n ptrate perfecte.

#include <stdio.h>
#include <math.h>

int n;

void patrat(int m){


if(m>n)return;
else {
printf("%i:%i ",m,m*m);
patrat(m+1);
}
}
void main(void){
printf("n=");scanf("%i",&n);
patrat(1);
}

45
3.Algoritmul lui Euclid.

#include <stdio.h>

int cmmdc(int m,int n){


if (n==0) return(m);
else cmmdc(n,m%n);
}

void main(void){
int m,n;
printf("m,n=");scanf("%i,%i",&m,&n);
printf("cmmdc(%i,%i)=%i",m,n,cmmdc(m,n));
}

4. Se citete n, s se gseasc primul numr prim mai mare dect n. (Se presupune cunoscut
demonstraia faptului c exist p-prim mai mare dect oricare n. Sntem astfel siguri c algoritmul se
oprete! )

#include <stdio.h>
#include <math.h>

int n;

int are_divizor(int p,int d){


if(d>sqrt(p))return 0;
else if(p%d==0) return 1;
else are_divizor(p,d+1);
}
void prim(int p){
if(!are_divizor(p,2)){
printf("\n%i",p);
return;
}
else prim(p+1);
}
void main(){
printf("n=");scanf("%i",&n);
prim(n+1);
}

5. S se afieze primele n numere prime.

#include <stdio.h>
#include <math.h>

int n;

int are_divizor(int p,int d){


if(d>sqrt(p))return 0;
else if(p%d==0) return 1;
else are_divizor(p,d+1);
}
void prim(int p,int i){
if(i>n)return;
if(!are_divizor(p,2)){
printf("%i,",p);
prim(p+1,i+1);

46
}
else prim(p+1,i);
}
void main(){
printf("n=");scanf("%i",&n);
prim(2,1);
}

6. Se citete n gradul unui polinom P i a[0],a[1],...,a[n] coeficienii reali ai acestuia. Se citete o


valoare real x, s se calculeze P(x).

#include <stdio.h>

int n;
float a[20],x;

float P(int i){


if(i==1)return a[0];
else return P(i-1)*x+a[i-1];
}
void citeste_coef(int i){
if(i>n)return;
else {printf("%i:",i);scanf("%f",&a[i]);citeste_coef(i+1);}
}
void main(){
printf("n=");scanf("%i",&n);
citeste_coef(0);
printf("x=");scanf("%f",&x);
printf("P(%f)=%f",x,P(n+1));
}

7. Se citesc m i n gradele a dou polinoame P i Q, i a[0],a[1],...,a[m] respectiv b[0],b[1],...,b[n]


coeficienii reali ai acestora. S se afieze coeficienii c[0],c[1],...,c[m+n] ai polinomului produs
R=PxQ.

#include <stdio.h>

int m,n;
float a[20],b[20],c[40];

float suma_prod(int i,int j){


if(j==i)return a[i]*b[0];
else return a[i-j]*b[j]+suma_prod(i,j+1);
}
void calc_coef(int i){
if(i>m+n)return;
else c[i]=suma_prod(i,0);
}
void citeste_coef(float a[],int i){
if(i>n)return;
else {printf("%i:",i);scanf("%f",&a[i]);citeste_coef(a,i+1);}
}
void afis_coef(float a[],int i){
if(i>n)return;
else {printf("%f ",a[i]);afis_coef(a,i+1);}
}
void main(){
printf("m(gradul polinomului P)=");scanf("%i",&m);
printf("Introd.coef.polinomului P:");
citeste_coef(a,0);

47
printf("n(gradul polinomului Q)=");scanf("%i",&n);
printf("Introd.coef.polinomului Q:");
citeste_coef(b,0);
calc_coef(0);
afis_coef(c,0);
}

8. Se citete n, o valoarea ntreag pozitiv, s se determine suma cifrelor lui n.

#include <stdio.h>

int n;

int suma(int n){


if(n<10)return n;
else return n%10+suma(n/10);
}
void main(){
printf("n=");scanf("%i",&n);
printf("suma cifrelor=%i",suma(n));
}

48
Probleme rezolvate i exerciii de programare
Vom ncepe prin a face o observaie important: exist totdeauna un pericol n oferirea "pe
tav" a soluiilor la probleme. n urmtoarele subcapitolele nu am fost deloc "zgrcii" i se pot gsi
destule probleme rezolvate att n Pascal ct i n C, dei pentru unele vei putea gsi rezolvarea doar
ntr-unul din limbaje. Pericolul const n faptul c, nceptorilor lenei, lipsii de voin i nclinai ctre
a copia mereu, li se ofer posibilitatea s nu-i mai "bat" capul cu rezolvarea problemelor acum cnd
au totul "de-a gata". Desigur, cei care ies n pierdere snt tot ei. Ne-am asumat acest risc gndindu-ne nu
att la cei lenei ct mai ales la programatorii nceptori bine-intenionai crora aceste probleme, cu
rezolvrile lor tipice, le poate fi de un real folos. Putem spune c urmat astfel exemplul autorilor
mediilor de programare Turbo Pascal i Turbo C (sau Borland) care prin help-urile lor generoase au
contribuit decisiv la formarea multor generaii de programatori.
V avertizm c, n practica concret de programare, programatorul (care nu este i analist)
primete de la cel care a analizat nainte problema doar indicaii de programare. Rareori analistul pune
la dispoziia programatorului i o descriere n pseudocod a algoritmilor ce trebuiesc implementai. Deci,
nici un programator nceptor nu trebuie s-i fac iluzia c "generozitatea" din acest capitol o va mai
ntlni vreodat n practica concret de programare sau c va avea vreodat la dispoziie surse
"abundente" de inspiraie. Este cert c n practic lipsa "inspiraiei" va trebui compensat prin
"transpiraie".

Probleme elementare. Exerciii de programare

Oferim n continuare o mulime de probleme de programare "clasice" rezolvate ntr-un mod


didactic. Am adugat naintea celor dou versiuni de soluionare n cele dou limbaje de programare,
Pascal i C, cteva rnduri ce cuprind elementele de baz ale analizei probleme.
Ne-am strduit s aezm problemele n ordinea dificultii lor, de la cele elementare spre cele
mai dificile. De aceea este recomandat ca ele s fie parcurse n aceast ordine.
Atragem atenia nceptorilor: una din trsturile specifice ale programrii este c o problem
admite mai multe rezolvri corecte. Dei pot fi diferite n unele detalii, fiind echivalente prin rezultatele
pe care le ofer, noi le vom numi variante. Aa c, ceea ce se ofer n continuare este doar o variant de
rezolvare pentru fiecare problem, ea fiind pasibil de mbuntiri, att pentru versiunea Pascal ct i
pentru versiunea C. Se zice c o variant de program (algoritm) este mai eficient dect alta dac
cantitatea de resurse-calculator folosit este mai redus: memorie-calculator (necesarul de spaiu) mai
puin i timp-calculator (necesarul de timp sau durata de execuie) mai mic.
Este cunoscut c n nvarea unei limbi strine ajut mult exersarea traducerilor dintr-o limb
ntr-alta. Evident, pentru realizarea retroversiunii (termenul de specialitate folosit) este necesar
cunoaterea temeinic a uneia din cele dou limbaje. La fel, n cazul programrii, nvarea celui de-al
doilea limbaj de programare este mult uurat de faptul c am asimilat deja primul limbaj de
programare. n finalul capitolului vor apare, pentru exerciiu, mai multe probleme avnd varianta de
rezolvare doar ntr-unul din limbaje, Pascal sau C, i v propunem s scriei programul corespondent n
cellalt limbaj. Astfel, cei care au nvat deja Pascal vor putea astfel s nvee C-ul foarte rapid , i
reciproc.

S se afieze soluiile reale ale ecuaiei de gradul al doilea.

Analiza problemei - elaborarea algoritmului:


Fie ecuatia de gradul II ax2+bx+c=0
-daca toti coeficientii ecuatiei sunt egali cu 0 atunci avem o ecuatie
nedeterminata care are o infinitate de solutii (S=R).
-daca a,b=0 ,iar c<>0 atunci avem o ecuatie care nu are solutii.
-daca a=0 ,b,c <>0 atunci ecuatia se reduce la o ecuatie de gradul I care
are o singura solutie x=-c/b.
-daca a,b,c <>0 atunci trebuie calculat discriminantul (delta) ecuatiei d=b*b-4*a*c
-daca d>=0 atunci ecuatia are solutii reale x1,2=(-b+-sqrt(d))/(2*a)
-daca d<0 atunci ecuatia nu are solutii reale.

program ecuatie;

49
var a,b,c,d:real;
BEGIN
write('a=');readln(a);
write('b=');readln(b);
write('c=');readln(c);
if a=0 then
if b=0 then
if c=0 then
writeln('Ecuatie nedeterminata, S=R')
else writeln('Ecuatia nu are solutii.')
else writeln('Ecuatie de gradul I cu solutia x=',-c/b:6:2)
else
begin
d:=b*b-4*a*c;
if d>=0 then
begin
writeln('x1=',(-b-sqrt(d))/(2*a):6:2);
writeln('x2=',(-b+sqrt(d))/(2*a):6:2);
end
else writeln('Ecuatia nu are solutii reale.');
end;
readln;
END.

#include <stdio.h>
#include <math.h>

float a,b,c; // coeficientii ecuatiei de gradul II


float delta;

void main(){
printf("Introd.coefic.ecuatiei a b c:");scanf("%f %f %f",&a,&b,&c);
delta=b*b-4*a*c;
if (delta>=0) {
printf("Sol.reale: x1=%6.2f, x2=%6.2f",(-b+sqrt(delta))/2./a,(-b-sqrt(delta))/2./a);
} else {
printf("Sol.complexe: x1=(%6.2f,%6.2f), x2=(%6.2f,%6.2f)",-b/2./a,sqrt(-delta)/2./a,-b/2/a,-
1./2./a*sqrt(-delta));
}
}

S se determine dac trei numere reale pot reprezenta laturile unui triunghi. Dac da, s se
calculeze perimetrul si aria sa.

Analiza problemei elaborarea algoritmului :


-trebuie sa vedem cnd trei numere pot fi lungimile laturilor unui triunghi: cele trei numere trebuie sa
fie pozitive si suma a oricare doua dintre ele sa fie mai mare decat a treia latura.
-algoritmul poate fi implementat folosind o functie care sa verifice daca cele trei numere indeplinesc
conditiile enumerate mai sus.
-dupa verificarea celor trei numere calculam perimetrul si aria triunghiului folosind formula lui Heron
s=sqrt(p(p-a)(p-b)(p-c)), unde semiperimetrul este p=(a+b+c)/2.

program arie;
var a,b,c:integer;
s,p:real;

function laturi_ok:boolean;
begin
laturi_ok:= (a>0) and (b>0) and (c>0) and (a+b>c) and (a+c>b) and (b+c>a) ;

50
end;

BEGIN
write('introduceti laturile');readln(a,b,c);
P:=(a+b+c)/2;
IF laturi_ok then
begin s:=sqrt(p*(p-a)*(p-b)*(p-c));
writeln('s=',s:5:2);
writeln(p=,p*2:5:2);
end
else writeln('laturi negative sau prea mari');
readln;
END.

// solutia in limbajul C

#include <stdio.h>
#include <math.h>

float a,b,c;
float s,p;

int laturi_ok(void){
return (a>0)&&(b>0)&&(c>0)&&(a+b>c)&&(a+c>b)&&(b+c>a) ;
}

void main(void){
printf("introduceti laturile a b c:");scanf("%f %f %f",&a,&b,&c);
p=(a+b+c)/2;
if (laturi_ok()){
s=pow(p*(p-a)*(p-b)*(p-c), 0.5);
printf("s=%6.2f p=%6.2f",s,p);
}
else printf("laturi negative sau prea mari");
}

S se afieze media aritmetic, geometric i hiperbolic a trei valori reale.

Analiza problemei - elaborarea algoritmului:


-trebuie aplicate formulele pentru calculul celor trei medii si trebuie analizate cazurile :
cand nu putem calcula media geometrica a trei numere(cand produsul lor este negativ,deci cand
avem unul sau trei numere negative)
cand nu putem calcula media hiberbolica a numerelor(cand unul dintre numere este egal cu 0 si nu
poate fi facuta impartirea cu 0).
- in TurboPascal exista o functie pentru calculul radicalului de ordinul 2 (sqrt),dar pentru calculul
radicalului de ordinul n nu este implementata o functie de aceea pentru calculul radicalului de ordinul n
folosim functia exponentiala ( exp ) pentru a calcula o puterea a lui: an =exp(n*ln(a)), iar pentru a
calcula radical de ordinul n din a: a1/n=exp(1/n*ln(a)) .

program medii;
var a,b,c,ma,mg,mh:real;

BEGIN
write('a=');readln(a);
write('b=');readln(b);
write('c=');readln(c);
writeln('ma=',(a+b+c)/3:6:2);
if (a=0) or (b=0) or (c=0) then writeln('mg=0')

51
else
if a*b*c>0 then writeln('mg=',exp(1/3*ln(a*b*c)):6:2)
else writeln('Nu putem calcula media geometrica ,nr negative .');
if (a=0) or (b=0) or (c=0) then writeln('Nu putem calcula media hiperbolica')
else writeln('mh=',3/(1/a+1/b+1/c):6:2);
readln;
END.

// solutia in limbajul C

#include <stdio.h>
#include <math.h>

float a,b,c,ma,mg,mh;

void main(void){
printf("a=");scanf("%f",&a);
printf("b=");scanf("%f",&b);
printf("c=");scanf("%f",&c);
printf("ma=%6.3f",(a+b+c)/3.);
if (a==0 || b==0 || c==0){
printf("mg=0");
printf("Nu putem calcula media hiperbolica");
} else {
if (a*b*c>0) then writeln("mg=%6.3f",pow(a*b*c,1./3.));
else printf("Nu putem calcula media geometrica ,nr negative .");
printf("mh=%6.3f",3./(1/a+1/b+1/c));
}
}

S se determine suma primelor n numere naturale.

Analiza problemei elaborarea algoritmului:


-suma primelor n numere naturale poate fi calculata, fr a folosi formula cunoscut, cu una dintre
instructiunile repetitive cunoscute(for,while ,repeat)
-indiferent de instructiunea repetitiva folosita trebuie initializata suma cu 0 (s=0)
-folosim un contor i (1,n) care la fiecare pas se incrementeaza cu 1 si se aduna la s
-ciclul se incheie cand valoarea lui i>n
-daca folosim instructiunea for, numarul pasilor este cunoscut, valoarea initiala a contorului fiind 1,
iar cea finala fiind n.

program suma;
var s,i:word;

BEGIN
writeln(Introduceti limita n=);readln(n);
s:=0;
for i:=1 to n do s:=s+i;
writeln(s=,s);
readln;
END.

// solutia in limbajul C

#include <stdio.h>

unsigned s,i;
void main(void){
printf("Introduceti n=");scanf("%u",&n);

52
for(s=0,i=1;i<=n;i++) s+=i;
printf("s=%u",s);
}

S se determine dac n este ptrat sau cub perfect.

Analiza problemei elaborarea algoritmului:

-pentru a verifica daca un numar este patrat perfect calculam radacina patrata a numarului
-daca numarul este patrat perfect radacina lui este un numar intreg altfel este un numar cu zecimale
-verificam daca patratul partii intregii a radacinii numarului este egal cu numarul dat ,daca da numarul
este patrat perfect altfel numarul nu este patrat perfect
-la fel procedam pentru a verifica daca un numar este cub perfect .

program patrat_si_cub_perfect;
var n:longint;

BEGIN
write('n=');readln(n);

if n=trunc(sqrt(n))*trunc(sqrt(n)) then
writeln(n,' este patrat perfect')
else
writeln(n,' nu este patrat perfect');

if n=trunc(exp(1/3*ln(n)))*trunc(exp(1/3*ln(n)))*trunc(exp(1/3*ln(n))) then
writeln(n,' este cub perfect')
else
writeln(n,' nu este cub perfect');
readln;
END.

// solutia in limbajul C

#include <stdio.h>
#include <math.h>

unsigned long n,m;

void main(void){
printf("n=");scanf("%lu",&n);
m=pow(n,0.5);if(n==m*m) printf("n este patrat perfect.");
m=pow(n,1./3.);if(n==m*m*m) printf("n este cub perfect.");
}

S se determine toate numerele de 4 cifre divizibile cu n .

Analiza problemei - elaborarea algoritmului:

-observam ca daca abordam solutia la "prima mn" numarul pailor n cadrul ciclului for este de 8999,
pentru ca valoarea de intrare in ciclul for este 1000 iar valoarea de iesire este 9999.
-re-analiznd problema putem stabili un numar foarte mic de pasi care este egal cu numarul de numere
formate din patru cifre divizibile cu n .

program nr_divizibile;
var n,i:word;

BEGIN

53
write('n=');readln(n);
{for i:=1000 to 9999 do
if (i mod n=0) then write(i,' ');
writeln;}

if 1000 mod n =0 then


for i:=(1000 div n) to 9999 div n do
write(i*n,',')
else
for i:=(1000 div n)+1 to 9999 div n do
write(i*n,',');
readln;
END.

// solutia in limbajul C

#include <stdio.h>

unsigned n,i;

void main(void){
printf("n=");scanf("%u",&n);
if (1000 % n ==0)
for(i=1000 /n;i<=9999 / n;i++) pritnf("%4u,",i*n);
else
for(i=1000 / n+1;i<= 9999 / n;i++) printf("4u,",i*n);
}

S se determine suma cifrelor lui n.

Analiza problemei - elaborarea algoritmului:

-suma cifrelor numarului citit se obtine adunnd de fiecare data ultima cifra ce este restul impartirii lui
n la 10 (n mod 10) iar ceea ce ramine eliminind ultima cifra este dat de impartirea lui n la 10 (n div
10).

program suma_cifre;
var n,s:word;

BEGIN
write('n=');readln(n);
s:=0;
while n<> 0 do
begin
s:=s+n mod 10;
n:=n div 10;
end;
writeln('s=',s);
readln;
END.

// solutia in limbajul C

#include <stdio.h>

unsigned n,s;

void main(void){

54
printf("n=");scanf("%u",&n);
s=0;
while (n!=0) {
s+=n % 10;
n/=10;
}
printf("s=%u",s);
}

S se afieze urmtorul triunghi de numere:

1
12
123
......
1 2 3 ..n

program triunghi;
var i,j,n:word;

BEGIN
write('n=');readln(n);
for i:=1 to n do
begin
for j:=1 to i do
write(j,' ');
writeln;
end;
readln;
END.

// solutia in limbajul C

#include <stdio.h>

int n,i,j;

void main(void){
printf("n=");scanf("%u",&n);
for(i=1;i<=n;i++) {
for(j=1;j<=i;j++)
printf("%i ",j);
putchar('\n');
}
}

Se citete o valoare real. S se determine radical din x cu 5 zecimale exacte pe baza irului
convergent xn=1/2(xn-1+x/xn-1), cu x0>0 arbitrar ales.

Analiza problemei elaborarea algoritmului:

Pentru rezolvarea problemei folosim sirul convergent dat (metoda lui Newton) care consta in etapele:
-pornind cu x0=1 se genereaza recursiv urmatorul sir de numere reale
xn=1/2(xn-1+x/xn-1)
-cand diferenta intre xn si xn-1 este foarte mica(mai mica decat o limita data)procesul de generare a lui xn
inceteaza
-la sfarsit xn reprezinta radacina patrata a lui x.

var x,xn,xn_1:real;

55
BEGIN
write('Introduceti valoarea:');readln(x);
xn:=1;
repeat
xn_1:=xn;
xn:=0.5*(xn_1+x/xn_1);
until abs(xn-xn_1)<1e-5;
writeln('radical din ',xn:6:2,'=',sqrt(x):10:5);
readln;
END.

// solutia in limbajul C

#include <stdio.h>
#include <math.h>

float x,xn,xn_1;

void main(void){
printf("Introduceti valoarea:");scanf("%f",&x);
xn=1;
do{
xn_1=xn;
xn=0.5*(xn_1+x/xn_1);
} while abs(xn-xn_1)<1e-5;
printf('radical obtinut =%7.5f, comparativ cu %7.5",x,pow(x,0.5));
}

Se citete n, s se determine toate numerele perfecte mai mici dect n. Un numr este perfect dac
este egal cu suma divizorilor si (de ex. 6=1+2+3).

Analiza problemei elaborarea algoritmului:

-pentru a verifica daca un numar este patrat perfect trebuie sa i determinam divizorii si sa verificam
daca suma acestora este egala cu n
- se observa ca ultimul divizor nu trebuie luat in calcul pentru ca este egal cu n
-pentru a afisa toate numerele perfecte < n folosim un ciclu while in care il decrementam pe n si
verificam daca noul n este un numar perfect ,daca da il afisam

program nr_perfecte;
var n,d,i:word;

BEGIN
write('n=');readln(n);
while n>1 do
begin
dec(n);
d:=0;
for i:=1 to n-1 do
if n mod i=0 then d:=d+i;
if n=d then writeln(n);
end;
readln;
END.
// o varianta C

#include <conio.h>
#include <stdio.h>

56
main()
{
long int i,n,j,sum,k;
clrscr();
printf("n=");
scanf("%ld",&n);
k=0;
i=0;
do
{
k=k+1;
do
{
sum=1;
i=i+1;
for(j=2;j<=i/2;j++)
if (i%j==0)
sum=sum+j;
}
while(sum!=i);
printf("%ld ",i);
}
while(k<n);
}

Se citete n un numr ntreg pozitiv, s se afieze n transcris n baza 2.

Analiza problemei - elaborarea algoritmului:


- folosim algoritmul cunoscut :
ct timp n <>0 executa
- imparte n la 2
- in urma impartirii n retine catul si restul
- numarul in baza doi se obtine scriind resturile in ordinea inversa in care le-am obtinut
- pentru a retine aceste resturi care trebuie tiparite in ordine inversa am folosit un sir (n2inv) in care
am retinut resturile pe care dupa aceea l-am afisat in ordine inversa.

program transf_in_baza_2;
var n,n2,i,j:word;
n2inv:array[1..20] of word;

BEGIN
write('n=');readln(n);
i:=1;
while n>0 do
begin
n2:=n mod 2;
n2inv[i]:=n2;
n:=n div 2;
i:=i+1;
end;
for j:=i-1 downto 1 do
write(n2inv[j]);
readln;
END.

// o varianta C putin diferita

57
#include <stdio.h>
typedef unsigned char pointer[4];
void afiseaza(pointer px,int dim,char* format){
int i,j;
for(j=dim-1;j>=0;j--){
for(i=8;i>=0;i--) printf("%c",px[j] & (1<<i) ? '1':'0');
putchar('.');
}
printf(" adica ");printf(format,*px);
}
float y;
long x;

void main(void){
printf("\nIntrod. intregul x si realul y:");scanf("%d %f",&x,&y);
printf("\nx= ");
afiseaza(&x,sizeof(x),"%d");
printf("\ny= ");
afiseaza(&y,sizeof(y),"%f");
}

Se citete n i irul de valori reale x1,x2,..,xn ordonate cresctor. S se determine distana


maxim ntre dou elemente consecutive din ir.

Analiza problemei - elaborarea algoritmului :


- este o problema maxim
- distanta dintre primele valori consecutive din sir se noteaza cu max
- dupa care facem o comparatie cu urmatoarele distante dintre valori
- in momentul in care se intalneste o valoare mai mare decat max atunci aceasta valoare va deveni
noul max
- algoritmul se opreste in momentul in care se face comparatia dintre max si distanta dintre ultimele
doua valori ale sirului.

program dist_elem;
var n,i:word;
max:real;
x:array[1..50] of real;

BEGIN
write('n=');readln(n);
for i:=1 to n do
begin
write('x[',i,']=');
readln(x[i]);
end;
max:=x[2]-x[1];
for i:=2 to n-1 do
if x[i+1]-x[i]>max then max:=x[i+1]-x[i];
writeln('max=',max:6:2);
readln;
END.

Se citete n gradul unui polinom i irul coeficienilor an, .. , a0. Se citete x, s se determine P(x).

program polinom;
var n,i :integer;
p,x:real;
a:array[0..20] of integer;

58
BEGIN
write('n=');readln(n);
for i:=0 to n do
begin
write('a[',i,']=');
readln(a[i]);
end;
write('x=');readln(x);

{p:=a[0];
for i:=1 to n do
p:=p+a[i]*exp(i*ln(x));
writeln('P(',x,')=',p:6:2);}

p:=0;
for i:=n downto 0 do
p:=p*x+a[i];
writeln('P(',x,')=',p:6:2);
readln;
END.

Se citete o propoziie (ir de caractere) terminat cu punct. S se determine cte vocale i


consoane conine propoziia.

Analiza programului - elaborarea algoritmului:


- citim propozitia caracter cu caracter pana la intalnirea caracterului '.'
- folosim instructiunea case (selectie multipla) care daca la intalnirea unei vocale din sir
incrementeaza nr de vocale ,iar la intalnirea unei consoane incrementeaza nr de consoane.

program nr_consoane_si_vocale;
var c:char;
i,nv,nc:word;
sir:string[25];

BEGIN
write('Introduceti propozitia:');readln(sir);
i:=1; nv:=0; nc:=0;
repeat
case sir[i] of
'a','e','i','o','u': nv:=nv+1;
'b','c','d','f','g','h','j','k','l','m','n','p','r','s','t','x','y','w' :
nc:=nc+1;
end;
i:=i+1;
until sir[i]='.';
writeln('Nr de vocale=',nv);
writeln('Nr de consoane=',nc);
readln;
END.

// varianta C

#include <stdio.h>
#include <ctype.h>

int i,vocale=0,consoane=0;
char c,sir[80];

void main(void){

59
printf("Introd.propozitia terminata cu punct:");gets(sir);
for(i=0;sir[i]!='.';i++)
switch (toupper(sir[i])){
case 'A':
case 'E':
case 'I':
case 'O':
case 'U': vocale++; break;
default: if (isalpha(sir[i])) consoane++;
}
printf("Vocale:%i, Consoane:%i, Alte car.:%i", vocale, consoane, i-vocale-consoane);
}

Se citete m,n dimensiunea unei matrici A=(a[i,j])mxn de valori reale. S se determine suma
elementelor pe fiecare linie i coloan.

program matrice3;
var m,n,i,j:word;
a:array[1..50,1..50] of real;
sl,sc:array[1..50] of real;

BEGIN
write('Introduceti nr de linii m=');readln(m);
write('Introduceti nr de coloane n=');readln(n);
for i:=1 to m do
begin
for j:=1 to n do
begin
write('a[',i,',',j,']=');
read(a[i,j]);
end;
writeln;
end;

for i:=1 to m do sl[i]:=0;


for j:=1 to n do sc[j]:=0;

for i:=1 to m do
begin
for j:=1 to n do
sl[i]:=sl[i]+a[i,j];
writeln('suma elementelor de pe linia ',i,'=',sl[i]:6:2);
end;

for j:=1 to n do
begin
for i:=1 to m do
sc[j]:=sc[j]+a[i,j];
writeln('suma elementelor de pe coloana ',j,'=',sc[j]:6:2);
end;
readln;
END.

// varianta C

#include <stdio.h>

unsigned m,n,i,j;
float a[50][50];

60
float sl[50],sc[50];

void main(void){
printf("Introduceti nr de linii m=");scanf("%u",&m);
pritnf("Introduceti nr de coloane n=");scanf("%u",&n);
for (i=0;i<m;i++){
for (j=0;j<n;j++){
printf("a[%u,%u]=",i,j);
scanf("%f",&a[i][j]);
}
putchar('\n');
};
for (i=0;i<m;i++) sl[i]=0;
for (j=0;j<n;j++) sc[j]=0;
for (i=0;i<m;i++) {
for (j=0;j<n;j++)
sl[i]+=a[i][j];
printf("suma elementelor de pe linia %u =%f",i,sl[i]);
}
for (j=0;j<n;j++) {
for (i=0;i<m;i++)
sc[j]+=a[i][j];
pritnf("suma elementelor de pe coloana %u=%f",j,sc[j]);
}
}

Se citete n i k, i o matrice A=a[i,j]nxn ptratic. S se determine Ak.

Analiza problemei - elaborarea algoritmului:


-algoritmul consta de fapt in calcularea elementelor matricii produs
-elementul c[i,j] =suma(k=1..n) a[i,k]*b[i,k] .
-Ak=A*A*..*A
-matricea fiind patratica atunci cand k=2 termenii b[i,k]=a[i,k],iar cand k>2 termenii b[i,k] pastreaza
elementele produsului anterior A*A, folosim pentru aceasta atribuire procedura aribuire.

program matrice1;
type matrice= array[1..3,1..3] of real;
var a,b,p: matrice;
n,i,j,k,l:word;

procedure atribuire(a:matrice);
begin
for i:=1 to n do
for j:=1 to n do
b[i,j]:=a[i,j];
end;

procedure inmultire ;
begin
for i:=1 to n do
for j:=1 to n do
p[i,j]:=0;
for i:=1 to n do
for j:=1 to n do
for l:=1 to n do
p[i,j]:=p[i,j]+a[i,l]*b[l,j];
end;

BEGIN

61
write('Introduceti puterea lui A ,k=');readln(k);
write('Introduceti dimensiunea matricii n=');readln(n);
for i:=1 to n do
begin
for j:=1 to n do
begin
write('a[',i,',',j,']=');
readln(a[i,j]);
end;
writeln;
end;

if k=1 then
for i:=1 to n do
for j:=1 to n do
p[i,j]:=a[i,j]
else
if k=2 then
begin
atribuire(a);
inmultire;
end
else
begin
atribuire(a);
inmultire;
k:=k-1;
while k>1 do
begin
atribuire(p);
inmultire;
k:=k-1;
end;
end ;

for i:=1 to n do
begin
for j:=1 to n do
write('p[',i,',',j,']=',p[i,j]:6:2,' ');
readln;
end;
readln;
END.

Iat un program Pascal care gestioneaz cu ajutorul unui fiier un catalog de note i persoane.

Type Persoana=Record Nume:String[20];Nota:Array[1..4]of integer; End;


Var f:File of Persoana;
Perstemp:Persoana;
Procedure Creare;
Begin
Writeln('Introd.');
Assign(f,'Test.jo');
Rewrite(f);
Repeat
With PersTemp do begin
Write('Numele:');Readln(Nume);
If Nume='' then break;

62
Write('Notele:');Readln(Nota[1],Nota[2],Nota[3],Nota[4]);
end;
Write(f,PersTemp);
Until False;
Close(f);
End;
Procedure Citire;
Begin
Writeln('Introd.');
Assign(f,'Test.jo');
Reset(f);
Repeat
Read(f,PersTemp);
With PersTemp do begin
Writeln('Numele:',Nume);
Writeln('Notele:',Nota[1],Nota[2],Nota[3],Nota[4]);
end;
Until Eof(f);
Close(f);
End;
BEGIN
Creare;
Citire;
END.

Iat trei programe care exemplific modul de lucru cu fiiere n limbajul C.

// Copierea unui fisier text sursa intr-un fisier destinatie

#include <stdio.h>
void main(void)
{
FILE *in, *out;
char numfin[20],numfout[20];
long contor=0;

printf("Nume fisier sursa:");gets(numfin);


printf("Nume fis.destinatie:");gets(numfout);
if ((in = fopen(numfin, "rt"))== NULL){
fprintf(stderr, "Eroare: %s fisier inexistent.\n",numfin);
return;
}
out = fopen(numfout, "wt");
while (!feof(in)){
fputc(fgetc(in), out);contor++;
}
fclose(in);fclose(out);
printf("Lungimea fis.destinatie este de %ld octeti.",contor);
}

// Copierea unui fisier text sursa intr-un fisier destinatie


// cu substituirea unor cuvinte date prin linia de comanda

#include <stdio.h>
void main(int argc,char *argv[])
{
FILE *in, *out;
char numfin[20],numfout[20],c;

63
unsigned i=0,contor=0;

printf("Nume fisier sursa:");gets(numfin);


printf("Nume fis.destinatie:");gets(numfout);
if ((in = fopen(numfin, "rt"))== NULL){
fprintf(stderr, "Eroare: %s fisier inexistent.\n",numfin);
return;
}
out = fopen(numfout, "wt");
while (!feof(in)){
if((c=fgetc(in))==argv[1][i]){
if(argv[1][++i]==0) // s-a detectat sfirsitul sirului de caractere
fputs(argv[2],out),i=0; // se scrie sirul de caractere inlocuitor
}
else fputc(c, out);contor++;
}
fclose(in);fclose(out);
printf("Lungimea fis.destinatie este de %d octeti.",contor);
}

// prelucrarea unul fisier C ce contine o agenda telefonica

#include <stdio.h>
#include <ctype.h>
#include <conio.h>

struct articol
{
char nume[10],adresa[10],tel[7];
} inreg;

FILE *fagenda,*ftemp;
char mod[3]="wb";

void creare(void){
char temp;
puts("\nCrearea agendei:");
do{
printf("\nNume:");gets(inreg.nume);
printf("Adresa:");gets(inreg.adresa);
printf("Tel:");gets(inreg.tel);
fwrite(&inreg, sizeof(inreg), 1, fagenda); /* write struct inreg to file */
printf("Continuati[D/N]?");temp=getch();
}
while(toupper(temp)!='N'); // ciclu infinit ? NU!
fclose(fagenda); /* close file */
}

void listare(void){
int contor=0;
puts("\nListarea agendei:");
mod[0]='r';
if ((fagenda= fopen("agenda.jo", mod)) == NULL) /* open file agenda */
fprintf(stderr, "Cannot open output file.\n");
while(fread(&inreg, sizeof(inreg), 1, fagenda)!=0) /* write struct inreg to file */
printf("%d: %s, %s, %s\n",++contor,inreg.nume,inreg.adresa,inreg.tel);
fclose(fagenda); /* close file */
}

void main(void)

64
{
if ((fagenda= fopen("agenda.jo", mod)) == NULL) /* open file agenda */
fprintf(stderr, "Cannot open output file.\n");
creare();
listare();
}

65
Probleme ce necesit back-tracking

Am explicat pe larg aceast metod de programare ntr-un capitol separat. n acest capitol vom
oferi doar cteva exemple de probleme rezolvate. Majoritatea dintre ele snt de maxim dificultate i nu
li se cunoate o altfel de rezolvare dect prin aceast metod. Din fericire, aceast metod de proiectare
a soluiei are un caracter foarte general i "funcioneaz" n fiecare caz. Din nefericire, n practic,
atunci cnd dimensiunea datelor de intrare este consistent (avnd valori cel puin de ordinul sutelor)
programul rezultat devine, prin durata astronomic de execuie, total inutilizabil.
Atragem atenia c doar simpla lecturare a acestor exemple de probleme de back-tracking
rezolvate nu permite nicidecum nsuirea acestei metode de proiectare a soluiilor. Este necesar mai
nti implicarea i participare personal, a celui ce-i propune s nvee aceast metod, ncercnd direct
soluionarea lor i abia apoi comparnd soluia rezultat cu cea propus de noi.

Problema clasic de programare care necesit back-tracking (revenirea pe urma lsat) este
problema ieirii din labirint.

- iat o soluie simpl care iniializeaz labirintul n mod static, ca o matrice de caractere

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define XMAX 6
#define YMAX 6

char a[XMAX+1][YMAX+1]={
"*******",
"* * *",
"* * * *",
"* * ****",
"** * *",
"* * ",
"********"
};
int x0=1,y0=2;

void print(void){
int i,j;
for(i=0;i<=XMAX;i++){
for(j=0;j<=YMAX;j++)putchar(a[i][j]);
putchar('\n');
}
getchar();clrscr();
}

void escape(int x,int y){


if(x==XMAX || y==YMAX){ puts("Succes!");exit(1);}
a[x][y]='*';print();
if(a[x][y+1]==' '){puts("la dreapta");escape(x,y+1);}
if(a[x+1][y]==' '){puts("in jos ");escape(x+1,y);}
if(a[x][y-1]==' '){puts("la stinga ");escape(x,y-1);}
if(a[x-1][y]==' '){puts("in sus ");escape(x-1,y);}
return;
}

void main(void){
escape(x0,y0);
puts("Traped!");
}

66
S se genereze toate irurile de lungime n formate numai din caracterele a, b i c a.. s nu existe
dou subiruri identice alturate.

- de exemplu, dac n=3 putem avea iruri de forma abc, cab, bcb, etc. dar nu i iruri de forma aab;
pentru n=4 nu putem genera iruri de forma abab, baac, etc.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define byte unsigned char

char car[4]=" abc";


unsigned int n,contor;

int Valid(char *s,char c,byte k){ // functia de validare a sirului generat


byte i,j,ok,Val=1; // prin concatenarea unui singur caracter
for(i=k-1;i>=(k+1)/2;i--)
if (s[i]==c){
ok=1;
for(j=1;j<=k-i-1;j++)
if (s[i-j]!=s[k-j]){ok=0;break;}
if (ok) { Val=0;break;}
}
return Val;
}

void ConcatSir(char *s,byte k){ // functia ce implementeaza back-tracking-ul


byte i; // in varianta recursiva
if(k<=n){
for(i=1;i<=3;i++)
if (Valid(s,car[i],k)) {
s[k]=car[i];s[k+1]='\0';
ConcatSir(s,k+1);
}
} else { contor++;printf("%4i:%s",contor,s);}
}

void main(void){
printf("n:");scanf("%i",&n);
contor=0;
ConcatSir(" ",1);
exit;
}

S se afieze toate descompunerile unei sume s ntr-un numr minim de monezi ale unui sistem
monetar de n valori.

- de exemplu, n cazul unui sistem monetar de forma 10, 5, 3, 1 putem descompune suma 18 n diverse
moduri dar soluia minimal necesit doar 3 monezi: 18=1 x 10+1 x 5+1 x 3 ; descompunerea
minimal poate s nu fie unic ; sistemul monetar trebuie s fie astfel ales nct s permit
descompunerea oricrei sume ncepnd de la o valoare minimal n sus (orice sistem monetar conine de
obicei moneda unitar 1)

#include <stdio.h>

int m[10],a[10],a_final[10],s,n,nrmin=32000,kmin;

67
void descompune(int s,int k,int contor){
register int i;
if(s==0)
if(contor<nrmin){
nrmin=contor;kmin=k-1;
for(i=1;i<=k;i++)a_final[i]=a[i];
for(i=k+1;i<=n;i++)a_final[i]=0;
return;
}
else return;
if(k>n) return;
if(k==n){
a[k]=s/m[k];descompune(s-a[k]*m[k],k+1,contor+a[k]);
}
else for(i=s/m[k];i>=0;i--){
a[k]=i;descompune(s-i*m[k],k+1,contor+i);
}
}

void main(void){
int i;
printf("Introd.nr.de valori n a sistemului monetar:");scanf("%i",&n);
printf("Introd.in ordine descresc.cele %i valori monetare:",n);
for(i=1;i<=n;i++)scanf("%i",&m[i]);
printf("Introd.suma s:");scanf("%i",&s);
descompune(s,1,0);
if(nrmin>0) for(i=1;i<=kmin;i++)printf("%i * %i,",a_final[i],m[i]);
else puts("Nu se poate descompune !");
}

S se afieze toate descompunerile unui numr s ca sum de n elemente.

- de exemplu, pentru s=13 i n=3 avem urmtoarele 14 descompuneri 13= 1+1+11= 1+2+10=
1+3+9== 1+6+6= 2+2+9= 2+3+8= 2+4+7= 2+5+6= 3+3+7= 3+4+6= 3+5+5= 4+4+5
- dei este cu totul alt problem dect cea dinainte, putem observa asemnarea dintre cele dou soluii
(ambele snt date n varianta recursiv)

#include <stdio.h>

int a[10],s,n,contor=0;

void descompune(int s,int k){


register int i;
if(k==1){ a[n]=s;printf("%3i:",++contor);
for(i=1;i<=n;i++)printf("%i ",a[i]);
puts("");return;
}
else for(i=1;i<s;i++){ a[n+1-k]=i;descompune(s-i,k-1);}
}

void main(void){
printf("Introd.suma s si in cit se descompune n:");scanf("%i %i",&s,&n);
descompune(s,n);
getchar();
}

68
S se afieze toate descompunerile unui numr s ca sum de n elemente distincte.

- aceasta este o variant a problemei dinainte; putei sesizai unde apare diferena n rezolvare ?

#include <stdio.h>

int a[10],s,n,contor=0;

void descompune(int s,int k){


register int i;
if(k==0){ printf("%3i:",++contor);
for(i=1;i<=n;i++)printf("%4i",a[i]);
puts("");return;
}
else for(i=a[n-k]+1;i<s;i++){ a[n+1-k]=i;descompune(s-i,k-1);}
}

void main(void){
printf("Introd.suma s si in cit se descompune n:");scanf("%i %i",&s,&n);
a[0]=0;
descompune(s,n);
if(contor==0)puts("Nu se poate descompune !");
getchar();
}

69
Probleme cu soluie surprinztoare

n rezolvarea fiecreia din problemele urmtoare este foarte uor de czut n capcana
soluionrii de genul "la prima mn" sau brute-force-approach n limba englez (abordare n for
brut). Este cea mai des ntlnit capcan pentru programatorii lipsii de subtilitate, experien sau
cultur de specialitate. Este i aceasta o rezolvare, desigur, dar lipsa ei de eficien i de elegan este
evident. Tocmai de aceea, considerm foarte util prezentarea ctorva exemple elocvente, mpreun cu
soluiile lor. Unele dintre probleme au fost selecionate dintre problemele date la concursurile i
olimpiadele colare de programare .
Prin acest capitol nu urmrim doar nsuirea unor cunotine practice de programare ci, mai
ales, aprofundarea capacitii de analiz i proiectare a soluiilor. Aceasta presupune un salt calitativ n
nvarea programrii i de aceea acest capitol devine cu adevrat util numai pentru acei programatori
inteligeni i dornici de auto-perfecionare. Sau pentru cei care se pregtesc pentru participarea la
concursurile i olimpiadele de informatic.
Soluiile oferite de noi snt, pentru fiecare problem, eficiente i "elegante". Acest fapt se
datoreaz accentului pus pe aprofundarea i mbuntirea primei analize a problemei.
Putem atunci spune, c motto-ul acestui capitol este: "Nu te mulumi niciodat cu soluia la
prima mn !".

S se afieze numrul cuburilor perfecte mai mici dect n.

Analiza problemei - elaborarea algoritmului:

Capcana problemei const n tentativa de a parcurge printr-un ciclu for toate numerele de la 1 la n i de
a contoriza cele care snt cuburi perfecte.
La o a nou privire, mai atent, observm c partea ntreag a radicalului de ordinul 3 din n ne ofer
acel numr care ridicat la a 3-a este cel mai apropiat cub de n. Deci, partea ntreagp a radicalului de
ordinul 3 din n este egal chiar cu numrul cuburilor mai mici dect n.
(Este suficient s calculm radical de ordinul 3 din n pentru a afla cte cuburi mai mici dect n exist.)

program cuburi_perfecte;
var n,i,nr_cub:word;
BEGIN
write('n=');readln(n);
nr_cub:=trunc(exp(1/3*ln(n)));
writeln('numarul cuburilor perfecte < ',n,' este = ', nr_cub);
readln;
END.

Se citesc m, n numrtorul i numitorul unei fracii. S se simplifice aceast fracie.

Analiza problemei - elaborarea algoritmului:


Capcana const n a efectua simplificarea pas cu pas, cutnd pe rnd fiecare divizor comun al
numrtorului i numitorului. n plus, ar trebui s avem grij c, pentru unii divizori comuni, este
nevoie de o simplificare repetat. Deci, dou cicluri imbricate !
-pentru a obine o fracie ireductibil este suficient s o simplificm o singur dat cu cmmdc al
numitorului i al numrtorului,eliminndu-se astfel simplificrile succesive
-vom folosi subalgoritmul (Euclid) care calculeaz cmmdc al numrtorului i al numitorului.

program simplificare;
var m,n:word;

function cmmdc(m,n:word):word;
begin
while m<>n do
if m>n then m:=m-n
else n:=n-m;

70
cmmdc:=m;
end;

BEGIN
write('numaratorul fractiei m= ');readln(m);
write('numitorul fractiei n= ');readln(n);
if n=0 then writeln('Fractie inexistenta.')
else
if m=0 then writeln(m,'/',n,'=',0)
else
writeln(m,'/',n,' = ',m div cmmdc(m,n),'/',n div cmmdc(m,n));
readln;
END.

Se citesc a, b, c ntregi. S se determine toate perechile ntregi (x,y) soluii ale ecuaiei ax+by=c.

Analiza problemei elaborarea algoritmului;

Problema a fost dat la olimpiada colar de informatic. Ea pare la prima vedere imposibil. Exist
ecuaii, de exemplu: 3x+2y=1 care are o infinitate de soluii , (1,-1), (3,-4), (5,-7), (7,-10), Cum ar
putea fi afiat atunci pe ecran o mulime infinit de perechi ? Soluia este de a afia aceast mulime
printr-o descriere sintetic a ei (afind formula care poate genera toate perechile ce o compun).
1. daca c=1 atunci exista (x0,y0) a.. ax0+by0=1 doar daca [a,b]=1 ; restul solutiilor (x,y) au forma
x=x0+kb , y=y0-ka, cu k intreg.
2. daca c>1 atunci exista solutiile (x0,y0) doar daca [a,b]|c; restul solutiilor se construiesc la fel;
prin [a,b] se inelege cmmdc(a,b)
Programul trebuie doar s determine x0 i y0.

Program ax_plus_by_egal_c;
Var a,b,c,x0,y0,y:integer;
BEGIN
Write('a,b,c=');Readln(a,b,c);
x0:=0;
For y:=0 to a do
If abs(c-b*y) mod a=0 then begin
y0:=y;x0:=(c-b*y) div a;break;
end;
If x0<>0 then Writeln('Sol. (x,y) ale ec. ',a,'x+',b,'y=',c,' sint (',x0,'+k*',b,',',y0,'-k*',a,')')
else Writeln('Nu exista solutii pentru ecuatia ',a,'x+',b,'y=',c);
END.

/*Varianta C de solutionare:
1. daca c=1 atunci exista (x0,y0) a.i. ax0+by0=1 doar daca cmmdc[a,b]=1 ;
restul solutiilor (x,y) au forma x=x0+kb y=y0-ka, cu k intreg.
2. daca c>1 atunci exista solutiile (x0,y0) doar daca cmmdc[a,b] | c;
restul solutiilor se construiesc la fel.
3. exista posibilitatea ca, pornind de la perechi (x0,y0) distincte, sa se
obtina solutii noi diferite (multimi infinite de perechi distincte).
4. toate solutiile (multimi infinite de perechi) pleaca de la o pereche
(x0,y0) aflata in dreptunghiul (-b,-a)x(b,a).
Un bun exemplu este ecuatia 18x+42y=6.*/

#include <stdio.h>
#include <math.h>

int a,b,c,x0=0,y0=0,y,k;

void main(void){

71
printf("a,b,c:");scanf("%i %i %i",&a,&b,&c);

printf("Ecuatia %ix+%iy=%i are sol.de forma:",a,b,c);


for(y=0;y<=a;y++)
if(abs(c-b*y) % a==0){
y0=y;x0=(c-b*y) / a;
if(x0!=0){
printf("\n %i*k%+i, -(%i*k-%i), de ex. ",b,x0,a,y0);
for(k=-2;k<=2;k++)printf("(%i,%i) ",x0+k*b,y0-k*a);
}
}
if(!x0 && !y0 && c)printf("Nu exista solutii pentru ecuatia %ix+%iy=%i",a,b,c);
}

Se citete n o valoare ntreag pozitiv. S se determine toate descompunerile n diferen de


ptrate ale lui n.

Analiza problemei elaborarea algoritmului:


Artm n continuare cum se poate evita soluia "banal"-capcan ce-ar consta n dou cicluri for
imbricate. Soluia urmtoare efectueaz doar radical din n pai, fa de n2 pai ai soluiei "la prima
mn".
-pentru a determina toate descompunerile in diferenta de patrate ale lui n pornim de la formula a 2-
b2=(a+b)(a-b)=n
-observam ca produsul termenilor a+b si a-b este produsul a doi dintre divizorii lui n,unul din termeni
este divizor (d) a lui n celalalt este tot divizor a lui n si il aflam impartindu-l pe n la d (n div x)
-notam cu x primul divizor a lui n (x=d) si cu y=n div x si obtinem relatiile
a+b=x deci un sistem de doua ecuatii cu doua necunoscute ,pe care il rezolvam
a-b=y prin metoda reducerii ,si avem 2a=x+y => a=(x+y )/2 , b=(y-x)/2,
-pentru ca (x+y)/2 sa fie o solutie a ecuatiei a2-b2=(a+b)(a-b)=n trebuie ca x+y sa fie un numar par si
y-x sa fie un numar par
-daca aceasta conditie este indeplinita afisam solutia care indeplineste conditia ceruta.

Program descompunere_patrate;
var n,d,a,b,x,y:integer;
BEGIN
write('n=');readln(n);
for d:=1 to trunc(sqrt(n)) do
if n mod d =0 then
begin
x:=d;
y:=n div x;
if (x+y) mod 2 =0 then
begin
a:=(x+y) div 2;
b:=(y-x) div 2;
writeln(n,'=',a*a,'-',b*b);
end;
end;
readln;
END.

Se citete n i x1, x2, , xn rdcinile ntregi ale unui polinom de gradul n. Se cere s se determine
pe baza relaiilor lui Viete coeficienii an, an-1, , a1, a0.

Analiza problemei elaborarea algoritmului;

Cea mai des ntlnit rezolvare este cea de tip back-tracking, aparent mai uoar, dar n fapt
extrem de ineficient pentru n nu mare ci doar mricel ! Urmtoarea soluie de tip iterativ este o mic
"bijuterie" de program iterativ i de aceea v lsm plcerea de a-l nelege singuri.

72
#include <stdio.h>

void main(void){
int a[100],x[100],n,i,k;
printf("n=");scanf("%d",&n);
printf("Radacinile:\n");
for(i=0;i<n;i++){
printf("x[%d]=",i);scanf("%d",&x[i]);a[i]=0;
}
a[0]=1;a[n]=0;
for(k=1;k<=n;k++){
for(i=k;i>0;i--)
a[i]=a[i-1]-a[i]*x[k-1];
a[0]*=-x[k-1];
}
for(i=n;i>=0;i--) printf("a[%d]=%d ",i,a[i]);
}

Se citete n. S se afieze toate numerele de n cifre, formate numai cu cifrele 1 i 2, divizibile cu


2n.

Analiza problemei elaborarea algoritmului:


Problema a fost dat la olimpiada colar de informatic. Abordarea "n for" a acestei probleme nu
duce la nici un rezultat:
- daca s-ar alege varianta de rezolvare "la prima mina" ar trebui verificate toate cele 2 n posibilitati,
adica toate cele 2n numere de n cifre ce se pot forma numai cu cifrele 1 si 2 (cite 2 posibilitati
pentru fiecare pozitie). In acest caz, programul avind o complexitate exponentiala, ar dura un
timp exponential, pt. n=50 ar dura ct vrsta sistemului nostru solar !
pt.n=1 avem unica solutie numarul 2;
pt. n=2 avem deasemenea unica solutie 12; observam ca 2-ul este "folosit"
pt. n=3 avem deasemenea unica solutie 112; observam ca 12 este din nou "folosit"
In general, se deduce ca numerele de n cifre, ce trebuie sa se divida cu 2 n , se divid cu 2n-1; ele se pot
scrie sub forma c*10(n-1)+M=c*2n-1*5n-1+M= Multiplu(2n-1)+M; inseamna ca M (cele n-1 cifre ramase)
trebuie sa se divida cu 2n-1; inseamna ca M este unul din numerele gasite ca solutie la pasul n-1.
Daca exista o singura solutie M pt.cazul n-1 (M se divide cu 2n-1) acest nr.se poate scrie M=2(n-1)*par
sau 2(n-1)*impar, rezulta ca M mod 2n=0 sau M mod 2n=2(n-1). Deci,in cazul a n cifre din cele doua
posibilitati (1M sau 2M) se va alege astfel unica solutie:
daca M mod 2n=0 atunci solutia este 2M=2*10(n-1)+M=Multiplu(2n)
daca M mod 2n=2(n-1) atunci solutia este 1M=10(n-1)+M=2(n-1)*5(n1)+M=Multiplu(2n)!
Solutia propusa este una iterativa i face maximum n pai !

Program 1_2_si_2_la_n;
Var
nr,zece_la_n:longint;
n,i:byte;
BEGIN
Writeln('Se citeste n. Sa se afiseze toate numerele de n cifre,');
Writeln('formate numai cu cifrele 1 si 2, si divizibile cu 2^n.');
Write('Introduceti n (max.10):');Readln(n);
nr:=2;zece_la_n:=1;
For i:=2 to n do begin
zece_la_n:=10*zece_la_n;
If nr mod (1 shl i)=0 then nr:=2*zece_la_n+nr
else nr:=zece_la_n+nr;
end;
Writeln('Solutia este:',nr);
readln;
END.

73
Se citete n. S se determine o alegere a semnelor + i - astfel nct s avem relaia 12...n=0.

Analiza problemei elaborarea algoritmului:


Problema a fost dat la olimpiada colar de informatic. Daca se incearca o abordare "in forta" si "la
prima mina" vor trebui verificate 2n posibilitati de asezare a semnelor + si -. Adica se obtine un
algoritm exponential, total ineficient. Soluia "elegant" ce rezult printr-o analiz mai aprofundat:
-mai intai se va imparti suma in doua parti: cea cu plus si cea cu minus.
Privindu-se atent se observa ca se pot deosebi trei cazuri:
1. cind avem intre cele n numere un numar impar de numere impare (de ex.n=3,5,6...) caz in care
numerele impare nu pot fi repartizate in cele doua parti (plus si minus) decit astfel: un nr.par de numere
impare intr-o parte si un nr.impar de nr impare in cealalta; implica ca cele doua parti au paritati diferite,
deci suma lor nu poate fi 0 !
Acest caz apare cind n=4k+1, 4k+2.
2. cind n=4k atunci numerele de la 1 la n pot fi grupate cite patru astfel:
1-2-3+4, ..., (4i+1)-(4i+2)-(4i+3)+(4i+4), ... si vor avea suma 0 pe fiecare grupa de patru !
3. altfel, n=4k+3, putem grupa numerele asemanator ca la cazul dinainte cu exceptia primei grupe: -1-
2+3, 4-5-6+7, ..., (4i)-(4i+1)-(4i+2)+(4i+3),...reazultind din nou suma 0 pe fiecare grupa !

Program Plus_Minus;
Var
n,i,c:byte;
BEGIN
Writeln('Se citeste n. Sa se determine o alegere a semnelor + si - ');
Writeln('astfel incit sa avem relatia 12...n=0.');
Write('n:');Readln(n);
c:=n mod 4;
case c of
1,2: Writeln('Nu exista solutie.');
0: For i:=1 to n div 4 do
write('+',4*(i-1)+1,'-',4*(i-1)+2,'-',4*(i-1)+3,'+',4*(i-1)+4);
3:begin
Write('-1-2+3');
For i:=1 to n div 4 do
write('+',4*i,'-',4*i+1,'-',4*i+2,'+',4*i+3);
end;
end;
Readln;
END.

74
Elemente de programare a PC - urilor

Oferim n continuare cteva exemple de programe, unele n Pascal, altele n C, pentru a


permite celor pasionai s-i nsueasc cunotinele minimale de programare a PC-urilor: lucrul cu
tastatura, accesul direct la memorie, lucrul n modul grafic, etc. Pentru cei ce doresc s aprofundeze
acest subiect sau doresc ct mai multe detalii le recomandm, pe lng citirea atent a help-ului Turbo
Pascal-ului sau a Turbo C-ului, folosirea utilitarului TechHelp specializat n descrierea programrii
PC-urilor.
Ideea care ar defini cel mai bine acest tip de cunotine de programare este coninut n
cunoscuta expresie : "Secrete mici, efecte mari !".

// Un simplu program muzical

#include <stdio.h>
#include <dos.h>
#include <conio.h>
main(){ /* Do do# Re re# Mi Fa fa# sOl sol# La la# Si */
int octava[]={65 , 69 , 73 , 78 , 82 , 87 , 92 , 98 , 104 , 110 , 116 , 123};
int i,j,nr_octava,i_nota,timp=500;
float masura,durata,durata_masura;
char *linia="42$2R2R4M4F2O2L1R2R2S2S4L4O2O2"; //$4D2D4$3S4L2";

do{
masura=(float)(linia[0]-'0')/(linia[1]-'0');durata_masura=0;
for(i=2;linia[i]!='\0';i++){
if (i%2==0){
switch(linia[i]){
case '$' : {nr_octava=1;for(j=linia[++i]-'0';j>0;j--)nr_octava*=2;}
break;
case 'D' : i_nota=0;break;
case 'd' : i_nota=1;break;
case 'R' : i_nota=2;break;
case 'r' : i_nota=3;break;
case 'M' : i_nota=4;break;
case 'F' : i_nota=5;break;
case 'f' : i_nota=6;break;
case 'O' : i_nota=7;break;
case 'o' : i_nota=8;break;
case 'L' : i_nota=9;break;
case 'l' : i_nota=10;break;
case 'S' : i_nota=11;break;
}
} else {
if (linia[i]=='6') durata=1/16; else durata=1/(float)(linia[i]-'0');
durata_masura+=durata;
if (durata_masura>masura) { nosound();durata_masura=0;}
sound(nr_octava*octava[i_nota]);
delay(durata*timp);
} /* else */
} /* for */
} /* do */
while (!kbhit());
nosound();
}

Program Citite_Taste;
uses crt;
var c:char;

75
shift:byte absolute $40:$17; { adresa octetului de stare a tastaturii }
begin
repeat
c:=readkey;
if (shift and $3>0) then
write(' shift ',c,':',Ord(c))
else write(' ',c,':',Ord(c));
until c=#27;
end.

// Program C pt. afisarea Tabelului codurilor ASCII;

#include <stdio.h>

void main(){
unsigned short c;
for(c=0;c<=255;c++)
switch(c){
case 7 : printf("b%3u",c);break; // beep
case 8 : printf("B%3u",c);break; // back space
case 9 : printf("T%3u",c);break; // tab
case 10 : printf("L%3u",c);break; // line feed
case 13 : printf("R%3u",c);break; // return
case 27 : printf("E%3u",c);break; // escape
default : printf("%c%3u",c,c); // caractere afisabile
};
}

Program Tenis;
{ Joc demonstrativ al posibilitatilor de folosire a accesului direct
la memoria ecran. Paletele sint actionate de tastele 'A' si 'W', respectiv
'sageata sus' si 'sageata jos'. }
Uses Crt;
Const viteza=1500;
Type Ecran=Record
car:char;
atrib:byte;
End;
Var
scr:array[1..25,1..80] of Ecran absolute $b800:$0; { Adresa de memoriei ecran in mod text }
x,y,x0,y0:byte;
i,d,s:integer;
u:real;
ok:boolean;
tasta:char;
yP1:array[1..5]of byte;
yP2:array[1..5]of byte;
uP:array[1..5]of real;

Procedure Paleta1(tip:char);
Begin {generare paleta 1}
for i:=1 to 5 do
scr[yP1[i],76].car:=tip;
end;
Procedure Paleta2(tip:char);
Begin {generare paleta 2}
for i:=1 to 5 do
scr[yP2[i],5].car:=tip;

76
End;
Procedure Mutapaleta1;
Begin
Paleta1(' ');
if (tasta=#80) and (yP1[i]<24) then {miscarea paletei 1}
for i:=1 to 5 do Inc(yP1[i]);
if (tasta=#72) and (yP1[i]>6) then
for i:=1 to 5 do Dec(yP1[i]);
End;
Procedure Mutapaleta2;
Begin
Paleta2(' '); {miscarea paletei 2}
if (tasta=#122) and (yP2[i]<24) then
for i:=1 to 5 do Inc(yP2[i]);
if (tasta=#119) and (yP2[i]>6) then
for i:=1 to 5 do Dec(yP2[i]);
End;
procedure cantec; {genereaza cantecul final}
begin sound(400);delay(800);
sound(500);delay(800);
sound(600);delay(800);
sound(650);delay(800);
sound(600);delay(800);
sound(700);delay(800);
sound(650);delay(1000);
end;
Begin {program principal-generare cadru}
Clrscr;
d:=0;s:=0;
{ writeln('________ ________ _______ ______ ________ ');
write(char(179),' ',char(179),' ',char(179),' ');
writeln(char(179),' ',char(179));
readln;}
clrscr;
For x:=1 to 80 do begin
scr[1,x].car :=#219;
scr[25,x].car:=#219;
end;
For y:=2 to 9 do begin {poarta}
scr[y,1].car :=#219;
scr[y,80].car:=#219;
end;
For y:=17 to 24 do begin
scr[y,1].car :=#219;
scr[y,80].car:=#219;
end;
x0:=40;
y0:=13;
u:=20*PI/180; {initializare miscare minge}
x:=x0;
y:=y0;
for i:=1 to 5 do begin
yP1[i]:=10+i;
yP2[i]:=10+i;
uP[i]:=(i/3*PI-PI)/15; {unghiul de dispersie a paletei}
end;
tasta:=' ';
repeat {miscare minge}
if ((u>=0) and (u<PI/2) or (u > 3*PI/2) and (u<2*PI)) then inc(x)
else dec(x);

77
y:=y0+Trunc(Abs(x-x0) * Sin(u)/Cos(u));
if scr[y,x].car<>' ' then begin
if (y=1)or(y=25) then begin {ciocniri}
u:=2*PI-u;x0:=x;
if y=1 then y0:=2 else y0:=24;
end; {-de pereti}
if (x=1)or(x=80) then begin
u:=PI+u;if u>2*Pi then u:=u-2*PI;
y0:=y;
if x=1 then x0:=2 else x0:=79;
end;
if x=76 then begin {-de palete}
for i:=1 to 5 do
if y=yP1[i] then begin
sound(1000);
u:=PI+u+uP[i];
if u>2*Pi then u:=u-2*PI;
x0:=x;y0:=y;
end;
nosound;
end;
if x=5 then begin {-de palete}
for i:=1 to 5 do
if y=yP2[i] then begin
sound(600);
u:=PI+u+uP[i];
if u>2*Pi then u:=u-2*PI;
x0:=x;y0:=y;
end;
nosound;
end;
end
else if not (((x=1)or(x=80)) and((y<17)and(y>8))) then
begin {gol}
scr[y,x].car:='0';
i:=1;
ok:=false;
repeat
ok:=keypressed;
inc(i);
until (i=viteza)or ok;
if ok then begin
tasta:=readkey;
if tasta = #0 then tasta:=readkey;
mutapaleta1;
mutapaleta2;
end;
Paleta1(#219);
Paleta2(#219);
scr[y,x].car:=' ';
scr[y,x].car:=' ';
end
else begin
sound(800);
if (x>=80)and(y>9)and(y<17) then d:=d+1;
if (x<=1)and(y>9)and(y<17) then s:=s+1;
textcolor(2);
textbackground(7);
gotoxy(39,2);
write('SCOR');

78
gotoxy(38,3);
write(' ',d,' : ',s);
if (d=5)or(s=5) then begin
gotoxy(35,10);
write(' G A M E O V E R ');
cantec; nosound;
halt;
end;
delay(1500);
paleta1(' ');
paleta2(' ');
x0:=40;
y0:=13;
u:=20*PI/180; {reinitializare miscare minge}
x:=x0;
y:=y0;
for i:=1 to 5 do begin
yP1[i]:=10+i;
yP2[i]:=10+i;
uP[i]:=(i/3*PI-PI)/5;
end;
tasta:=' ';
nosound;
end;
until tasta=#27;
End.

Program Biliard; { demonstrativ pentru folosirea modului grafic }


uses Graph,Crt;
Const nr_obiecte=10;
raza=25;
pasx=3;pasy=2;
viteza=10; { de la 0 la 10 }
var
grDriver,grMode,ErrCode: Integer;
i,xMax,yMax,xtmp,ytmp:word;
x,y:Array[1..nr_obiecte] of word;
sensx,sensy:Array[1..nr_obiecte] of shortint;

Procedure Deseneaza(x,y,color:word);
Const bucati=12;
Var x1,y1,unghi,Xasp,Yasp:word;
Begin
SetWriteMode(XORPut);SetColor(color);
GetAspectRatio(Xasp, Yasp);
unghi:=0;
x1:=x+Trunc(raza*cos(unghi*2*PI/bucati));
y1:=y+Trunc(raza*sin(unghi*2*PI/bucati)*Xasp/Yasp);
For unghi:=1 to bucati do begin
xtmp:=x+Trunc(raza*cos(unghi*2*PI/bucati));
ytmp:=y+Trunc(raza*sin(unghi*2*PI/bucati)*Xasp/Yasp);
Line(x1,y1,xtmp,ytmp);Line(x,y,x1,y1);
x1:=xtmp;y1:=ytmp;
end;
End;

begin
grDriver := Detect;
InitGraph(grDriver, grMode,'');

79
ErrCode := GraphResult;
if ErrCode = grOk then
begin { Do graphics }
xMax:=GetMaxX;yMax:=GetMaxY;
Rectangle(0,0,xMax,yMax);
Randomize;
For i:=1 to nr_obiecte do begin
x[i]:=raza+Random(xMax-2*raza);y[i]:=raza+Random(yMax-2*raza);
sensx[i]:=-1+(i mod 2)*2;sensy[i]:=-sensx[i];
Deseneaza(x[i],y[i],i);
end;
Repeat
For i:=1 to nr_obiecte do begin
Deseneaza(x[i],y[i],i);
xtmp:=x[i]+pasx*sensx[i];ytmp:=y[i]+pasy*sensy[i];
If (xtmp>raza) and (xtmp<xMax-raza) then x[i]:=xtmp
else sensx[i]:=-sensx[i];
If (ytmp>raza) and (ytmp<yMax-raza) then y[i]:=ytmp
else sensy[i]:=-sensy[i];
Deseneaza(x[i],y[i],i);
Delay(100-10*viteza);
end;
Until KeyPressed;
Readln;
CloseGraph;
end
else
Writeln('Graphics error:', GraphErrorMsg(ErrCode));
end.

// Program C de umplere a ecranului text prin acces direct la memoria ecran


#include <dos.h>
#include <conio.h>

struct scrcar{
unsigned char car,atrib;
} far *ecran;

int lin,col;
int culoare=BLUE,fundal=LIGHTGRAY;

void main(void){
ecran=(struct scrcar far *)MK_FP(0xb800,0);
for(lin=0;lin<25;lin++)
for(col=0;col<80;col++) {
ecran[lin*80+col].car='*';
ecran[lin*80+col].atrib=fundal*16+culoare;
}
getch();
}

Program Acces_direct_ecran_grafic320_200;
{ Fiecare jumatate de ecran se genereaza din cealalta jumatate
pe baza proprietatilor automatelor celulare asemanator ca in jocul Life }
Uses crt;
Const maxl=200-1;
maxc=320-1;

80
mijl=maxc div 2;
Type Matrice=array[0..maxl,0..maxc] of byte;
var
scr:Matrice absolute $A000:0; { adresa memoriei ecran in modul grafic 320x200 }
i,j,k,l,c,x:integer;
ok:char;
BEGIN
asm {initializeaza in mod grafic 320x200x250 NU in 640x400x256}
mov ah,0
mov al,13h
int 10h;
end;
randomize;x:=random(maxc);
for k:=1 to 2 do
for i:=0 to maxl do
for j:=0 to mijl do
scr[i,j+k*mijl]:=random(maxc) ;
k:=0;
repeat
repeat
for i:=0 to maxl do
for j:=0 to mijl do begin
l:=i;c:=j+k*mijl;
if (scr[(l-1)mod maxl,c]<scr[l,c])and
(scr[l,(c-1)mod mijl]<scr[l,c]) then
scr[i,j+((k+1)mod 2)*mijl]:=(scr[(l-1)mod maxl,c]+scr[l,(c-1)mod mijl]+ x)div 3-1
else if (scr[l,(c+1)mod mijl]>scr[l,c])and
(scr[(l+1)mod maxl,c]>scr[l,c]) then
scr[i,j+((k+1)mod 2)*mijl]:=(scr[(l+1)mod maxl,c]+scr[l,(c+1)mod mijl]+ x) div 3+1
else scr[i,j+((k+1)mod 2)*mijl]:=scr[l,c]+1;
end;
k:=(k+1) mod 2;
until keypressed;
ok:=readkey;x:=random(maxc);
if ok<>#27 then ok:=readkey;
until ok=#27;
{readln;}
asm {inchide modul grafic}
mov ax,0
int 10h
end;
END.

Program Mouse; { Gestionarea mouse-ului prin apelul intreruperii de sistem $33 }


uses Crt,Graph,Dos;
var
grDriver,grMode,ErrCode : Integer;
mfunc,buton,mx,my,xf,yf,x,y:word;
xi,yi:integer;
s1,s2,s3:string[5];
P : pointer;
Size : Word;

{ Intr $33, nr.fctiei dorite in AX:


00 mouse reset
01 cuplare cursor mouse (vizibil)
02 decuplare cursor mouse(ascuns)
03 determ.unei apasari pe tasta si semnalare pozitie
04 pozitionarea cursorului de mouse

81
05 inform.suplim.despre apasarea tastelor
06 inreg.tastelor de mouse eliberate
07 stabilire domeniu orizontal(minim si maxim)
08 - || - - || -vertical - || - - || -
09 selectare cursor grafic
10 selectare cursor text
13/14 emulare creion optic conectat/deconectat
15 stabilire sensibilitate mouse
29 fixarea paginii ecran in care mouse-ul e vizibil
30 afisarea - || - - || - - || - - || -

procedure MouseReg;
var reg:registers;
begin
reg.ax:=mfunc;reg.bx:=buton;reg.cx:=mx;reg.dx:=my;
intr($33,reg);
mfunc:=reg.ax;buton:=reg.bx;mx:=reg.cx;my:=reg.dx;
end;
}
procedure MouseAsm;ASSEMBLER;
ASM
MOV AX,mfunc
MOV BX,buton
MOV CX,mx
MOV DX,my
INT $33
MOV mfunc,AX
MOV buton,BX
MOV mx,CX
MOV my,DX
end;

Begin
grDriver := Detect;
InitGraph(grDriver,grMode,'');
ErrCode := GraphResult;
if ErrCode = grOk then
begin
if mem[memW[0:$cc+2]:memW[0:$cc]]=$cf then
begin
outtext('Mouse-ul nu este instalat!');
readln;closegraph;halt;
end;
mfunc:=0;mouseasm; {initializare}
mfunc:=1;mouseasm; {vizibil}
mfunc:=3;
mouseasm;xi:=mx;yi:=my;
setactivepage(1);
rectangle(xi,yi,mx,my);
Size := ImageSize(xi,yi,mx,my);
GetMem(P, Size); { Get memory from heap }
GetImage(xi,yi,mx,my,P^);
putimage(xi,yi,P^,XORput);
setactivepage(0);
PutImage(100, 100, P^, ORPut);
repeat
mouseasm;
xi:=mx;yi:=my;
while buton=1 do
begin

82
PutImage(100, 100, P^,XORPut);
mouseasm;
setactivepage(1);
rectangle(xi,yi,mx,my);
Size := ImageSize(xi,yi,mx,my);
GetMem(P, Size); { Get memory from heap }
GetImage(xi,yi,mx,my,P^);
putimage(xi,yi,P^,XORput);
setactivepage(0);
PutImage(100, 100, P^, ORPut);
end;
until keypressed;
mfunc:=2;mouseasm; { decuplare mouse }
CloseGraph;
end
else
WriteLn('Graphics error:',GraphErrorMsg(ErrCode));
end.

// Program C de generare a efectului grafic-plasma-prin utilizarea unor functii ale modului grafic
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>

int MX,MY;
int p1,p2,p3,p4,r1,r2,r3,r4;

void plasma(int x1,int x2,int y1,int y2){


if(x2-x1<2) return;
p1=getpixel(x1,y1);
p2=getpixel(x2,y1);
p3=getpixel(x2,y2);
p4=getpixel(x1,y2);
r1=random(4);
r2=random(4);
r3=random(4);
r4=random(4);
if (getpixel(x1+(x2-x1)/2,y1)==0) putpixel(x1+(x2-x1)/2,y1,(p1+p2)/2+r1);
if (getpixel(x2,y1+(y2-y1)/2)==0) putpixel(x2,y1+(y2-y1)/2,(p2+p3)/2+r2);
if (getpixel(x1+(x2-x1)/2,y2)==0) putpixel(x1+(x2-x1)/2,y2,(p3+p4)/2+r3);
if (getpixel(x1,y1+(y2-y1)/2)==0) putpixel(x1,y1+(y2-y1)/2,(p4+p1)/2+r4);
putpixel(x1+(x2-x1)/2,y1+(y2-y1)/2,(p1+p2+p3+p4)/4+random(2));
plasma(x1,x1+(x2-x1)/2,y1,y1+(y2-y1)/2);
plasma(x1+(x2-x1)/2,x2,y1,y1+(y2-y1)/2);
plasma(x1,x1+(x2-x1)/2,y1+(y2-y1)/2,y2);
plasma(x1+(x2-x1)/2,x2,y1+(y2-y1)/2,y2);
}

int gdriver = VGA, gmode = VGAHI, errorcode,i;


double red=20,green=30,blue=40;

struct palettetype pal;

void main(void){
/* select a driver and mode that supports the use */
/* of the setrgbpalette function. */

83
/* initialize graphics and local variables */
initgraph(&gdriver, &gmode, "");

/* read result of initialization */


errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* terminate with an error code */
}

/* grab a copy of the palette */


getpalette(&pal);

for (i=0; i<pal.size; i++)


setrgbpalette(pal.colors[i], red+i, green+i, blue+i);

randomize();
MX=getmaxx();MY=getmaxy();
putpixel(0,0,MAXCOLORS/2);
putpixel(0,MY,MAXCOLORS/2);
putpixel(MX,0,MAXCOLORS/2);
putpixel(MX,MY,MAXCOLORS/2);
plasma(0,MX,0,MY);
// rotate palette
while(!kbhit()){
for(i=0;i<pal.size;i++)
setrgbpalette(pal.colors[i],(int) red+i, (int) green+i, (int) blue+i);
red+=0.5; green+=1; blue+=1.5;
}
closegraph();
}

Program Sarpe;
{ Program de joc demonstrativ: "Sarpele" culegator de numere. El este dirijat
cu ajutorul sagetilor, viteza sa de miscare poate fi modificata corespunzator
in orice moment folosind tastele de la 1 la 9. }
Uses Crt;
Const
sc=#219;
lungmax=95;
maxnext=10;
xlimit=[1,80];
ylimit=[1,25];
Var
sx,sy:array[1..95] of byte;
c:char;
i,primul,ultimul,next,tdelay,idelay:integer;
xnext,ynext:byte;
Begin
clrscr;
randomize;
for i:=1 to 79 do begin gotoxy(i,1);write(sc);gotoxy(i,25);write(sc);end;
for i:=1 to 24 do begin gotoxy(1,i);write(sc);gotoxy(80,i);write(sc);end;
primul:=2;ultimul:=1;

84
for i:=primul downto ultimul do begin sx[i]:=40;sy[i]:=13;end;
next:=0;idelay:=100;
for i:=primul downto ultimul do begin
gotoxy(sx[i],sy[i]);write(sc);
end;
c:=readkey;
while next<maxnext do
begin
xnext:=2+random(78);ynext:=2+random(23);
inc(next);gotoxy(xnext,ynext);write(next);
repeat
if keypressed then begin
c:=readkey;tdelay:=idelay;
if c=#0 then c:=readkey;
end
else tdelay:=tdelay*97 div 100;
case c of
'1'..'9':
idelay:=100+100 div (ord(c)-ord('1')+1);
#75: { stinga }
begin
gotoxy(sx[ultimul],sy[ultimul]);write(' ');
if primul=lungmax then begin
sx[1]:=sx[primul]-1;sy[1]:=sy[primul];
primul:=1
end
else begin
inc(primul);
sx[primul]:=sx[primul-1]-1;sy[primul]:=sy[primul-1];
end;
if ultimul=lungmax then ultimul:=1
else inc(ultimul);
end;
#77: { dreapta }
begin
gotoxy(sx[ultimul],sy[ultimul]);write(' ');
if primul=lungmax then begin
sx[1]:=sx[primul]+1;sy[1]:=sy[primul];
primul:=1
end
else begin
inc(primul);
sx[primul]:=sx[primul-1]+1;sy[primul]:=sy[primul-1];
end;
if ultimul=lungmax then ultimul:=1
else inc(ultimul);
end;
#72: { sus }
begin
gotoxy(sx[ultimul],sy[ultimul]);write(' ');
if primul=lungmax then begin
sx[1]:=sx[primul];sy[1]:=sy[primul]-1;
primul:=1
end
else begin
inc(primul);
sx[primul]:=sx[primul-1];sy[primul]:=sy[primul-1]-1;
end;
if ultimul=lungmax then ultimul:=1
else inc(ultimul);

85
end;
#80: { jos }
begin
gotoxy(sx[ultimul],sy[ultimul]);write(' ');
if primul=lungmax then begin
sx[1]:=sx[primul];sy[1]:=sy[primul]+1;
primul:=1
end
else begin
inc(primul);
sx[primul]:=sx[primul-1];sy[primul]:=sy[primul-1]+1;
end;
if ultimul=lungmax then ultimul:=1
else inc(ultimul);
end;
end;
if primul > ultimul then
for i:=primul downto ultimul do begin
gotoxy(sx[i],sy[i]);write(sc);
if (sx[primul]=sx[i]) and (sy[primul]=sy[i]) and (i<>primul) then
c:=#27;
end
else
begin
for i:=ultimul to lungmax do begin
gotoxy(sx[i],sy[i]);write(sc);
if (sx[primul]=sx[i]) and (sy[primul]=sy[i]) and (i<>primul) then
c:=#27;
end;
for i:=1 to primul do begin
gotoxy(sx[i],sy[i]);write(sc);
if (sx[primul]=sx[i]) and (sy[primul]=sy[i]) and (i<>primul) then
c:=#27;
end;
end;
if (sx[primul] in xlimit)or(sy[primul] in ylimit) then c:=#27;
delay(tdelay);
until (c=#27) or ((sx[primul]=xnext)and(sy[primul]=ynext));
sound(next*30);
if c=#27 then next:=maxnext
else
if ultimul-next <= 0 then begin
for i:=lungmax+ultimul-next to lungmax do begin
sx[i]:=sx[ultimul];sy[i]:=sy[ultimul];
end;
for i:=1 to ultimul do begin
sx[i]:=sx[ultimul];sy[i]:=sy[ultimul];
end;
ultimul:=lungmax+ultimul-next;
end
else begin
for i:=ultimul-next to ultimul do begin
sx[i]:=sx[ultimul];sy[i]:=sy[ultimul];
end;
ultimul:=ultimul-next;
end;
delay(tdelay);
nosound;
end; { next < maxnext}
End.

86
Program Scan_Taste;
{ Program ce demonstreaza posibilitatea de acces la codurile de scanare
ale tastaturii. Este indicat sa fie lansat in mod DOS si nu de sub Windows. }
Uses Crt,Dos;
Var
tasta:byte;
KbdIntVec:procedure;
{$F+}
Procedure KeyClick; interrupt;
begin
Port[$20]:=$20; { resetarea portului de acces al tastaturii }
end;

Begin
GetIntVec($9,@KbdIntVec); { modificarea intreruperii de tastatura }
SetIntVec($9,Addr(KeyClick)); { cu o procedura proprie "inofensiva" }
tasta:=0;
repeat
repeat until tasta<>Port[$60];
tasta:=Port[$60];
gotoxy(20,2);write(tasta:3);
until tasta=129;
SetIntVec($9,@KbdIntVec);
End.

Program Taste_muzicale_V2;
{ Program demonstrativ de folosire muzicala a tastaturii pe post de "orga".
Pentru o mai buna intelegere este utila consultarea programului scantast.pas }
Uses Crt,Dos;
Const
Nota_Do:array[1..4] of integer=(33,66,132,264);
Raport:array[1..10]of real=(24/24,27/24,30/24,32/24,36/24,40/24,45/24,
48/24,51/24,54/24);
Nota:array[1..10]of string[3]=('Do','Re','Mi','Fa','Sol','La','Si',
'Do','Re','Mi');
CodT:array[1..4]of byte=(44,30,16,2);

Type Pixel=Record
atrib:byte;
car:char;
end;
Var
tasta:byte;i:integer;
KbdIntVec:procedure;
ecran:array[1..25,1..80]of Pixel absolute $b800:0000;
{$F+}
Procedure KeyClick; interrupt;
begin
Port[$20]:=$20;
end;
Begin
ClrScr;
GetIntVec($9,@KbdIntVec);
SetIntVec($9,Addr(KeyClick));
tasta:=0;
repeat
repeat until tasta<>Port[$60];

87
tasta:=Port[$60];
if (tasta>=CodT[1])and(tasta<CodT[1]+10) then
begin
gotoxy(5*(tasta+1-CodT[1]),24);write(Nota[tasta+1-CodT[1]]);
sound( Trunc( Raport[ tasta+1-CodT[1] ] * Nota_Do[1] ) )
end
else
if (tasta>=CodT[2])and(tasta<CodT[2]+10) then
begin
gotoxy(5*(tasta+1-CodT[2]),22);write(Nota[tasta+1-CodT[2]]);
sound( Trunc( Raport[ tasta+1-CodT[2] ] * Nota_Do[2] ) )
end
else
if (tasta>=CodT[3])and(tasta<CodT[3]+10) then
begin
gotoxy(5*(tasta+1-CodT[3]),20);write(Nota[tasta+1-CodT[3]]);
sound( Trunc( Raport[ tasta+1-CodT[3] ] * Nota_Do[3] ) )
end
else
if (tasta>=CodT[4])and(tasta<CodT[4]+10) then
begin
gotoxy(5*(tasta+1-CodT[4]),18);write(Nota[tasta+1-CodT[4]]);
sound( Trunc( Raport[ tasta+1-CodT[4] ] * Nota_Do[4] ) )
end
else nosound;
until tasta=129;
SetIntVec($9,@KbdIntVec);
End.

Program Testare_VESA;

{ Program de testare a posibilitatilor de lucru a placii grafice in


standardul VESA. }
uses dos;
type tmoduri=array[1..256] of word;

var imod,vseg,x,y:word; cbank,c:longint; rg:registers;


ntbanks:longint; opt:char;
vesabuf:record sign:longint; vers:word; oem:pchar;
capab:longint; list:^tmoduri;
reserv:array[1..512] of byte end;
vesamod:record attr:word; wina,winb:byte;
gran,winsiz,sega,segb:word; pagfun:pointer;
bytes,width,height:word;
charw,charh,planes,bits,nbanks,model,sbank,
nrimpg,reservb,rms,rfp,gms,gfs,bms,bfs:byte;
reserv:array[1..512] of byte end;

function hexa(v:word):string;
const s:string[16]='0123456789abcdef';
function hexb(b:byte):string;
begin
hexb:=s[b div 16+1]+s[b mod 16+1];
end;
begin
hexa:=hexb(hi(v))+hexb(lo(v));
end;

procedure setbank(b:longint);

88
begin
vseg:=$a000;
if b<>cbank then with rg,vesamod do begin
cbank:=b; ax:=$4f05; bx:=0;
dx:=b*64 div gran; intr(16,rg);
end;
end;

procedure putpixel(x,y:word; cul:longint);


var l:longint; m,z:word;
begin
with rg,vesamod do case bits of
4: begin
l:=longint(bytes)*y+x div 8;
port[$3ce]:=3; port[$3cf]:=0;
port[$3ce]:=5; port[$3cf]:=2;
port[$3ce]:=8; port[$3cf]:=128 shr (x and 7);
setbank(l shr 16);
z:=mem[vseg:word(l)]; mem[vseg:word(l)]:=cul;
end;
8: begin
l:=longint(bytes)*y+x; setbank(l shr 16);
mem[vseg:word(l)]:=cul;
end;
15,16: begin
l:=longint(bytes)*y+x*2; setbank(l shr 16);
memw[vseg:word(l)]:=cul;
end;
24: begin
l:=longint(bytes)*y+x*3;
z:=word(l); m:=l shr 16; setbank(m);
if z<$fffe then move(cul,mem[vseg:z],3)
else begin
mem[vseg:z]:=lo(cul);
if z=$ffff then setbank(m+1);
mem[vseg:z+1]:=lo(cul shr 8);
if z=$fffe then setbank(m+1);
mem[vseg:z+2]:=cul shr 16;
end;
end;
end;
end;

begin
with rg, vesabuf, vesamod do begin
ax:=$4f00; es:=seg(vesabuf); di:=ofs(vesabuf);
sign:=$41534556; intr(16,rg);
if al<>$4f then begin
writeln('Standardul VESA nu e implementat');
exit end;
imod:=1;
while list^[imod]<>$ffff do begin
ax:=3; intr(16,rg); ax:=$4f01; cx:=list^[imod];
es:=seg(vesamod); di:=ofs(vesamod);
intr(16,rg);
if attr and 16<>0 then begin
writeln(oem,' VESA Versiune ',hi(vers),'.',lo(vers));
writeln(hexa(list^[imod]),
' Rezolutie: ',width,' x ',height,
' Culori: ',longint(1) shl bits);

89
write('Doriti testare (D/N)? '); readln(opt);
end else opt:='N';
if upcase(opt)='D' then begin
ax:=$4f02; bx:=list^[imod];
intr(16,rg); cbank:=-1;
ntbanks:=longint(bytes)*height div gran div 1024;
for x:=0 to ntbanks do begin
setbank(x); mem[$a000:$ffff]:=0;
fillchar(mem[$a000:0],$ffff,0);
end;
case bits of
4,8: c:=15;
15: c:=32767;
16: c:=65535;
24: c:=longint(1) shl 24-1;
end;
for x:=0 to width-1 do begin
putpixel(x,0,c); putpixel(x,height-1,c);
end;
for y:=0 to height-1 do begin
putpixel(0,y,c); putpixel(width-1,y,c);
end;
for x:=0 to 191 do for y:=0 to 191 do begin
case bits of
4: c:=(y div 48)*4+x div 48;
8: c:=(y div 12)*4+x div 12;
15,16: c:=(y div 6)*(1 shl rfp)+x div 6;
24: c:=longint(x)*65536+y;
end;
putpixel(x+4,y+4,c);
end;
readln;
end;
inc(imod);
end;
ax:=3; intr(16,rg);
end;
end.

90
Curioziti i trucuri de programare

Pentru o ct mai complet prezentare a programrii n C nu puteam evita prezentarea unor


curioziti i ale unor trucuri de programare C. Acelai lucru este valabil i pentru limbajul Pascal dar
este acesta este oarecum "ieit din mod". Numrul foarte mare de astfel de "invenii" a condus la
organizarea nc din 1984 a unui concurs internaional de programare numit foarte sugestiv The
International Obfuscated C Code Contest IOCCC adic Concursul internaional de programare
ofuscat C (nclcit i confuz). Participanii la acest concurs ofer n fiecare an adevrate perle de
programare C ce dovedesc, pe lng serioase cunotine de C, aptitudinile extraordinare i fiabilitatea
compilatorului C. Multe din capodoperele acestui concurs au fost apoi nscripionate pe tricouri sau
pungi, spre deliciul fanilor programrii C.
Aceast pasiune are totui i o latur serioas ce poate fi sesizat n programarea sub
platformele (sistemele de operare) gen Unix. n aceste sisteme toate programele circul nu numai sub
forma de cod executabil ci i n sursa original C. Ascunderea unor informaii despre programarea
sistem de ochii celor "periculos" de curioi este astfel dificil. Dar iat c acest tip de programare
"ofuscat" face acest lucru posibil ! Numai cei foarte pasionai i "prind urechile" n descifrarea unor
astfel de programe intenionat nclcite. Altfel spus, secretul unor astfel de programe se ascunde chiar n
rebusul din faa ochilor cititorului.
Recomandm acest capitol n special fanilor programrii C i celor foarte pasionai.

// Un simplu "Hello world!" dar care arata o surprinzatoare interpretare a compilatorului C

#include <stdio.h>
char a[]="Hello world!";
int i;
void main(void){
for(i=0;a[i]!='\0';i++)
putchar(i[a]); // !! a[i] <=> *(a+i) <=> *(i+a) <=> i[a] !!
}

// Iata unde conduce folosirea tipului de date float:


// c este foarte diferit de w ?!
// Putem spune ca acesta este un bug al C-ului ?

#include <stdio.h>
float a=12345679.,b=12345678.,
c=a*a-b*b,
u=a*a,v=b*b,w=u-v;
void main(){
printf("a=%f,b=%f\nc=%f,w=%f\n",a,b,c,w);
}

// Iata si varianta "corecta" in care nu se produce nici o trunchiere:

#include <stdio.h>
long double a=12345679.,b=12345678.,
c=a*a-b*b,
u=a*a,v=b*b,w=u-v;
void main(){
printf("a=%Lf,b=%Lf\nc=%Lf,w=%Lf\n",a,b,c,w);
}

91
// Acest program este capabil sa-si duplice identic la "iesire" codul sursa C fara a efectua nici o
// citire de nicaieri. Are deci caracteristica unui virus, se auto-replica !

#include <stdio.h>
char *s[]={
"#include <stdio.h>",
"char *s[]={",
"void main(void){",
"int i;char *ps;",
"puts(s[0]);puts(s[1]);",
"for(i=0;i<10;i++)",
" {putchar(34);for(ps=s[i];*ps;ps++)putchar(*ps);",
" putchar(34);putchar(',');putchar(10);}",
"putchar(34);for(ps=s[10];*ps;ps++)putchar(*ps);putchar(34);putchar(10);",
"putchar('}');putchar(';');putchar(10);",
"for(i=2;i<11;i++)puts(s[i]);putchar('}');"
};
void main(void){
int i;char *ps;
puts(s[0]);puts(s[1]);
for(i=0;i<10;i++)
{putchar(34);for(ps=s[i];*ps;ps++)putchar(*ps);
putchar(34);putchar(',');putchar(10);}
putchar(34);for(ps=s[10];*ps;ps++)putchar(*ps);putchar(34);putchar(10);
putchar('}');putchar(';');putchar(10);
for(i=2;i<11;i++)puts(s[i]);putchar('}');
}

// Program C surpriza (ales dintre cele de la IOCCC)


// Ce face acest program intr-o singura linie ?

int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hello, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---


j,i/i);}

// Alt program C surpriza (ales dintre cele de la IOCCC)


// Ce face acest program intr-o singura linie ?

main(v,c)char**c;{for(v[c++]="Hello, world!\n)";(!!c)[*c]&&(v--||--
c&&execlp(*c,*c,c[!!c]+!!c,!c));**c=!c)write(!!*c,*c,!!**c);}

// Puteti "decripta" acest program C de trei linii ? Executia lui arata clar ce face, intrebarea este
// insa cum face ?!

#define P(X)j=write(1,X,1)
#define C 39
int M[5000]={2},*u=M,N[5000],R=22,a[4],l[]={0,-1,C-1,-1},m[]={1,-C,-1,C},*b=N,
*d=N,c,e,f,g,i,j,k,s;main(){for(M[i=C*R-1]=24;f|d>=b;){c=M[g=i];i=e;for(s=f=0;
s<4;s++)if((k=m[s]+g)>=0&&k<C*R&&l[s]!=k%C&&(!M[k]||!j&&c>=16!=M[k]>=16))a[f++
]=s;if(f){f=M[e=m[s=a[rand()/(1+2147483647/f)]]+g];j=j<f?f:j;f+=c&-16*!j;M[g]=
c|1<<s;M[*d++=e]=f|1<<(s+2)%4;}else e=d>b++?b[-1]:e;}P(" ");for(s=C;--s;P("_")
)P(" ");for(;P("\n"),R--;P("|"))for(e=C;e--;P("_ "+(*u++/8)%2))P("| "+(*u/4)%2
);}

92
Confruntare de opinii: Informatic versus Matematic
Dei poate prea neobinuit pentru o culegere de probleme, am inut totui s introducem acest
capitol pentru "a-i pune n gard" pe nceptorii ntr-ale informaticii de capcana confruntrilor sterile,
pro informatic sau contra matematicii.
E bine ca ei s afle c dei informatica este studiat ca tiin de sine stttoare ea este totui
oficial considerat i clasificat ca o sub-disciplin a matematicii. Desigur, acest fapt zgndre orgoliul
unor "informaticieni pur-snge" care, nenelegnd c aceste clasificri snt pur formale, intr deseori n
confruntri aprinse de opinii cu matematicienii conservatori pe tema apartenenei teoriilor informatice
la matematic. Aceste sterile discuii n contradictoriu nu pot fi ns auzite n mediile cu adevrat
tiinifice, acolo unde se ntlnesc cei mai pasionai i mai profunzi cercettori ai ambelor discipline.
Putem rezuma opiniile contradictorii, pe care le-am auzit i noi deseori, sub forma
urmtoarelor dou ntrebri care formuleaz n dou moduri distincte aceeai dilem:
1. Se bazeaz informatica n ntregime pe matematic sau ea are o existen separat ?
2. Se poate "face" informatic fr s cunoti matematic foarte bine ?
nainte de a oferi rspuns, vom lmuri mai nti o alt confuzie ceea ce ne va permite s
rspundem mai uor la cele dou ntrebri: care este diferena dintre informatic i tiina
calculatoarelor (computer science) ?
Se tie c exist n facultile de la noi din ar dou (chiar trei) secii cu profil informatic:
secia de informatic la facultatea de tiine, secia de calculatoare la facultatea de inginerie i, mai
nou, secia de prelucrare electronic a informaiei economice (informatic economic) la facultatea de
tiine economice. Snt aceste secii esenial diferite ?
S vedem o opinie cu "greutate". Iat cuvintele academicianului Nicolae Teodorescu despre
informatic (am pus n eviden prin litere ngroate cuvintele ce ni s-au prut eseniale): Calculatorul
electronic are ns ca merit esenial stimularea unui mod de gndire care atepta de veacuri un mijloc
tehnic prodigios pentru a da minii omeneti putina hotrtoare de a-l introduce n strategiile
investigative de avangard. Acesta este modul de gndire algoritmic care permite sortarea, analiza i
prelucrarea unui numr mare de posibiliti, precum i alegerea celei sau celor mai potrivite care
conduc la rezultatul sau rezultatele urmrite, n studiul unor procese complexe care trebuie s fie
simplificate sau abandonate din lips de mijloace de cercetare. Pentru promovarea acestei gndiri,
calculatorul electronic nu era ns suficient el nsui, ci avea nevoie de o serie de discipline tiinifice
avnd ca baz gndirea algoritmic. Astfel, n puinii ani de la introducerea calculatorului electronic s-
au format discipline constituind o nou ramur a tiinei cu caractere mixte teoretice i tehnice, numit
la un moment informatic termen care a nlocuit pe cel iniial de tiin a calculului sau tiin a
calculatoarelor (computer science) , care avea un neles mai precis, dar n acelai timp mai restrns.
Vedem c, dintre cei toi termenii de specialitate ce se folosesc, cea mai larg accepiune o are
termenul de informatic. Ceilali termeni, cum snt tiina calculatoarelor i informatic economic, nu
fac dect s nuaneze i s particularizeze nelesul iniial mai general. tiina calculatoarelor abordeaz
informatica de pe poziii inginereti, ea primind un aport subtanial de la alte discipline inginereti ca
electronica, tiina prelucrrii semnalelor electrice sau tiina telecomunicaiilor. Informatica
economic utilizeaz noiuni cu caracter strict economic sau din domeniul tiinelor sociale. Putem
deduce c toate aceste nuanri i specializri au aprut din necesitate, datorit impactului deosebit pe
care utilizarea pe scar larg a calculatoarelor l are asupra sectoarelor societii.
Dac ns vom grupa disciplinele cu caracter informatic care se predau simultan la fiecare din
aceste secii diferite vom obine lista disciplinelor de baz ale informaticii: Bazele informaticii,
Programare, Structuri de date i algoritmi, Sisteme de operare, Baze de date. Alte discipline, cum snt
Arhitectura calculatoarelor, Reele de calculatoare, Ingineria programrii, Inteligena artificial,
Programarea orientat obiect, etc., snt considerate a fi discipline de specialitate n domeniu. De altfel,
datorit acestor diferenieri i specializri ntre secii, absolvenii seciilor respective se vor numi
programatori, ingineri de sistem sau economiti-informaticieni. S recunoatem c s-ar ajunge la o
adevrat "babilonie" dac nu numai matematicienii ci i inginerii sau economitii i-ar disputa cu
informaticienii "puri" ntietatea n domeniile informatice ce le revin !
Rmne s rspundem la ntrebarea iniial (formulat n dou variante): n ce msur se poate
face informatic fr matematic ? Privind lucrurile la fel de pragmatic ca i mai sus, dac privim
informatica ca pe o meserie (cu sub-specializrile ei) iar matematica tot ca pe o meserie, este evident c
nu este necesar s cunoti dou meserii pentru a o profesa bine pe una dintre ele. Deci, poi fi un bun
programator, inginer de sistem sau economist-informatician fr s ai cunotine serioase de
matematic. Trebuie ns s spunem, spre dezamgirea celor "lenei", c este exclus s fi lipsit de
cunotine de matematic pentru c atunci nu ai avea cum s-i nsueti cunotinele minimale pe care
le ofer disciplinele de baz ale informaticii nirate mai sus. Aceste discipline de baz fac apel la

93
modele i metode matematice considerate deja clasice i care snt privite ca i cultur matematic
indispensabil oricrui specialist n domeniu. Cum s-a ajuns la acest fapt, cum de gseti matematic n
economie i n inginerie, dar nu i invers ?
Este marele atu al matematicii: capacitatea de extragere a esenialului i capacitatea de
abstractizare (adic, capacitatea de modelare matematic). De altfel, este cunoscut faptul c
cunotinele matematice eseniale, indiferent de forma n care ele snt formalizate sau simbolizate, snt
aceleai pentru orice civilizaie terestr. Sau extraterestr ! Se tie c mesajele de pe sondele spaiale
americane, ce au prsit deja sistemul nostru solar, destinate unor posibile civilizaii extraterestre snt
"scrise" n limbaj matematic. S nu ne mai mirm atunci c "fr matematic nu se poate !".
Ca s nu cread cineva c facem pledoarie pentru matematic, aici ntr-o lucrare de
informatic, v facem cunoscut c, din contr, n cartea sa Vrsta de aur a matematicii, care prezint n
11 capitole cele mai mari realizri ale matematicii din ultimii 50 de ani, profesorul i cercettorul Keith
Devlin de la universitile Stanford i Pittsburgh a introdus un capitol cu titlul Eficiena algoritmilor i
n alte cinci capitole arat rolul important pe care l-a avut folosirea calculatorului n creterea eficienei
i validrii cercetrii pur matematice. Adic, ase din unsprezece capitole cer pentru a fi nelese bine
nu numai cunotine de matematc ci i de informatic. Iar unul din cele cinci capitole, Problema celor
patru culori, accentueaz rolul esenial (indispensabil) al programrii n demonstrarea cu ajutorul
calculatorului a uneia din cele mai celebre probleme de matematic. Aceast demonstraie a creat o
"bre" serioas n gndirea matematicienilor care au fost nevoii s ia foarte n serios "concurena" pe
care calculatorul (bine "dirijat" de programatori) a nceput s le-o fac. Iat chiar cuvintele profesorului
de matematic Keith Devlin scrise n ncheierea capitolului respectiv (ce explic modul n care s-a fcut
demonstraia cu calculatorul): "Matematica nu va mai fi niciodat aceeai." !
ncheiem cu convingerea c, cei care au parcurs cu interes aceast culegere, inclusiv acest
capitol, nu vor mai putea fi tentai de controverse "uoare" informatic versus matematic. Credem c
s-a putut vedea cum, cei care "snt deasupra" acestor discuii sterile, au sesizat cu nelepciune c
matematica - "mama informaticii" - se mbogete acum din plin prin intermediul informaticii,
"punndu-le astfel pe picior de egalitate" cele dou discipline.

Noi le urm tuturor celor studioi s-i concentreze toat energia pasiunii lor pentru nvarea
i stpnirea cu miestrie a "artei programrii". Ea poate fi considerat ca fiind prima treapt important
spre orizontul ctre care tinde tiina informaticii.

94
Bibliografie, adrese i locaii de interes pe Internet
Internetul e foarte mare, stufos i, de multe ori, labirintic. Tocmai de aceea, ne-am gndit s
venim n ajutorul celor foarte pasionai de informatic i de matematica aplicat n informatic. Oferim
n continuare doar cteva adrese pe care i noi le-am utilizat cu succes. Fiecare din aceste site-uri
conine la rndul lui liste de adrese i legturi (links) ctre alte site-uri cu subiecte asemntoare. Iat,
avei la dispoziie "un capt al ghemului" !

www.groups.dcs.st-and.ac.uk/~history/ - conine multe pagini interesante despre istoria


descoperirilor n matematic, utile celor care doresc s afle cum se face cu adevrat descoperiri n
matematic i cum s-a ajuns la necesitatea apariiei calculatoarelor
www.mathpages.com/KsBrown/ - conine o colecie impresionant de informaii, idei i
descoperiri de ultim or din matematic i informatic
www.mathsoft.com/asolve/ - conine o list substanial de probleme de matematic (i nu numai)
care i ateapt nc rezolvarea, multe dintre ele putnd fi abordate cu ajutorul calculatorului
www.ee.Surrey.ac.uk/Personal/R.Knott/Fibonacci/fib.html - este o "porti" de intrare n domeniul
fascinant al numerelor lui Fibonacci, cu multiple corelaii matematice i informatice
www.mans.cee.hw.ac.uk/ctl.html Computer Teaching and Learning Resources - numele site-ului
spune totul
www.k12tlc.net/Penrose/ K-12 Teaching & Learning Center - noi am ales pagina care prezint
biografia lui Sir Roger Penrose, dar avei nc multe altele la dispoziie
www.ioccc.org The International Obfuscated C Code Contest (IOCCC) Concursul internaional
de programare C ofuscat (nclcit i intenionat confuz)

Suplimentar, tot pentru cei foarte pasionai de matematic, informatic, de legtura dintre ele
i nu numai, oferim o selecie minimal de cri i articole care au constituit, direct sau indirect, o surs
de inspiraie n scrierea acestei culegeri:

Turbo Pascal 6.0. Ghid de utilizare, Microinformatica, Cluj-Napoca, 1992


Blnescu T. , Limbajul Turbo Pascal, Editura tehnic, Bucureti, 1992
Grigore Albeanu, Programarea n Pascal i Turbo Pascal. Culegere de probleme, Editura
tehnic, Bucureti, 1994
Tudor Sorin, Tehnici de programare, Editura L&S Infomat, Bucureti, 1998
Manual de programare C, (dup Kernigham i Ritchie) Microinformatica, Cluj-Napoca, 1986
Mulea I., Programarea n C, Microinformatica, Cluj-Napoca, 1992
Roger Penrose, Mintea noastrcea de toate zilele, (titlul original: Emperor's mind), Editura
tehnic, Bucureti, 2001
Roger Penrose, Incertitudinile raiunii. Umbrele minii, (titlul original: Shadows of the mind),
Editura tehnic, Bucureti, 2000
Keith Devlin, Vrsta de aur a matematicii, (titlul original: Matemathics: The New Golden Age),
Editura Thetha, Bucureti, 2000
Solomon Marcus, Gndirea algoritmic, Editura tehnic, Bucureti, 1982
L. Livovschi, H. Georgescu, Bazele informaticii, Editura didactic i pedagogic, Bucureti, 1981

95