Sunteți pe pagina 1din 75

Cuprins

CUPRINS.........................................................................................................................................................................................................1
INTRODUCERE.............................................................................................................................................................................................2
CE ANSE AM S DEVIN UN BUN PROGRAMATOR ?.......................................................................................................................3
LEGILE SUCCESULUI DURABIL (GHIDUL STUDENTULUI NDRTNIC)................................................................................5
PROBLEME DE JUDECAT......................................................................................................................................................................6
PROBLEME DE PERSPICACITATE.....................................................................................................................................................................6
PROBLEME CU CHIBRITURI............................................................................................................................................................................7
PROBLEME DE LOGIC I JUDECAT.............................................................................................................................................................7
PROBLEME DE LOGIC I JUDECAT CU "TENT INFORMATIC"..................................................................................................................9
NOIUNI FUNDAMENTALE DE PROGRAMARE...............................................................................................................................11
1.CELE TREI ETAPE ALE REZOLVRII UNEI PROBLEME CU AJUTORUL CALCULATORULUI...........................................................................11
2.CUM SE STABILETE CORECTITUDINEA I EFICIENA SOLUIONRII ?.....................................................................................................11
3. NOIUNILE FUNDAMENTALE ALE PROGRAMRII: ALGORITM, LIMBAJE DE DESCRIERE A ALGORITMILOR, PROGRAM, LIMBAJE DE
PROGRAMARE..............................................................................................................................................................................................12
3.1. Algoritmul.....................................................................................................................................................................................12
3.2. Descrierea algoritmilor................................................................................................................................................................12
3.3 Programul.........................................................................................................................................................................................13
4. SECRETUL NVRII RAPIDE A PROGRAMRII.......................................................................................................................................14
NOIUNI PRIMARE DE PROGRAMARE N PASCAL I C...............................................................................................................14
EXEMPLE DE PROBLEME REZOLVATE..........................................................................................................................................................16
METODA PRACTIC DE NVARE CE GARANTEAZ REZULTATE IMEDIATE................................................................19
PROBLEME SELECIONATE - ENUNURI........................................................................................................................................19
PROBLEME PROPUSE SPRE REZOLVARE (PROBLEME DE ANTRENAMENT)....................................................................................................19
PROBLEME DE EXAMEN...............................................................................................................................................................................20
PROBLEME DIFICILE.....................................................................................................................................................................................21
PROBLEME NESOLUIONATE NC...............................................................................................................................................................22
PROBLEME INSOLVABILE ALGORITMIC........................................................................................................................................................24
NOIUNI APROFUNDATE DE PROGRAMARE..................................................................................................................................27
METODE I STRATEGII DE PROIECTARE A ALGORITMILOR (ALIAS TEHNICI DE PROGRAMARE)...................................................................27
BACKTRACKING. ........................................................................................................................................................................................29
GREEDY.......................................................................................................................................................................................................30
PROGRAMAREA DINAMIC. ........................................................................................................................................................................31
BRANCH & BOUND......................................................................................................................................................................................31
RECURSIVITATEA.........................................................................................................................................................................................32
PROBLEME REZOLVATE I EXERCIII DE PROGRAMARE.......................................................................................................35
PROBLEME ELEMENTARE. EXERCIII DE PROGRAMARE..............................................................................................................................36
PROBLEME CE NECESIT BACK-TRACKING..................................................................................................................................................50
PROBLEME CU SOLUIE SURPRINZTOARE..................................................................................................................................................53
ELEMENTE DE PROGRAMARE A PC - URILOR..............................................................................................................................................57
CURIOZITI I TRUCURI DE PROGRAMARE................................................................................................................................................71
CONFRUNTARE DE OPINII: INFORMATIC VERSUS MATEMATIC......................................................................................74
BIBLIOGRAFIE, ADRESE I LOCAII DE INTERES PE INTERNET............................................................................................75
Introducere
Exist multe culegeri de probleme de informatic ce permit nvarea i perfecionarea n programare. Prin aceast culegere am
ncercat nu doar s sporim aceast mulime cu nc una ci s oferim un punct de vedere nou, original i incitant. Originalitatea nu este
dat de enunurile problemelor sau de rezolvrile oferite, ci de ideile i sfaturile cu caracter mobilizator pe care le oferim, precum i de
faptul c am introdus cteva capitole cu coninut mai puin obinuit ntr-o culegere de probleme de programare.
Ni s-a prut mai important ca n aceste vremuri, caracterizate prin cuvintele "m simt ntr-o permanent criz de timp", s oferim
ct mai mult din experiena noastr direct, att cea de programator ct i cea de profesor de programare. Dei nu credem c exist metode
perfecte de predare sau de nvare a programrii, totui sperm c prin asimilarea informaiilor originale oferite eficiena procesului de
nvare a programrii n limbajele C i Pascal va crete. Este important ca informaiile suplimentare s fie asimilate gradat i numai n
limita "suportabilitii" fiecruia. De aceea, n paginile ce urmeaz vei gsi i o serie de informaii i sfaturi ce sintetizeaz experiena
didactic acumulat ca profesor de informatic i urmndu-le v asigurm c vei obine succesul n programare.
n primele capitole a fost pus un accent important pe motivarea iniial a celor ce doresc s nvee programare. n capitolul "Ce
anse am s devin un bun programator" snt chiar prezentate cu sinceritate nzestrrile necesare unui bun programator.
Tot astfel se explic motivul introducerii unui capitol ce conine probleme de judecat. Rezolvarea acestora pot fi considerate nu
doar ca un excelent antrenament al minii ci i ca o bun ocazie de a aprinde pasiunea pentru informatic i de a ntri motivaia
programatorilor nceptori.
Asta nu nseamn c aceast culegere nu le este util i celor care au dobndit deja suficiente cunotine de programare. Am
introdus n ea cteva capitole ce conin informaii mai puin cunoscute. Unul cuprinde o list de probleme deosebite, unele foarte dificile,
altele crora nu li se cunoate nc o soluie i altele pentru care exist demonstraie riguroas c nu pot fi rezolvate cu ajutorul
calculatorului. Alt capitol cuprinde exemple de programare a PC-urilor: lucrul cu tastatura, mouse-ul, accesul direct la memoria ecran,
etc. Iar unele capitole ca Noiuni aprofundate de programare, Probleme cu soluie surprinztoare sau Curioziti i trucuri de
programare le snt n ntregime destinate celor care au depit stadiul de nceptor. Probabil c aceste informaii constituie o provocare
destul de substanial chiar i pentru cei avansai n ale programrii.
n concluzie, scopul acestei culegeri nu este doar de a contribui la formarea i specializarea programatorilor sau pentru
aprofundarea tehnicilor de programare, ct mai ales de a le oferi o baz, o motivaie i o iniiere celor care doresc s fac primii pai n
domeniul programrii. Iar acelor mptimii ai programrii care se simt deja plictisii, stui sau plafonai le promitem c parcurgnd
aceast culegere vor aprofunda cunotinele pe care i le-au nsuit deja i, dac vor avea curajul de "a se lua de piept" cu unele din
problemele nesoluionate nc, li se va reaprinde cu siguran focul pasiunii pentru programare.
nceptorilor le urm Bun venit n programare i tuturor Mult succes !
2
Ce anse am s devin un bun programator ?
Aceast ntrebare apare deseori n discuiile sincere dintre profesori i studenii lor descurajai de ntrzierea apariiei unor
rezultate care s certifice buna lor calitate ca programatori. Vom ncerca n rndurile ce urmeaz s rspundem ct mai clar la aceast
ntrebare oferind, n plus, o perspectiv prosptat asupra acestui subiect, prin luarea n considerare a unei serii de factori mai puin
utilizai n procesul didactic contemporan.
Mai nti s vedem ce s-ar putea nelege prin sigtagma bun programator, insisitnd n continuare doar pe aprofundarea
adjectivului bun, fr a mai defini sau detalia ce se nelege printr-un programator. Vom cita cuvintele recente ale lui Timoty Budd
( profesor la Oregon State University ) care d urmtoarea definiie: Un bun programator trebuie s fie nzestrat cu tehnic, experien,
capacitate de abstractizare, logic, inteligen, creativitate i talent. ntru-totul de acord cu aceast definiie vom trece n cele ce
urmeaz la explicitarea fiecrei caliti.
nainte vom deduce urmtoarea consecin imediat - deosebit de important - ce rezult din definiia de mai sus: cele apte
caliti trebuie s fie prezente toate pentru a se obine calificativul de bun programator. Deci, prin lipsa sau prin prezena atrofiat a
uneia , sau a mai multe din ingredientele reetei de mai sus, acest calificativ nu mai poate fi atins.
1. Tehnica este desigur o calitate ce poate fi, i este, dobndit doar prin aplicarea asidu (conform proverbului: exerciiul l face pe
maestru) n activitatea concret de programare a tehnicilor de programare nvate i asimilate de ctre programator n timpul
formrii sale profesionale. Nu este exclus aici posibilitatea obinerii tehnicii de programare nafara unui cadru specializat (ntr-o
facultate de profil ), ci chiar exist posibilitatea obinerii ei prin studiu individual i formaie proprie (autodidact ).
2. Experiena este perechea geamn a calitii de mai nainte, fr ns a se exclude una pe cealalt. Nu vom mai repeta cum i n ce
condiii poate fi ea obinut ci vom deduce urmtoarea consecina imediat : nici un programator nceptor nu poate fi numit bun
programator ntruct el nu a avut cnd (adic timpul necesar ) s dobndeasc ambele caliti. Este binecunoscut faptul c o
rubric important ce se cere completat la angajare sau la schimbarea locului de munc este experiena de programare n ani. Se
consider n general c experiena apare abia dup minimum doi ani de programare. Acest fapt nu trebuie privit ca o descurajare
pentru cei mai tineri programatori ci mai degrab ca pe un motiv de ambiionare i ca o invitaie la rapid autoperfecionare.
3. Abstractizarea este o trstur a intelectului uman i constituie un dat al oricrui om normal, dar din pcate(!) este o nsuire prea
puin dezvoltat i prea puin folosit de oamenii obinuii. Ea const din capacitatea de a extrage din context, de a vedea dincolo de
suprafaa imediat i de a putea sesiza structura scheletul ce susine ntreaga reea de detalii ale unei probleme generale. Pentru a fi
un bun programator acest calitate trebuie s fie net amplificat fa de normal ntruct st la baza oricrui proces de analiz i
modelare a problemelor, ct i la baza procesului de proiectare a soluiilor generale. Absena sau mai exact atrofierea acestei
capaciti se constat practic la studeni prin incapacitatea de a nelege sau de a asimila explicaii, demonstraii sau modele abstracte
( simplu spus, o acut i permanent lips de chef atunci cnd snt atinse anumite subiecte ce nu mai au contact direct cu realitatea
concret, imediat adic subiecte abstracte ). Metoda pentru a recpta sau a amplifica aceast capacitate este de a face ct mai des
uz de ea, adic de a o exersa mereu (conform zicalei funcia creeaz organul) ntr-un domeniu particular, susinut de o motivaie
personal puternic. Altfel spus, capacitatea noastr de abstractizare se va amplifica dac vom ncerca gsirea de soluii la
problemele dintr-unul din domeniile noastre preferate, pentru c rezolvarea acestora va fi automotivat, fcut cu chef i va
prezenta o doz sporit de atractivitate.
4. Logica este o alt calitate intrinsec a oricrui intelect sntos. Ea este absolut necesar att pentru a putea folosi mecanismele
mentale de deducie i inducie logic, ct i pentru a putea nelege uor, dar n acelai timp corect, cursul firul rou al unei
demonstraii sau al unui raionament ntins pe mai multe pagini. Asemenea tuturor calitilor intrinseci existente n stare potenial,
antrenarea i amplificarea acesteia se face prin exerciiu repetat, prin folosirea ei n mod curent.Din pcate, doar prin rezolvarea de
integrame nu se ajunge la amplificarea logicii
5. Inteligena este una din cele mai de pre caliti intrinseci ale intelectului uman. n cteva cuvinte, fr a avea pretenia de a da prin
acestea o definiie, prin inteligen nelegem capacitatea de a face (de a stabili) conexiuni sau legturi noi i folositoare (din
latinescul inter-legere) ntre idei, cunotine sau informaii aparent fr legtur. Fa de logic, pe care o considerm ca fiind o
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,
3
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.
4
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
5
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 ?
6
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
7
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
8
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 ?
9
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).
10
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
11
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)\{0}xx.
3. Finitudinea pentru fiecare intrare valid orice algoritm trebuie s conduc n timp finit (dup un numr finit de pai) la un rezultat.
Aceast caracteristic este analog proprietii de convergen a unor metode din matematic: trebuie s avem garania, dinainte de a
aplica metoda (algoritmul), c metoda se termin cu succes (ea converge ctre soluie).
S observm i diferena: n timp ce metoda matematic este corect chiar dac ea converge ctre soluie doar la infinit (!), un
algoritm trebuie s ntoarc rezultatul dup un numr finit de pai. S observm deasemenea c, acolo unde matematica nu ofer
dovada, algoritmul nu va fi capabil s o ofere nici el. De exemplu, nu este greu de scris un algoritm care s verifice corectitudinea
Conjecturii lui Goldbach: Orice numr par se scrie ca sum de dou numere prime, dar, dei programul rezultat poate fi lsat s
ruleze pn la valori extrem de mari, fr s apar nici un contra-exemplu, totui conjectura nu poate fi astfel infirmat (dar nici
afirmat!).
3.2. Descrierea algoritmilor
Dou dintre metodele clasice de descriere a algoritmilor snt denumite Schemele logice i Pseudo-Codul. Ambele metode de
descriere conin doar patru operaii (instruciuni) elementare care au fiecare un corespondent att schem logic ct i n pseudo-cod.
n cele ce urmeaz vom nira doar varianta oferit de pseudo-cod ntruct folosirea schemelor logice s-a redus drastic n ultimii ani.
Schemele logice mai pot fi ntlnite sub numele de diagrame de proces n anumite cri de specialitate inginereti. Avantajul descrierii
algoritmilor prin scheme logice este dat de libertatea total de nlnuire a operaiilor (practic, sgeata care descrie ordinea de execuie,
pleac de la o operaie i poate fi trasat nspre orice alt operaie). Este demonstrat matematic riguros c descrierea prin pseudo-cod, dei
12
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
13
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 : Exemplu :
14
Program Un_Simplu_Test;
Const e=2.68;
Var x:real;
BEGIN
x:=1./2+e*(1+e);
Writeln(Rezultatul este:,x);
END.
#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
else suma:=suma+j;
int i,j,suma;
..
if (i<=2*j+1) suma+=i
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;
15
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=(-bdelta)/(2*a)
- dac delta < 0 atunci ecuaia are soluiile complexe z1=(-b/(2*a), (-delta)/(2*a)), z1=(-b/(2*a), -(-delta)/(2*a))
Program Ecuatie_grad_2; { varianta Pascal }
Var a,b,c,delta:real;
BEGIN
Write('Introd. a,b,c:');Readln(a,b,c);
delta:=b*b-4*a*c;
If delta>=0 then
Begin
Writeln('x1=',(-b-sqrt(delta))/(2*a):6:2);
Writeln('x2=',(-b+sqrt(delta))/(2*a):6:2);
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;
16
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:
17
- un numr p este prim dac nu are nici un divizor nafar de 1 i p cu ajutorul unei variabile contor d vom parcurge toate valorile
intervalului [2.. p]; acest interval este suficient pentru depistarea unui divizor, cci: d1 | p p = d1*d2 (unde d1 < d2) d1 d1*d2 = p
iar d2 d1*d2 = p
Program Nr_prim; { Pascal }
Var p,i:word;
prim:boolean;
BEGIN
write('p=');readln(p);
prim:=true;
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':
18
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.
19
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.
20
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) 1M R2)
Dac xM atunci y=2x+1 i z=3x+1 aparin lui M. Se citete n, s se determine dac n aparine mulimii M fr a genera toate
elementele acesteia mai mici dect n.
27. Se citete n, k i o matrice A=(ai,j) nxn ptratic. S se determine 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
=n!/(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
21
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 !
22
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 k>01/(k(k+1))=k>0(1/k-1/
(k+1))=1.
Comentariu: aparent, descoperirea dezvoltrilor n serie pare s fi plecat de la unele evidente propieti geometrice, uor de sesizat chiar
din desene simple n care valorilor numerice li se asociaz segmente de lungimi corespunztoare. Iat ns o surpriz n aceast situaie:
suma seriei numerice este evident analitic ns reprezentarea geometric a "fenomenului" este "imposibil" !
4. Conjectura fraciilor egiptene (atribuit lui Erds i Graham). Orice fracie de forma 4/n se descompune ca sum de trei fracii
egiptene (de forma 1/x).
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 k>01/k
3
sau k>0k
-3
. Se tie c n cazul n care n locul puterii a 3-ia (cu
minus) punem puterea a 2-a (cu minus) seria converge la
2
/6, n cazul n care n locul puterii a 3-ia punem puterea a 4-a seria converge
la
4
/90.
Comentariu: dei pare a fi o problem de analiz matematic pur deoarece ni se cere s gsim expresia sintetic i nu cea numeric
aproximativ a sumei seriei, exist ns uluitoare descoperiri asemntoare ale unor formule de analiz numeric sau chiar dezvoltri n
serie (cea mai celebr fiind cea a lui cifrelor hexazecimale ale lui ) fcute cu ajutorul calculatorului prin calcul simbolic ! Mai multe
amnunte gsii la adresa corespunztoare de Internet pe care am trecut-o n ultimul capitol.
7. Problema ecuaiei diofantice de gradul 5. Exist a, b, c, and d ntregi pozitivi astfel nct 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 ?
23
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.
24
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" 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 =CARPILL ATE R =CARPIL LOW = CAR P AN= MEAN= ME AT EN= MAT E N= 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.
25
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 .
26
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 atunci
nu 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).
27
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.
28
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
C
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
/
29
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
30
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.
31
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.
32
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;
33
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));
}
34
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".
35
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(){
36
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.
37
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);
38
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 .
39
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) {
40
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.
41
// 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)
42
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");
}
43
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;
44
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;
45
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
46
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;
47
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>
48
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 */
49
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.
50
- 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){
51
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;
52
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)
53
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:
54
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;
55
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;
56
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
57
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
58
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;
59
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;
60
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.
61
// 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;
62
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!');
63
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);
64
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;
65
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
66
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. }
67
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] ) )
68
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);
69
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
70
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);
}
71
72
// 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
);}
73
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
74
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
75

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