Sunteți pe pagina 1din 124

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 .................................................................................................................. 10
PROBLEME DE LOGIC I JUDECAT ................................................................................................... 11
PROBLEME DE LOGIC I JUDECAT CU "TENT INFORMATIC" ......................................................... 14
NOIUNI FUNDAMENTALE DE PROGRAMARE ...................................................................... 16
1.CELE TREI ETAPE ALE REZOLVRII UNEI PROBLEME CU AJUTORUL CALCULATORULUI .................... 16
2.CUM SE STABILETE CORECTITUDINEA I EFICIENA SOLUIONRII ? .............................................. 16
3. NOIUNILE FUNDAMENTALE ALE PROGRAMRII: ALGORITM, LIMBAJE DE DESCRIERE A ALGORITMILOR, PROGRAM,
LIMBAJE DE PROGRAMARE .................................................................................................................. 18
3.1. Algoritmul ............................................................................................................................... 18
3.2. Descrierea algoritmilor .......................................................................................................... 19
3.3 Programul ................................................................................................................................ 21
4. SECRETUL NVRII RAPIDE A PROGRAMRII ................................................................................ 21
NOIUNI PRIMARE DE PROGRAMARE N PASCAL I C ...................................................... 23
EXEMPLE DE PROBLEME REZOLVATE .................................................................................................. 25
METODA PRACTIC DE NVARE CE GARANTEAZ REZULTATE IMEDIATE ........ 33
PROBLEME SELECIONATE - ENUNURI ................................................................................ 33
PROBLEME PROPUSE SPRE REZOLVARE (PROBLEME DE ANTRENAMENT) ............................................. 33
PROBLEME DE EXAMEN ....................................................................................................................... 36
PROBLEME DIFICILE ............................................................................................................................ 38
PROBLEME NESOLUIONATE NC ...................................................................................................... 40
PROBLEME INSOLVABILE ALGORITMIC ................................................................................................ 44
NOIUNI APROFUNDATE DE PROGRAMARE .......................................................................... 46
METODE I STRATEGII DE PROIECTARE A ALGORITMILOR (ALIAS TEHNICI DE PROGRAMARE) ............. 46
BACKTRACKING. ................................................................................................................................ 49
GREEDY. ............................................................................................................................................. 52
PROGRAMAREA DINAMIC. ................................................................................................................. 53
BRANCH & BOUND. ............................................................................................................................ 53
RECURSIVITATEA ................................................................................................................................ 54
PROBLEME REZOLVATE I EXERCIII DE PROGRAMARE ............................................... 62
PROBLEME ELEMENTARE. EXERCIII DE PROGRAMARE ...................................................................... 62
PROBLEME CE NECESIT BACK-TRACKING .......................................................................................... 89
PROBLEME CU SOLUIE SURPRINZTOARE .......................................................................................... 95
ELEMENTE DE PROGRAMARE A PC - URILOR ..................................................................................... 103
CURIOZITI I TRUCURI DE PROGRAMARE ....................................................................................... 119
CONFRUNTARE DE OPINII: INFORMATIC VERSUS MATEMATIC ............................ 122
BIBLIOGRAFIE, ADRESE I LOCAII DE INTERES PE INTERNET .................................. 124
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 !


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 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.

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.


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 i-e 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, 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



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 ?





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!





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
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
Na
R
Ra
T
Ta
T
Tn
N
Na
T
Ta

N
Nn
P
Pn
P
Pn

P
Pa
R
Rn
P
Pa

P
Pn
P
Pa
P
Pn
P
Pa
P
Pa
P
Pa
C
Ca
C
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 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
100 nabivonabivobinagevogenaduvogedunagevodunanabivobiduvogedu

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).

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
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).
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: ax
2
+bx+c=0,
se aplic cu succes pentru o mulime infinit de date de intrare: (a,b,c)e9\{0}x9x9.
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];

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)
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.


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 lipseasc}
{ Zona de declaraii constante, variabile,
proceduri i funcii }
BEGIN
{ Corpul programului format din instruciuni
terminate cu punct-vigul ; Corpul programului
poate fi privit ca o instruciune compus }
END.
(Orice se va scrie dup punct va fi ignorat de
ctre compilator)

// linii de incluziuni de fiiere header

// declaraii de variabile i funcii externe
(globale)

void main(void){
// declaraii de variabile locale

// corpul programului format din instruciuni
terminate cu punct-vigul ;
}

Exemplu :
Program Un_Simplu_Test;
Const e=2.68;
Var x:real;
BEGIN
x:=1./2+e*(1+e);
Writeln(Rezultatul este:,x);
END.

Exemplu :
#include <stdio.h>

int e=2.68;
float x;
void main(void){
x=1./2+e*(1+e);
printf(Rezultatul este %f:,x);
}
Atribuirea : var:=expresie;

Var i,j:integer;perimetrul:real;
..
j:=2000 div 15; { mprire ntreag
obligatorie }
i:=i+(j-1)*Sqr(2*j+1); { Sqr (Square) funcia
de ridicare la ptrat }
perimetrul:=2*PI*i; { PI constant real
implicit }
#include <math.h> // declar constanta M_PI
int i,j; float perimetrul;
..
j=2000 / 15; // mprire ntreag implicit !!
i+=(j-1)* (2*j+1)*(2*j+1); // n C avem
operatorul
// de adunare + nainte de egal = ; funcia
putere n
// C este pow(x,y)
perimetrul=2*M_PI*i;
Intrare/Ieire :
Citete var1, var2, var3, ;
Scrie var1, var2, var3, ;
Sau
Scrie expresia1, expresia2, expresia3,;

Var i,j:integer;perimetrul:real;
..
Readln(i,j); { citirea variabilelor i i j }
Perimetrul:=2*PI*i;
Writeln(Raza=,i:4,
Perimetrul=,perimetrul:6:2, Aria=,
PI*Sqr(i):6:2);
{ perimetrul si aria fiind valori reale, se afiseaza
cu descriptorul de format de afisare :6:2 pe 6
poziii de ecran cu rotunjit la 2 zecimale }
#include <math.h> // declar constanta M_PI
int i,j; float perimetrul;
..
scanf(%i %i,&i,&j); // %i %i este
descriptorul de format de citire, & este
operatorul de adresare
perimetrul=2*M_PI *i;
printf(Raza=%4i Perimetrul= %6.2f Aria=
%6.2f,i,perimetrul,M_PI*i*i); // %6.2f
descriptorul de format de afisare a unei valori
reale(flotante) pe 6 poziii rotunjit la 2
zecimale
Condiionala :
Dac <condiie_logic> atunci instruciune1 [altfel instruciune2];
Var i,j,suma:integer;
..
If i <= 2*j+1 then suma:=suma+i
int i,j,suma;
..
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;
..
suma:=0;i:=1;
Repeat
suma:=suma+i; i:=i+1;
Until i>100;
int i,j,suma;
..
suma=0;i=1;
do
suma+=i;
while (i++<100);
Ciclul de tipul Do-While:
Ct timp <condiie_logic> execut instruciune;
Var i,j,suma:integer;
..
suma:=0;i:=1;
While i<=100 do begin
suma:=suma+i; i:=i+1;
End;
int i,j,suma;
..
suma=0;i=1;
while (i++<100)
suma+=i;

Ciclul de tipul For (cu contor):
Pentru var_contor:=val_iniial pn la val_final execut instruciune;
Var i,j,suma:integer;
..
suma:=0;
For i:=1 to 100 do
Suma:=suma+i;
int i,j, suma;
..
for(suma=0,i=1;i<=100;i++)
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 ax
2
+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=(-b\delta)/(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);
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

#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 s \ 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;
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++;
}
printf("Vocale:%i, Consoane:%i, Alte car.:%i", vocale, consoane, i-vocale-consoane);
}
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,, pn.
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
1 2
1 2 3
..
1 2 3 n

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.

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.


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-1
k-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 i
2
+j
2
+k
2
=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
2
n
.
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
S
k
={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) 1eM R2) Dac xeM 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 A
k
.
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 x
3
+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
.
33. Se citete n, s se afieze binomul lui Newton generalizat: (x1+x2++xp)
n
=En!/(n1!n2!np!) x1
n
1x2
n
2xp
n
p
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. (Fn=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 a
n
pe baza relaiei a
n
=(a
k
)
2
pentru n=2k, i a
n
=a(a
k
)
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.

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)=c2
n
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 2
100
=(2
10
)
10
~(10
3
)
10
=10
30
, 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.

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 !
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=2
3
i 9=3
2
.

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

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
a
2
+b
2
, b
2
+c
2
, c
2
+a
2
i a
2
+b
2
+c
2
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 Ek>01/(k(k+1))=Ek>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).

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 x
2
+y
2
, (x-1)
2
+y
2
, x
2
+(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/2
3
+1/3
3
+1/4
3
+1/5
3
+ ?

Observaie: se cere s se spun ctre ce valoare converge seria Ek>01/k
3
sau Ek>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 t
2
/6, n cazul n
care n locul puterii a 3-ia punem puterea a 4-a seria converge la t
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 t) 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 a
5
+b
5
=c
5
+d
5
?

Observaie: Se cunoate c n cazul n care puterea este 3 avem soluia: 1
3
+12
3
=9
3
+10
3
iar n cazul n care
puterea este 4 avem soluia: 133
4
+134
4
=59
4
+158
4
.
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
x
n
+y
n
=z
n
nu admite soluie pentru n>2. Dar tot n aceeai perioad a descoperit i faptul c cea mai mic
soluie a ecuaiei diofantice x
2
- 109*y
2
= 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
2
13 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 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- 10
30
atunci orizontul ei de valabilitate este 10
30
. 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.
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 p
4
+q
4
+r
4
=s
4
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 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" c 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 .


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 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 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, 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)
--------------------------------------------
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 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 (e
n
) 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


1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
..
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.

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:

O
O

& 4

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.

Varianta iterativ-cu ciclu Varianta cu apel recursiv
contor:=val_init;
Repet
Corp_ciclu;
Incrementeaz(contor);
Pn cnd contor=val_final;

Funcie_Recursiv(contor){
Dac contor<val_final atunci
Corp_ciclu;
Funcie_Recursiv(contor+1);
}

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);
}

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);
}
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);
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));
}

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 ax
2
+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;
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) ;
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: a
n =
exp(n*ln(a)), iar pentru a calcula radical
de ordinul n din a: a
1/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')
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);
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
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){
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
1 2
1 2 3
......
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;

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>
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

#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;

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){
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];
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 A
k
.

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] .
-A
k
=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
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;
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;
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)
{
if ((fagenda= fopen("agenda.jo", mod)) == NULL) /* open file agenda */
fprintf(stderr, "Cannot open output file.\n");
creare();
listare();
}


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!");
}



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;

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();
}


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();
}




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;
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){
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 n
2
pai ai soluiei "la prima mn".
-pentru a determina toate descompunerile in diferenta de patrate ale lui n pornim de la formula a
2
-
b
2
=(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 a
2
-b
2
=(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.

#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 2
n
.

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 2
n
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 2
n-1
; ele se pot scrie
sub forma c*10
(n-1)
+M=c*2
n-1
*5
n-1
+M= Multiplu(2
n-1
)+M; inseamna ca M (cele n-1 cifre ramase) trebuie sa
se divida cu 2
n-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 2
n-1
) acest nr.se poate scrie M=2
(n-1)
*par sau
2
(n-1)
*impar, rezulta ca M mod 2
n
=0 sau M mod 2
n
=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 2
n
=0 atunci solutia este 2M=2*10
(n-1)
+M=Multiplu(2
n
)
daca M mod 2
n
=2
(n-1)
atunci solutia este 1M=10
(n-1)
+M=2(
n-1)
*5
(n1)
+M=Multiplu(2
n
)!
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.


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 2
n
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.


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;
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;
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);
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');
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,'');
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;
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
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
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. */

/* 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;
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);
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.


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];
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);
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);
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.
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);
}



// 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
);}
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 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.
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
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

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