The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.

Hyrje në Programim - PROGRAMIMI NË JAVA (a4)

Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by 16, 2024-06-17 14:29:51

Hyrje në Programim

Hyrje në Programim - PROGRAMIMI NË JAVA (a4)

3.7. Detyra praktike 43 Detyra 3.7.2.2 Pjesëtuesit Shkruani një program që pranon një numër të plotë pozitiv dhe pastaj printon të gjithë numrat e plotë pozitivë që janë pjesëtues të atij numri.  Detyra 3.7.2.3 Integer logarithm Integer logarithm i një numri të plotë n (me n ≥ 1) me një bazë b që është numër i plotë (me b > 1) është numri i herëve që b mund të shumëzohet me veten për të arritur n. Me fjalë tjera, është numri më i madh m ashtu që b m ≤ n. Shkruani një program që pyet përdoruesin të shënojë dy numra të plotë n dhe b (ashtu që n ≥ 1 dhe b > 1) dhe pastaj printon integer logarithm të numrit n me bazën b. Sigurisht, nuk jeni të lejuar të përdorni funksionet e ndërtuara nga klasa Math.  Detyra 3.7.2.4 Inversi i funksionit faktoriel Faktorieli i një numri të plotë jo-negativ n (shënohet n!) definohet si produkt n! := n ∏ k=1 k Vini re se 0! = 1, meqë produkti i një domeni të zbrazët është 1 sipas definimit. Inversi i funksionit faktoriel definohet si funksioni caf: caf(x) = numri më i madh n i tillë që n!<=x. Shembull: caf(1) == 1 caf(24) == 4 caf(200) == 5 Shkruani një program i cili pranon një numër të plotë jo-negativ n në hyrje, dhe printon caf(n) në dalje. 


44 Kapitulli 4 Funksionet statike Një funksion është një fragment kodi që kryen një detyrë të caktuar logjike që mund të përdoret në lokacione të ndryshme në programin. Përshkrimi i një funksioni, ngjashëm si variablat quhet deklarim i funksionit. Ne mund të përdorim një funksion duke ’thirrur’ atë: kjo quhet thirrje e funksionit. Ne mund ti kalojmë vlera një funksioni nëpërmjet parametrave: vlerat aktuale të cilat ofrohen me funksionin quhen argumente. Është e zakonshme që një funksion të kthejë një vlerë funksioni —rezultat (p.sh., një vlerë int), megjithatë disa funksione nuk kthejnë asnjë vlerë. 4.1 Deklarimi i funksionit Deklarimi i një funksioni përbëhet nga disa pjesë. Në përgjithësi, deklarimi funksionit ka formën e mëposhtme: 1 public static type functionName(type1 parameter1, ..., typeN parameterN) { 2 bodyStatements; 3 } Së pari specifikojmë llojin e funksionit. Lloji i funksionit është lloji i rezultatit ose vlerës kthyese të funksionit. Nëse funksioni nuk kthen një rezultat, lloji specifikohet si void. Ky lloj i funksionit quhet funksion void ose metodë. Lloji i funksionit ndiqet nga emri i funksionit. Rregullat e emërtimit për funksionet (identifikatorët ) janë të njëjta si për variablat (shih pjesën 2.3.1). Zakonisht, emri i funksionit që kthen vlerë jep një përshkrim të rezultatit të kthyer. Për shembull, isPrime do të ishte një emër i mirë për një funksion që merr një parametër hyrës dhe kthen një vlerë logjike true nëse argumenti i tij është një numër i thjeshtë, përndryshe kthen false. Lista e parametrave hyrës në funksionin përbëhet nga një sekuencë e deklarimeve të variablave të ndara me presje. Kjo listë mbyllet brenda kllapave. Nëse funksioni nuk ka parametra hyrës, kjo listë është e zbrazët (d.m.th., vetëm një çift kllapash). Lista e parametrave hyrës të funksionit ndiqet nga trupi i funksionit: kodi aktual. Në trupin, ne mund të përdorim parametrat si variabla të zakonshme. Këto variabla janë variabla lokale brenda funksionit: ndryshimi i vlerës së një variable lokale nuk ndikon vlerën e argumentit që jepet kur thirret funksioni. Ky mekanizëm njihet si ’call-by-value’ (shih pjesën 4.4).


4.1. Deklarimi i funksionit 45 4.1.1 Funksionet void Një funksion që nuk kthen një rezultat ka llojin void. Për shembull, funksioni i mëposhtëm i tregon përdoruesit që duhet të shënojë një numër të plotë në intervalin [lwb, upb]. PROGRAMI 4.1: Funksioni void 1 import java.util.Scanner; 2 3 public class FunctionEx { 4 5 public static void printIntervalMessage(int lwb, int upb) { 6 System.out.print("Shenoni nje numer ne intervalin [" + lwb + ", " + upb + "]"); 7 } 8 } Siç mund ta shihni, parametrat lwb dhe upb përdoren si të ishin variabla të zakonshme. Funksioni nuk kthen një rezultat. Prandaj, lloji i vlerës kthyese të funksionit është void. 4.1.2 Funksionet që kthejnë një rezultat Brenda trupit të një funksioni që kthen një rezultat, përdorim deklarimin return për të ndalur ekzekutimin e trupit të funksionit dhe për të kthyer rezultatin e funksionit. Një deklarim return ka formën e mëposhtme: return shprehja; ku shprehja duhet të jetë një shprehje që ka llojin e njëjtë të të dhënave si lloji i vlerës kthyese të funksionit. Brenda trupit të një funksioni që nuk kthen një rezultat (void) gjithashtu mund të përdorim deklarimin return për të terminuar ekzekutimin e truput, por sigurisht pa kthyer një vlerë: return; Në një funksion void nuk është e nevojshme të përdorim një deklarim return, meqë në mënyrë implicite është deklarimi i fundit i një funksioni të tillë. Kështu që, në një funksion void deklarimi return zakonisht përdoret vetëm si terminim i hershëm në një cikël. Një zgjerim i thjeshtë i funksionit printIntervalMessage do të ishte të lexojë një numër si hyrje dhe ta kthejë atë si rezultat. Sigurisht, kjo nënkupton se funksioni nuk është më një funksion void, meqë ai duhet të kthejë një vlerë int. Kështu që, arrijmë në funksionin e mëposhtëm numberFromInterval: PROGRAMI 4.2: Funksionet që kthejnë rezultat: Shembull 1 import java.util.Scanner; 2 3 public class FunctionEx2 { 4 5 public static int numberFromInterval(int lwb, int upb) { 6 int number; 7 Scanner input = new Scanner(System.in);


46 Kapitulli 4. Funksionet statike 8 System.out.print("Shenoni nje numer ne intervalin [" + lwb + ", " + upb + "]"); 9 do { 10 number = input.nextInt(); 11 if(number < lwb) { 12 System.out.println(number + "<" + lwb + ": provoni perseri"); 13 } 14 else if(number >= upb) { 15 System.out.println(number + ">=" + upb + ": provoni perseri"); 16 } 17 System.out.println(m); 18 } while((numer < lwb) || (number >= upb)); 19 return number; 20 } 21 } Ju mund të shihni se lloji i vlerës kthyese të funksionit është një int: një vlerë numerike që është numër i plotë prodhohet si rezultat. Cikli në trupin e funksionit ekzekutohet derisa të shënohet një numër që është brenda intervalit të kërkuar. Kur cikli terminon, vlera e shënuar së fundi kthehet si rezultat i funksionit. Është e lejuar të përdorim deklarimin return brenda ciklit. Në atë rast, cikli dhe funksioni do të përfundojnë, dhe vlera e caktuar do të kthehet. Nëse dëshironi të përdorni një deklarim return brenda trupit të ciklit është një çështje preference. Disa programerë konsiderojnë atë si stil i keq i programimit, ndërsa të tjerët përdorin shpesh këtë tipar. Është në dorën tuaj të vendosni. Një implementim alternativ i funksionit numberFromInterval duke përdorur këtë tipar do të ishte: PROGRAMI 4.3: Funksionet që kthejnë rezultat: Shembull 1 import java.util.Scanner; 2 3 public class FunctionEx { 4 5 public static int numberFromInterval(int lwb, int upb) { 6 int number; 7 Scanner input = new Scanner(System.in); 8 System.out.print("Shenoni nje numer ne intervalin [" + lwb + ", " + upb + "]"); 9 while (true) { 10 number = input.nextInt(); 11 if((lwb <= number) && (number < upb)) { 12 return number; 13 } 14 System.out.println(number + " nuk eshte ne intervalin [ " + lwb + ", " + upb + "]"); 15 } 16 } 17 }


4.2. Thirrja e funksionit 47 4.2 Thirrja e funksionit Funksionet mund të thirren duke shkruar emrin e funksionit dhe një listë (ndoshta të zbrazët) të argumenteve. Vlerat e argumenteve kopjohen në parametrat e funksionit. Meqë vlerat kopjohen, vlerat origjinale nuk ndryshohen nga një thirrje e funksionit. Qartazi, numri i argumenteve duhet të jetë i barabartë me numrin e parametrave të funksionit. Secili argument duhet të jetë një shprehje e një lloji të të dhënave që është kompatibile me llojin e të dhënave të parametrit korrespondues në deklarimin e funksionit. Thirrja e një funksioni void është një deklarim i zakonshëm, ndërsa thirrja e një funksioni që kthen një rezultat është një shprehje e llojit të njëjtë të të dhënave si lloji i vlerës kthyese të funksionit që mund ti caktohet si vlerë një variable. Për shembull, funksioni i mëposhtëm void 1 public static void printInt(int n) { 2 System.out.println("n = "+ n); 3 } mund të thirret si vijon: printInt(42); Funksioni square që kthen një rezultat: 1 public static float square (float x){ 2 return (x * x); 3 } mund të përdoret për të llogaritur ax2 + bx + c si vijon: y = a * square(x) + b * x + c; Vini re se ju tashmë jeni mësuar të thirrni funksione: println, nextInt janë shembuj të funksioneve të ndërtuara që i kemi përdorur më parë. 4.3 Fushëveprimi Fushëveprimi i një variable është regjioni në kodin në të cilin variabla ’ekziston’. Dallojmë dy lloje të variablave: variablat globale dhe variablet lokale. Një variabël globale deklarohet jashtë ndonjë funksioni, zakonisht në fillim të fajllit burimor (shpesh menjëherë pas deklarimit të klasës). Fushëveprimi i një variable globale është i tërë programi. Kjo është e ndryshme për variablat lokale. Në përgjithësi mund të themi se fushëveprimi i një variable lokale është regjioni i kodit nga deklarimi i variablës deri në fund të kllapës mbyllëse të bllokut të kodit në të cilin variabla është deklaruar. Një variabël lokale mund të ketë emrin e njëjtë si një variabël që është prezente në fushëveprimin përreth. Në atë rast, variabla nga fushëveprimi përreth është përkohësisht e padukshme. Nëse ekzekutimi i programit arrin fundin e fushëveprimit të variablës lokale, atëherë variabla origjinale bëhet përsëri e dukshme. Konsideroni shembullin e mëposhtëm dhe përpiquni të kuptoni se çfarë do të jetë dalja e këtij programi (mos shikoni menjëherë te zgjidhja):


48 Kapitulli 4. Funksionet statike PROGRAMI 4.4: Fushëveprimi: Shembull 1 2 public class FunctionEx2 { 3 4 int x = 1; 5 6 public static void function1() { 7 System.out.println(x); 8 x++; 9 System.out.println(x); 10 } 11 12 public static void function2() { 13 int x = 3; 14 System.out.println(x); 15 x++; 16 System.out.println(x); 17 if(x == 4) { 18 int x = 5; 19 System.out.println(x); 20 x++; 21 System.out.println(x); 22 } 23 System.out.println(x); 24 } 25 26 public static void main(String [] args) { 27 System.out.println(x); 28 function1(); 29 System.out.println(x); 30 function2(); 31 System.out.println(x); 32 } 33 } Siç mund ta shihni, variabla x është deklaruar tre herë. Kjo nuk paraqet një problem, meqë fushëveprimet janë të ndryshme. Deklarimi i parë në fillim të programit është jashtë çdo funksioni dhe prandaj është një deklarim global. Variabla globale x është e dukshme në tërë programin përderisa nuk krijohet një variablël lokale me emrin e njëjtë. Themi se fushëveprimi i x mbulon tërë programin. Në metodën main printohet vlera e variablës globale x, kështu që dalja do të jetë 1, siç e prisni. Pastaj thirret funksioni function1. Meqë ky funksion nuk ka ndonjë variabël lokale në fushëveprimin e tij, një referencë në x brenda këtij funksioni duhet të jetë një referencë në variablën globale x. Funksioni printon së pari vlerën e variablës x (d.m.th., 1), pastaj inkrementon x dhe printon përsëri vlerën e saj (d.m.th., 2). Pas ekzekutimit të funksionit function1, ekzekutimi i programit kthehet në metodën main. Kjo metodë poashtu printon vlerën e variablës x. Meqë function1 inkrementon vlerën e x, printohet vlera 2. Pastaj, thirret funksioni function2. Në këtë funksion deklarohet një tjetër variabël x. Kjo variabël është lokale, dhe ka një fushëveprim që përfundon në kllapën e fundit mbyllëse të funksionit function2. Variabla lokale x hijëzon variablën globale x (e cila bëhet e padukshme). Variabla lokale x ka fillimisht vlerën 3, dhe kështu që printohet vlera 3. Në vazhdim, variabla lokale x inkrementohet dhe prandaj printohet


4.4. Kalimi i parametrave sipas-vlerës 49 4. Meqë (x == 4) llogaritet në true, ekzekutohet trupi i deklarimit if. Këtu mund të shohim se gjithashtu është e mundshme të fusim variablat lokale në një bllok lokal kodi. Kështu që, përsëri është deklaruar një variabël e re lokale x që hijëzon variablën lokale x nga fushëveprimi përreth. Sigurisht, trupi i deklarimit if printon 5, dhe pastaj 6. Tani bëhet interesante. Përfundojmë bllokun e kodit të deklarimit if. Variabla lokale x që është deklaruar në trupin e deklarimit if del jashtë fushëveprimit, kështu që variabla zhduket (nuk ekziston më). Si rezultat, variabla lokale x nga fushëveprimi përreth bëhet e dukshme përsëri. Kjo variabël ende ka vlerën 4, kështu printohet vlera 4. Pastaj funksioni function2 përfundon dhe variabla lokale x gjithashtu zhduket. Kemi mbetur vetëm me variablën globale x ende të dukshme, e cila ende ka vlerën 2. Prandaj, më në fund printohet vlera 2 në metodën main. Si përfundim, programi prodhon daljen e mëposhtme: 1 1 2 2 3 4 5 6 4 2 4.4 Kalimi i parametrave sipas-vlerës Parametrat e një funksioni mund të konsiderohen si variabla lokale: ato ekzistojnë vetëm brenda funksionit. Bëjmë një dallim ndërmjet parametrave formalë dhe parametrave aktualë. Parametrat formalë janë parametrat që hasen në definimin e funksionit. Parametrat aktualë (gjithashtu të njohur si argumente) janë vlerat (shprehjet) që kalohen nga thirrësi. Për shembull, në funksionin vijues n është një parametër formal. 1 public static void printNextInt(int n) { 2 n++; 3 System.out.println(n); 4 } Kur thërrasim këtë funksion, argumenti që i kalojmë këtij funksioni është parametri aktual (që është vlera aktuale). Për shembull: printNextInt(41); Sigurisht, gjithashtu mund të shkruajmë: a = 41; printNextInt(a); Në të dy rastet, vlera 41 (që nuk është një variabël!) është parametri aktual i funksionit printNextInt. Ju mund të mendoni për këtë si vijon: vlera 41 është kopjuar në


50 Kapitulli 4. Funksionet statike variablën lokale n (parametri formal) të funksionit printNextInt para se kodi i funksionit të fillojë ekzekutimin. Ky princip quhet thirrja sipas-vlerës. Në JAVA kalimi i parametrave, i ashtuquajturi mekanizmi i kalimit të paramentrave, gjithmonë ndjek këtë princip thirrja sipas-vlerës. Një rrjedhim i rëndësishëm i kësaj është si vijon. Kur një parametër kalohet sipas vlerës, pastaj vlera e parametrit aktual kopjohet në parametrin formal. Kështu që, kur funksioni modifikon vlerën e parametrit formal, ai modifikon një kopje dhe jo vlerën origjinale të parametrit aktual. Prandaj, një funksion nuk mund të ndryshojë vlerën e parametrit aktual nëpërmjet mekanizmit të kalimit të parametrave. Kështu që, fragmenti i programit: 1 a = 41; 2 System.out.println(a); 3 printNextInt(a); 4 System.out.println(a); do të prodhojë daljen e mëposhtme: 41 42 43 Inkrementimi i parametrit formal n nuk ka efekt në variablën a që është përdorur si parametër aktual. Supozoni se dëshirojmë të krijojmë një funksion swap me dy parametra ashtu që thirrja e funksionit swap(a, b) shkëmben vlerat e variablave a dhe b. Nëse kuptoni principin e kalimit sipas-vlerës atëherë ju e dini se pse nuk punon funksioni i mëposhtëm: 1 public static void swap(int a,int b) { 2 int h = a; 3 a = b; 4 b = h; 5 } Ky funksion është i saktë në JAVA, dhe do të pranohet nga kompajleri pa ndonjë ankesë. Megjithatë, meqë modifikimi i parametrave formalë nuk ka efekt në parametrat aktualë, ky funksion nuk bën ’asgjë’. Kështu që, pyetja është se si të implementojmë funksionalitetin e dëshiruar? Për të iu përgjigjur kësaj pyetje, ne së pari duhet të shikojmë se si bëhet kalimi i parametrave sipas referencës. 4.5 Kalimi i parametrave sipas-referencës Mekanizmi i kalimit të parametrit në JAVA përdor principin e kalimit sipas-vlerës. Kjo na ndalon nga implementimi i funksionit swap drejtpërdrejtë. Ndonjëherë, dëshirojmë që të modifikojmë vlerën e një ose më shumë argumenteve në një funksion. Shumë gjuhë programore (p.sh., Pascal dhe C++) kanë një mekanizëm tjetër të kalimit të parametrave që quhet kalimi sipas-referencës. Ky mekanizëm nuk kopjon vlerën e argumenteve, por kalon nëpërmjet referencës në variablat, kështu që funksioni modifikon përmbajtjen e argumenteve aktualë (dhe jo kopjet). Kalimi sipas-referencës


4.5. Kalimi i parametrave sipas-referencës 51 përmirëson performancën duke eleminuar nevojën për të kopjuar të dhënat që mund të jenë të një sasie të madhe. Për dallim nga gjuhët tjera, JAVA nuk lejon të zgjedhim ndërmjet kalimit sipas-vlerës ose kalimit sipas-referencës —të gjithë argumentet kalohen sipas-vlerës. Thirrja e një funksioni mund të kalojë dy lloje të vlerave në një funksion —kopje të vlerave primitive (d.m.th., vlera të llojeve primitive të të dhënave) dhe kopje të referencave të objekteve. Objektet vetë nuk mund të kalohen në funksionet. Kur një funksion modifikon një parametër të llojeve primitive të të dhënave, modifikimet në parametrin nuk kanë efekt në vlerën origjinale të argumentit në thirrjen e funksionit. Kjo është gjithashtu e vërtetë për parametrat e llojit referencë. Nëse modifikoni një parametër të llojit referencë ashtu që të referojë në një objekt tjetër, vetëm parametri referon në objektin e ri —referenca e ruajtur në variablën e funksionit thirrës referon në objektin origjinal. Edhe pse referenca e një objekti kalohet sipas-vlerës, një funksion akoma mund të bashkëveprojë me objektin e referencuar me thirrjen e funksioneve duke përdorur kopjen e referencës së objektit. Meqë referenca e ruajtur në parametrin është një kopje e referencës që është kaluar si një argument, parametri në funksionin e thirrur dhe argumenti në funksionin thirrës referon në objektin e njëjtë në memorie. Kështu që, duke iu referuar një objekti, funksioni i thirrur mund të manipulojë drejtpërdrejtë objektin e funksionit thirrës. Kështu që, mund të implementojmë funksionin swap duke përdorur vargjet (shih kapitullin 5) si parametra formalë. 1 public static void swap(int [] arr, int pos1, int pos2) { 2 int temp = arr[pos1]; 3 arr[pos1] = arr[pos2]; 4 arr[pos2] = temp; 5 } Kalimi i vargjeve sipas-referencës ka kuptim për arsye të performancës. Nëse vargjet do të ishin kaluar sipas-vlerës, një kopje e secilit element do të duhej të krijohej dhe të kalohej. Për vargje të mëdha të cilat kalohen shpesh në funksione, kjo do të konsumonte kohë dhe memorie në mënyrë të konsiderueshme, për kopjimin e vlerave në vargjet.


52 Kapitulli 4. Funksionet statike 4.6 Detyra praktike 4.6.1 Funksionet Ushtrimi 4.6.1.1 — Testimi i katrorit. Shkruani një funksion me një parametër numër të plotë që teston nëse vlera e parametrit është katrori i një numri ose jo. Sigurisht, nuk jeni të lejuar të përdorni funksionin sqrt nga klasa Math. Ushtrimi 4.6.1.2 — Shumica e votave. Shprehja (a || b || c) llogaritet në true nëse të paktën një nga shprehjet a, b ose c është e saktë. Shkruani një funksion me tre parametra të llojit int që kthen një vlerë logjike true nëse dhe vetëm nëse të paktën dy nga parametrat e tij janë të saktë. Ushtrimi 4.6.1.3 — Shumëfishat. Shkruani një funksion isMultipleOf(x, y) i cili kthen true nëse dhe vetëm nëse x është një numër i plotë shumëfish i y. Parametrat x dhe y janë të llojit int. Ushtrimi 4.6.1.4 — Viti i brishtë. Viti është një vit i brishtë nëse është i plotëpjesëtueshëm me 4, por jo me 100. Përjashtime bëjnë vitet që janë të plotëpjesëtueshëm me 400 (këta janë vite të brishta). Shkruani një funksion isLeapYear(x) që përcakton nëse një vit është vit i brishtë ose jo. Ushtrimi 4.6.1.5 — Trekëndëshi. Shkruani një funksion showTriangle(ch, n) me dy parametra: një karakter ch dhe një numër të plotë pozitiv n. Funksioni duhet të printojë një diagram trekëndsh si vijon: n kopje të ch në rreshtin e parë, n - 1 kopje të ch në rreshtin e dytë, e kështu me rradhë. Për shembull, dalja e showTriangle(’+’, 4) duhet të jetë: ++++ +++ ++ + Ushtrimi 4.6.1.6 — Numri i zgjidhjeve të një funksioni kuadratik. Shkruani një funksion numSolutions(int a, int b, int c) që kthen numrin e zgjidhjeve unike reale të funksionit kuadratik ax˙ 2 + bx˙ + c = 0.


4.6. Detyra praktike 53 Ushtrimi 4.6.1.7 — Shifra e parë. Shkruani një funksion firstDigit(x) që kthen shifrën e parë të një numri të plotë pozitiv. Shembuj: firstDigit(648768) = 6 firstDigit(555220) = 5 4.6.2 Programe të vogla Në detyrat e mëposhtme nevojitet të zhvilloni programe të vogla për probleme relativisht të thjeshta. Detyra 4.6.2.1 Numri palindrom Një palindrom është një fjalë që lexohet njëjtë në të dy drejtimet. Disa shembuj të palindromeve janë: radar, level, rotor, madam, kayak, kimik. Një numër palindrom është një numër që ka të njëjtën veti: mund të lexohet në të dy drejtimet. Një shembull është numri 12321. Shkruani një program të plotë që pyet përdoruesin të shënojë një numër pozitiv dhe pastaj printon nëse numri është një numër palindrom ose jo.  Detyra 4.6.2.2 Distanca Manhattan Harta e rrugës Manhattan është e thjeshtë. Rrugët kanë vetëm një nga dy drejtimet e mundshme: veri në jug ose perëndim në lindje. Distanca ndërmjet dy rrugëve që veprojnë paralelisht quhet bllok. Kjo është shumë e ngjashme me një rrjet që e njohim nga matematika. Prandaj, ne numërojmë kryqëzimet e rrugëve njëjtë siç veprojmë në matematikë, si një çift koordinatash të numrave të plotë (x,y). 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 Shkruani një program që pyet përdoruesin të shënojë koordinatat e dy kryqëzimeve dhe pastaj printon distancën ndërmjet këtyre dy lokacioneve për sa i përket numrit të blloqeve ndërmjet tyre. Kjo distancë quhet distanca Manhattan ose distanca city-block, që është plotësisht e ndryshme nga distanca Euclidean (distanca në vijë të drejtë). 


54 Kapitulli 5 Vargjet Në një variabël të zakonshme mund të ruani një vlerë të vetme. Një varg lejon të ruani një sekuencë vlerash të llojit të njëjtë të të dhënave. Një varg është në fakt një listë e numëruar, me një variabël në secilën pozitë në listën. Numri i një pozite quhet indeksi i asaj pozite. Vlerat që janë ruajtur në vargun quhen elemente të vargut. Vargjet kanë të përcaktuar gjatësinë (numrin e elementeve) kur ata krijohen, megjithëse një variabël e vargut mund të ri-caktohet ashtu që të referojë në një varg të ri që ka një gjatësi tjetër. Kjo paraqet një kufizim të vargjeve. Vargjet janë objekte, kështu që konsiderohen të jenë lloje referencë të të dhënave. Siç do ta shihni së shpejti, çfarë ne zakonisht mendojmë si një varg është një referencë në një objekt vargu në memorie. Elementet e vargut mund të jenë ose të llojeve primitive të të dhënave ose të llojeve referencë të të dhënave (duke përfshirë vargjet). 5.1 Deklarimi dhe inicializimi i vargjeve Vargjet zënë hapësirë në memorie. Si objektet tjera, vargjet krijohen me fjalën kyçe new. Për të krijuar një varg, specifikojmë llojin e elementeve të vargut dhe numrin e elementeve. Një shprehje e tillë kthen një referencë që mund të ruhet në një variabël të vargut. Ne mund të deklarojmë një varg në të cilin mund të ruajmë njëqind numra të plotë si vijon: int [] list = new int[100]; Në këtë shembull, emri i vargut është list. Për rregullat e emërimit të vargjeve (indetifikatorët ) përdorim të njëjtat rregulla si ato për variablat e zakonshme skalare (shih pjesën 2.3.1). Pas deklarimit të vargut, ne kemi rezervuar mjaftueshëm hapësirë në memorie për të ruajtur 100 numra të plotë: ne themi se madhësia e vargut është 100. Nëse vargu vetëm është deklaruar, atëherë të gjitha elementet e vargut inicializohen me zero. Krijimi i vargut gjithashtu mund të kryhet në dy hapa si vijon: int [] list; // deklarimi i variablës së vargut list = new int[100]; // krijimi i vargut Në deklarimin, kllapat e mesme pas llojit të të dhënave tregojnë se list është një variabël që do të referojë në një varg (d.m.th., variabla do të ruajë një referencë në


5.2. Indeksimi i vargjeve 55 vargun). Në deklarimin e vlerëdhënies, variabla list pranon referencën në një varg të ri të 10 elementeve int. Në deklarimin e një vargu, specifikimi i numrit të elementeve në kllapat katrore të deklarimit (p.sh., int [10] list;) është një gabim sintaksor. Ne mund të kombinojmë deklarimin dhe inicializimin e një vargu në një rresht kodi: int [] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; Pas deklarimit, ne kemi në dispozicion një varg digits që mund të ruajë dhjetë numra të plotë. Fillimisht, vargu është mbushur me shifrat nga 0 deri në 9. Kur përdorim inicializimin direkt të një vargu, kompajleri është në gjendje të përcaktojë vetë madhësinë e vargut. Nga shembulli i mësipërm, kompajleri është në gjendje të përcaktojë se madhësia e vargut është 10. Sigurisht, nuk mund të ruajmë më shumë elemente në një varg sesa madhësia e përcaktuar me deklarimin e vargut. Nëse madhësia e vargut është më e madhe sesa numri i elementeve të inicializuara, atëherë elementet e mbetura do të inicializohen me vlerat default të llojit të të dhënave të vargut përkatës —zero për elementet që kanë llojin numerik të të dhënave, false për boolean dhe null për llojet referencë. Një program mund të deklarojë vargje të llojeve të çfarëdoshme. Çdo element i një vargu të llojit primitiv të të dhënave përmban një vlerë të llojit të deklaruar të vargut. Ngjashëm, në një varg të një lloji referencë, çdo element është një referencë në një objekt të llojit të deklaruar të vargut. Për shembull, çdo element i një vargu int është një vlerë int, dhe çdo element i një vargu String është një referencë në një objekt String. 5.2 Indeksimi i vargjeve Qasja e elementeve të vargut quhet indeksim. Ne i qasemi një elementi të vargut në indeksin i të një vargu a duke përdorur shënimin a[i]. Mbani në mend se indeksi i elementit të parë të një vargu është gjithmonë 0. Kështu që, elementi i fundit i një vargu të madhësisë n ka indeksin n - 1. Një indeks duhet të jetë një numër i plotë jo-negativ. Një program mund të përdor një shprehje si një indeks. Për shembull, nëse ne supozojmë se variabla a është 4 dhe variabla b është 5, atëherë shprehja digits[a+b] += 2; shton 2 në elementin digits[9]. Indeksimi i një vargu është një shprehje për qasje në vargun, e cila mund të përdoret në anën e majtë të një deklarimi të vlerëdhënies për të vendosur një vlerë të re në një element të vargut, si në vijim: digits[5] = 8; Për të përcaktuar gjatësinë e vargut digits përdorim shprehjen digits.length


56 Kapitulli 5. Vargjet e cila kthen si rezultat numrin e elementeve të vargut, në rastin tonë vlerën 10. Një varg që përmban n elemente ka indekset nga intervali [0, n). Nëse përpiqeni ti qaseni vargut në një indeks i që është jashtë këtij intervali (d.m.th., i < 0 ose i >= 10), mund të rezultojë në një gjendje të pazakonshme: ndonjëherë programi ndalon (thyhet) menjëherë në momentin kur ndodh gabimi përkatës, ndonjëherë ekzekutimi i programit vazhdon dhe gjëra të papritshme mund të shkojnë keq më vonë. Indeksimi i një vargu me një indeks jo-valid quhet indeksimi jashtë-kufinjve. Një shembull i këtij gabimi që shpesh ndodh është paraqitur në fragmentin e kodit në vazhdim: int i, a[]; for (i = 0; i <= 10; i++) { a[i] = 1; } Në vend të testimit i <= 10, është dashur të përdorim testimin i < 10 sepse a[10] nuk ekziston. 5.3 Shembuj duke përdorur vargjet Në vazhdim jepen disa shembuj që paraqesin deklarimin e vargjeve, krijimin e vargjeve, inicializimin e vargjeve dhe manipulimin e elementeve të vargut. 5.3.1 Krijimi dhe inicializimi i një vargu Shembulli në vazhdim krijon një varg me 10 elemente int, që fillimisht janë zero (vlera default për variablat int). Pastaj bëhet printimi i rezultatit në një format tabelare —kolona e parë paraqet indekset, ndërsa kolona e dytë paraqet vlerat e elementeve të vargut. PROGRAMI 5.1: Inicializimi i elementeve të një vargu 1 public class InitArray { 2 public static void main(String [] args) { 3 int [] array; // deklarimi i vargut te emeruar array 4 array = new int[10]; // krijon vargun 5 array[0] = 23; 6 array[1] = 24; 7 array[2]= 32; 8 System.out.println("Index\t Value"); 9 10 // printon te gjithe vlerat e elementeve te vargut 11 for (int counter = 0; counter < array.length; counter++) 12 System.out.println(counter + "\t" + array[counter]); 13 } 14 }


5.3. Shembuj duke përdorur vargjet 57 Index Value 0 23 1 24 2 32 3 0 4 0 5 0 6 0 7 0 8 0 9 0 Deklarimi for printon numrin e indeksit (i përfaqësuar nga counter) dhe vlera e secilit element (e përfaqësuar nga array[counter]). Variabla e ciklit counter është inicializuar në 0 —indeksimi i vlerave fillon në 0, kështu që përdoret numërimi duke filluar nga 0 që lejon ciklin të qaset në secilin element në vargun. Kushti në ciklin for përdor shprehjen array.length për të përcaktuar gjatësinë e vargut. Në këtë shembull gjatësia e vargut është 10, kështu që cikli vazhdon ekzekutimin derisa vlera e variablës counter është më e vogël se 10. Vlera më e madhe e indeksit për një varg me 10 elemente është 9, kështu që duke përdorur operatorin ’më e vogël se’ në kushtin e ciklit garanton që cikli nuk do të tentojë të qaset në një element jashtë kufirit të vargut (d.m.th., gjatë iterimit të fundit të ciklit, counter është 9). 5.3.2 Llogaritja e vlerave që ruhen në një varg Në vazhdim jepet një program i cili krijon një varg me 10 elemente dhe i cakton secilit element një nga numrat e plotë çift nga 2 deri në 20 (2, 4, 6, 8, ..., 20). Pastaj, programi paraqet vargun në një format tabelar. Deklarimi for në rreshtat 7-8 llogarit vlerën e një elementi të vargut duke shumëzuar vlerën aktuale të variablës counter me 2, pastaj duke i shtuar 2. PROGRAMI 5.2: Llogaritja e vlerave që ruhen në elementet e një vargu 1 public class InitArray1 { 2 public static void main(String [] args) { 3 final int ARRAY_LENGTH = 10; // deklarimi i konstantes 4 int [] array = new int[ARRAY_LENGTH]; // krijimi i vargut 5 6 //llogaritja e vleres per secilin element ne vargun 7 for(int counter = 0; counter < array.length; counter++) 8 array[counter] = 2 + 2 * counter; 9 10 System.out.println("Index \t Value"); // titujt e kolonave 11 12 // printimi i secilit element te vargut 13 for(int counter = 0; counter < array.length; counter++) 14 System.out.println(counter + "\t" + array[counter]); 15 } 16 }


58 Kapitulli 5. Vargjet Index Value 0 2 1 4 2 6 3 8 4 10 5 12 6 14 7 16 8 18 9 20 Në rreshtin 8 përdoret modifikatori final për të deklaruar konstanten ARRAY_LENGTH me vlerën 10. Konstantet shpesh e bëjnë programin më të lexueshëm se programet që përdorin vlerat literale (p.sh., 10) —një konstante e emëruar si ARRAY_LENGTH qartësisht tregon qëllimin e tij, ndërsa një vlerë literale mund të ketë kuptime të ndryshme bazuar në kontekstin e tij. Konstantet duhet të inicializohen para se të përdoren dhe nuk mund të modifikohen më pas. Caktimi i një vlere në një konstante pasi të inicializohet është një gabim kompajlimi. Përpjekja për të përdorur një konstante para se të inicializohet është një gabim kompajlimi. 5.3.3 Shuma e elementeve të një vargu Shpesh, elementet e një vargu përfaqësojnë një seri vlerash që përdoren në një llogaritje. Nëse, për shembull, ato përfaqësojnë pikët e një provimi, profesori mund të dëshirojë të mbledhë pikët në elementet e vargut dhe të përdorë atë shumë për të llogaritur mesataren e klasës për provimin. Programi në vijim mbledh vlerat e një vargu me 10 elemente numra të plotë. Deklarimi for kryen llogaritjet. PROGRAMI 5.3: Llogaritja e shumës së elementeve të një vargu 1 public class SumArray { 2 public static void main(String [] args) { 3 int [] array = {87, 68, 94, 100, 83, 78, 85, 91, 76, 87}; 4 int total = 0; 5 6 //shto vleren e secilit element ne total-in 7 for(int counter = 0; counter < array.length; counter++) 8 total += array[counter];


5.3. Shembuj duke përdorur vargjet 59 9 10 System.out.println("Shuma e elementeve ne varg " + total); 11 } 12 } Shuma e elementeve te vargut: 849 5.3.4 Deklarimi for i zgjeruar Deklarimi for i zgjeruar iteron nëpër elementet e një vargu pa përdorur një numërues. Paraqesim se si të përdorim deklarimin for të zgjeruar me strukturat e ndërtuara të të dhënave. Sintaksa e një deklarimi for të zgjeruar është: 1 for(type parameter : arrayName) 2 statements; ku parameter ka një lloj të dhënash dhe identifikator (p.sh., int number), dhe arrayName është vargu nëpër të cilin iterohet. Lloji i të dhënave i parametrit duhet të jetë në përputhje me llojin e të dhënave të elementeve në varg. Siç e ilustron edhe shembulli në vijim, identifikatori përfaqëson vlerat e elementeve të njëpasnjëshme në vargun, në iterimet e njëpasnjëshme të ciklit. Programi në vijim përdor deklarimin for i zgjeruar për të mbledhur numrat e plotë në një varg të notave të studentëve. Parametri i for-it të zgjeruar është i llojit int, sepse array përmban vlerat int —cikli selekton një vlerë int nga vargu gjatë çdo iterimi. Deklarimi for i zgjeruar iteron nëpër vlerat e njëpasnjëshme në vargun (një nga një). Kreu i deklarimit mund të lexohet si "për çdo iterim, cakto elementin e ardhshëm të array në variablën number të llojit int, pastaj ekzekuto deklarimin vijues". Prandaj, për çdo iterim, identifikatori number përfaqëson një vlerë int në array. PROGRAMI 5.4: Përdorimi i deklarimit for të zgjeruar për të mbledhur numrat e plotë në një varg 1 public class EnhancedForTest { 2 public static void main(String [] args) { 3 int [] array = {87, 68, 94, 100, 83, 78, 85, 91, 76, 87}; 4 int total = 0; 5 6 //shto vleren e secilit element ne total-in 7 for(int number : array) 8 total += number; 9 10 System.out.println("Shuma e elementeve ne varg " + total); 11 } 12 } Shuma e elementeve te vargut: 849 Deklarimi for i zgjeruar thjeshton kodin për të iteruar nëpër një varg.


60 Kapitulli 5. Vargjet Deklarimi for i zgjeruar mund të përdoret vetëm për të ju qasur elementeve të vargut - nuk mund të përdoret për të modifikuar elementet e vargut. Nëse programi duhet të modifikojë elementet, përdorni deklarimin tradicional for, të kontrolluar nga numëruesi. Deklarimi for i zgjeruar mund të përdoret në vend të deklarimit for të kontrolluar nga numëruesi nëse kodi që iteron nëpër një varg nuk kërkon qasje në numëruesin që tregon indeksin e elementit aktual të vargut. Për shembull, mbledhja e numrave të plotë në një varg kërkon qasje vetëm në vlerat e elementeve —indeksi i secilit element është i parëndësishëm. Megjithatë, nëse një program duhet të përdoret një numërues për ndonjë arsye tjetër se vetëm të iterojë nëpër një varg (p.sh., për të printuar numrin e indeksit për secilën vlerë të elementit të vargut), duhet të përdoret deklarimi for i kontrolluar nga numëruesi. 5.4 Vargjet shumë-dimensionale Përveç vargjeve një-dimensionale (d.m.th., vargjet që ju nevojitet një indeks i vetëm për të ju qasur një elementi), mund të deklarojmë vargjet shumë-dimensionale: int [][] matrix = new int[3][4]; Ky deklarim krijon një varg dy-dimensional: 3 rreshta me 4 elemente (kolona). Nëse dëshirojmë ti qasemi elementit të parë të rreshtit të dytë, atëherë mund të indeksojmë këtë element me matrix[1][0] (mbani në mend, indeksimi fillon nga indeksi 0). Vargjet dy-dimensionale shpesh përdoren për të përfaqësuar tabelat e vlerave që përmbajnë informacione të organizuara në rreshta dhe kolona. Për t’ju qasur një elementi të vetëm të tabelës, duhet të përcaktojmë dy indekset. Indeksi i parë identifikon rreshtin e elementit dhe indeksi i dytë identifikon kolonën e tij. Vargjet që kërkojnë dy indekse për t’ju qasur një elementi të caktuar quhen vargje dy-dimensionale. (Vargjet shumë-dimensionale mund të kenë më shumë se dy dimensione.) JAVA nuk mbështet vargjet shumë-dimensionale në mënyrë të drejtpërdrejtë, por lejon të specifikoni vargjet një-dimensionale elementet e të cilave janë vargje një-dimensionale, duke arritur kështu efektin e njëjtë. Vargjet dy-dimensionale mund të inicializohen me deklarimin si vijon: int matrix[][] = {{0, 1, 2, 3}, {0, 4, 5, 6}, {0, 0, 6, 7}}; Kompajleri numëron numrin e vargjeve të mbivendosura një-dimensionale për të përcaktuar numrin e rreshtave në vargun matrix. Pastaj, numëron vlerat e vargut të mbivendosur një-dimensional për një rresht për të përcaktuar numrin e kolonave në atë rresht. Siç do të shohim më poshtë, kjo nënkupton që rreshtat mund të kenë gjatësi të ndryshme. Mënyra se si përfaqësohen vargjet shumë-dimensionale i bën ata shumë fleksibil. Në fakt, gjatësitë e rreshtave në vargun matrix nuk kërkohet që të jenë të njëjtë. Për shembull, int [][] matrix = {{1, 2}, {3, 4, 5}};


5.4. Vargjet shumë-dimensionale 61 krijon vargun matrix të numrave të plotë me dy elemente (të përcaktuar nga numri i vargjeve të mbivendosura një-dimensionale) që përfaqëson rreshtat e vargut dydimensional. Secili element i vargut matrix është një referencë në një varg njëdimensional të variablave int. Vargu matrix për rreshtin 0 është një varg njëdimensional me dy elemente (1 dhe 2), dhe vargu matrix për rreshtin 1 është një varg një-dimensional me tre elemente (3, 4 dhe 5). Programet gjithashtu mund të përdorin variabla për të përcaktuar dimensionet e vargut, sepse new krijon vargjet në kohën e ekzekutimit —jo në kohën e kompajlimit. Si me vargjet një-dimensionale, elementet e një vargu shumë-dimensional inicializohen kur krijohet objekti i vargut. Një varg shumë-dimensional në të cilin secili rresht ka numër të ndryshëm të kolonave mund të krijohet si vijon: int [][] matrix = new int[2][]; //krijon 2 rreshta b[0] = new int[5]; //krijon 5 kolona per rreshtin 0 b[1] = new int[3]; //krijon 3 kolona per rreshtin 1 Deklarimet e mësipërme krijojnë një varg dy-dimensional me dy rreshta. Rreshti 0 ka pesë kolona, dhe rreshti 1 ka tre kolona. 5.4.1 Shembull me vargjet dy-dimensionale: Paraqitja e vlerave të elementeve Programi i mëposhtëm paraqet inicializimin e vargjeve dy-dimensionale dhe përdorimin e cikleve të mbivendosura for për të vizituar çdo element të vargut. Në metodën main të klasës InitArray deklarohen dy vargje. PROGRAMI 5.5: Inicializimi i vargjeve dy-dimensionale 1 public class InitArray { 2 public static void main(String [] args) { 3 int [][] array1 = {{1, 2, 3}, {4, 5, 6}}; 4 int [][] array2 = {{1, 2}, {3}, {4, 5, 6}}; 5 6 System.out.println("Vlerat ne array1 sipas rreshtit jane"); 7 outputArray(array1); //printon array1 sipas rreshtit 8 9 System.out.println("Vlerat ne array2 sipas rreshtit jane"); 10 outputArray(array2); //printon array2 sipas rreshtit 11 12 public static void outputArray(int [][] array) { 13 //iteron neper rreshtat e vargut 14 for(int row = 0; row < array.length; row++) { 15 //iteron neper kolonat e rreshtit aktual 16 for(int col = 0; col < array[row].length; col++) { 17 System.out.println(array[row][col]); 18 } 19 System.out.println(); 20 } 21 } 22 } 23 }


62 Kapitulli 5. Vargjet Vlerat ne array1 sipas rreshtit jane 1 2 3 4 5 6 Vlerat ne array2 sipas rreshtit jane 1 2 3 4 5 6 Rreshtat 7 dhe 10 invokojnë metodën outputArray (rreshtat 12 - 21) për të paraqitur elementet e vargjeve array1 dhe array2, respektivisht. Metoda pranon një varg dy-dimensional. Deklarimi for printon rreshtat e vargut dy-dimensional. Në ciklin e jashtëm for, shprehja array.length përcakton numrin e rreshtave në vargun. Në ciklin e brendshëm for, shprehja array[row].length përcakton numrin e kolonave në rreshtin aktual të vargut. Kushti në deklarimin for të brendshëm mundëson ciklin të përcaktojë numrin e saktë të kolonave në secilin rresht. Parimisht, nuk ka kufizim në numrin e dimensioneve të një vargu. Në praktikë, megjithatë, rrallë-herë mund të hasni vargjet që kanë më shumë se tre dimensione 5.5 Përdorimi i vargjeve si parametra të një funksioni Vargjet mund gjithashtu të përdoren si parametra të një funksioni. Megjithatë, ekziston diçka speciale. Konsiderojmë programin vijues: PROGRAMI 5.6: Vargjet: Shembull 1 2 public class ArraysEx { 3 4 public static void increment(int a) { 5 a++; 6 } 7 8 public static void incrementFirst(int a[]) { 9 a[0]++; 10 } 11 12 public static void main(String [] args) { 13 int x = 1; 14 int y [] = {1}; 15 increment(x); 16 System.out.println("x = " + x); 17 increment(y[0]); 18 System.out.println("y[0] = " + y[0]); 19 incrementFirst(y); 20 System.out.println("y[0] = " + y[0]); 21 } 22 } Dalja e këtij programi do të jetë:


5.6. Stringjet: vargjet e karaktereve 63 x = 1 y[0] = 1 y[0] = 2 Dalja është ndoshta pak më ndryshe se çfarë keni pritur. Dy rezultatet e para tregojnë se funksioni increment nuk modifikon përmbajtjen e parametrave aktualë x dhe y[0]. Ne e presim këtë, meqë thirrja e funksionit përdor mekanizmin e kalimit të parametrit sipas-vlerës. Funksioni incremetFirst ndryshon përmbajtjen e y[0] kur y përdoret si një argument. Kështu që, kur funksioni incrementFirst përfundon ekzekutimin e tij, do të kemi y[0] == 2. Shkaku i kësaj është i qartë, vargu vetë nuk kalohet si argument i funksionit, por në vend të tij kalohet një tregues (pointer) në vargun. 5.6 Stringjet: vargjet e karaktereve Një variant i veçantë i një vargu është string-u, që nuk është asgjë më shumë se një varg i llojit char që përdoret për të ruajtur një tekst (d.m.th., një sekuencë të karaktereve). Ju mund të deklaroni dhe inicializoni një string si vijon: char text[] = "Hello"; Kjo krijon një string (d.m.th., një varg të llojit char) të emëruar text. Vargu është inicializuar me tekstin Hello. Mund të printojmë një string në ekran duke përdorur System.out.println. Për shembull, kodi në vazhdim System.out.println(text + "world!"); do të prodhojë daljen: Hello world! Mund të përdorim funksionin readLine për të lexuar një string nga tastiera. Për shembull: input.readLine(); lexon një rresht që është një string, nga tastiera kur përdoruesi jep një hyrje në program. Ka disa funksione të ndërtuara në JAVA që punojnë me stringjet. Këto funksione janë pjesë e paketës java.lang e cila është e importuar vetvetiu në momentin kur fillojmë krijimin e një klase të re. Le të shikojmë disa prej këtyre funksioneve. Të fillojmë me funksionin length(): text.length(); Funksioni length kthen gjatësinë në int të argumentit të tij, stringut text. Kështu që, deklarimi i mëposhtëm do të prodhojë si dalje 5 (që është madhësia e stringut text): String text = "Hello" System.out.println(text.length());


64 Kapitulli 5. Vargjet Funksioni substring përdoret për të nxjerrë një nën-string nga stringu. text.substring(int beginIndex, int endIndex); Funksioni substring nxjerr një nën-pjesë nga stringu nga karakteri në indeksin beginIndex deri në karakterin në indeksin endIndex - 1. Kështu që, gjatësia e nën-stringut është endIndex - beginIndex. Për shembull për stringun: String s = "Hello World!"; s.substring(6, 12); rezultati do të jetë si në vazhdim: World! Nëse dëshirojmë të krahasojmë përmbajtjet e dy stringjeve për barazi, atëherë duhet të përdorim funksionin equals. Krahasimi bëhet karakter për karakter në pozitat përkatëse të stringut. s0.equals(s1); Funksioni equals krahason të dy stringjet s0 dhe s1 për barazi. Ai kthen rezultat logjik true ose false. Nëse s0 është i barabartë me s1 (karakter për karakter) atëherë funksioni do të kthejë true, përndryshe do të kthejë false. Kështu që kodi në vazhdim: String s0 = "java"; String s1 = "java"; System.out.println(s0.equals(s1) ? ”Equal” : ”Not Equal”;) do të prodhojë daljen: Equal Poashtu për krahasim të dy stringjeve përdoret funksioni compareTo. s0.compareTo(s1); Funksioni compareTo krahason të dy stringjet s0 dhe s1. Ai kthen një rezultat numër të plotë. Nëse s0 është më i vogël se s1 atëherë funksioni kthen një numër negativ, nëse s0 është më i madh se s1 atëherë funksioni kthen një numër pozitiv më të madh se 0, dhe nëse s0 është i barabartë me s1 atëherë funksioni kthen 0. Këtu ’më e vogël se’ nënkupton se nëse i vendosim stringjet s0 dhe s1 në rendin alfabetik, atëherë s0 do të jetë i pari. Kështu që, fragmenti i mëposhtëm i kodit: PROGRAMI 5.7: Krahasimi i stringjeve për barazi 1 2 public class StringEx { 3 4 public static void compareStrings(String s0, String s1) { 5 if(s0.compareTo(s1) == 0) { 6 System.out.println("Stringjet nuk jane te barabarte"); 7 } 8 else if(s0.compareTo(s1) < 0) {


5.7. Lista e argumenteve me gjatësi të ndryshueshme 65 9 System.out.println("Stringu ’" + s0 + "’ eshte me i vogel se ’" + s1 + "’"); 10 } 11 else { 12 System.out.println("Stringu ’" + s0 + "’ eshte me i madh se ’" + s1 + "’"); 13 } 14 } 15 16 public static void main(String [] args) { 17 String s0 = "elephant"; 18 String s1 = "fly"; 19 compareStrings(s0, s1); 20 } 21 } do të prodhojë daljen: Stringu ’elephant’ eshte me i vogel se ’fly’ 5.7 Lista e argumenteve me gjatësi të ndryshueshme Me listat e argumenteve me gjatësi të ndryshueshme, mund të krijoni metoda që pranojnë një numër të paspecifikuar të argumenteve. Një lloj i të dhënave i ndjekur nga një ellipsis (...) në listën e parametrave të një metode tregon se metoda pranon një numër të ndryshueshëm të argumenteve të atij lloji të caktuar të të dhënave. Ky përdorim i ellipsis mund të paraqitet vetëm njëherë në një listë parametrash, dhe ellipsis së bashku me llojin e tij të të dhënave, duhet të vendoset në fund të listës së parametrave. Programi i mëposhtëm paraqet metodën average që pranon një sekuencë me gjatësi të ndryshueshme të numrave jo të plotë (doubles). JAVA trajton listën e argumenteve me gjatësi të ndryshueshme si një varg elementet e të cilit janë të të njëjtit lloj të të dhënave. Prandaj, trupi i metodës mund të manipulojë parametrin numbers si një varg të numrave jo të plotë (doubles). Metoda average ka një listë të argumenteve me gjatësi të ndryshueshme, kështu që ajo mund të llogarisë mesataren e aq argumenteve double sa thirrësi i kalon. Dalja tregon se secila thirrje në metodën average kthen vlerën e saktë. PROGRAMI 5.8: Përdorimi i listës së argumenteve me gjatësi të ndryshueshme 1 2 public class VarArgsTest { 3 4 public static void average(double... numbers) { 5 double total = 0.0; //inicializimi i variables total 6 7 //llogarit total duke perdorur deklarimin for te zgjeruar 8 for(double d : numbers) 9 total += d; 10 11 return total / numbers.length;


66 Kapitulli 5. Vargjet 12 } 13 14 public static void main(String [] args) { 15 double d1 = 10.0; 16 double d2 = 20.0; 17 double d3 = 30.0; 18 double d4 = 40.0; 19 20 System.out.println("d1 = " + d1 + "\nd2 = " + d2 + "\nd3 = " + d3 + "\nd4 " + d4); 21 22 System.out.println("Mesatarja e d1 dhe d2 eshte " + average (d1, d2)); 23 System.out.println("Mesatarja e d1, d2 dhe d3 eshte " + average(d1, d2, d3)); 24 System.out.println("Mesatarja e d1, d2, d3 dhe d4 eshte " + average(d1, d2, d3, d4)); 25 } 26 } do të prodhojë daljen: d1 = 10.0 d2 = 20.0 d3 = 30.0 d4 = 40.0 Mesatarja e d1 dhe d2 eshte 15.0 Mesatarja e d1, d2 dhe d3 eshte 20.0 Mesatarja e d1, d2, d3 dhe d4 eshte 25.0 Vendosja e një ellipsis që tregon një listë të argumenteve me gjatësi të ndryshueshme në mes të një liste parametrash është një gabim sintaksor. Një ellipsis mund të vendoset vetëm në fund të listës së parametrave. 5.8 Përdorimi i argumenteve të vijës komanduese Është e mundshme të kalojmë argumentet nga vija komanduese (ata njihen si argumente të vijës komanduese) në një aplikacion duke përfshirë parametrat e llojit String [] (d.m.th., një varg i String) në listën e parametrave të metodës main. Me marrëveshje, ky parametër quhet args. Kur një aplikacion ekzekutohet duke përdorur komandën java, JAVA kalon argumentet e vijës komanduese që paraqiten pas emrit të klasës në komandën java në metodën main të aplikacionit si String në vargun args. Numri i argumenteve të vijës komanduese merret duke iu qasur atributit length të vargut. Shembulli i ardhshëm përdor argumentet e vijës komanduese për të përcaktuar madhësinë e një vargu, vlerën e elementit të parë dhe një numër që përfaqëson inkrementimin për të llogaritur vlerat e elementeve tjera të vargut. Komanda java InitArray 5 0 4


5.8. Përdorimi i argumenteve të vijës komanduese 67 kalon tre argumente 5, 0 dhe 4, në aplikacionin InitArray. Argumentet e vijës komanduese janë të ndarë me hapësirë, jo me presje. Kur kjo komandë ekzekutohet, metoda main e klasës InitArray pranon vargun me tre elemente args (d.m.th., args.length është 3) në të cilin args[0] përmban String "5", args[1] përmban String "0" dhe args[2] përmban String "4". Programi në vazhdim përcakton se si të përdorim këto argumente —konverton tre argumentet e vijës komanduese në vlera int dhe përdor ato për të inicializuar një varg. Kur programi ekzekutohet, nëse args.length nuk është 3, programi printon një mesazh gabimi dhe terminon. Përndryshe, inicializon dhe paraqet vargun bazuar në vlerat e argumenteve të vijës komanduese. Metoda static parseInt e klasës Integer konverton argumentin String të tij në një int. PROGRAMI 5.9: Inicializimi i një vargu duke përdorur argumentet e vijës komanduese 1 2 public class InitArray { 3 4 public static void main(String [] args) { 5 //kontrollo numrin e argumenteve te vijes komanduese 6 if(args.length != 3) 7 System.out.println("Gabim: Ri-shenoni komanden e tere, duke perfshire madhesine e vargut, vleren fillestare dhe vleren inkrementuese"); 8 else { 9 //marrja e madhesise se vargut nga argumenti i pare i vijes komanduese 10 int arrayLength = Integer.parseInt(args[0]); 11 int [] array = new int[arrayLength]; //krijimi i vargut 12 13 //marrja e vleres fillestare dhe vleres inkrementuese nga argumentet e vijes komanduese 14 int initialValue = Integer.parseInt(args[1]); 15 int increment = Integer.parseInt(args[2]); 16 17 //llogaritja e vlerave per cdo element te vargut 18 for(int counter = 0; counter < array.length; counter++) 19 array[counter] = initialValue + increment * counter ; 20 21 System.out.println("Indeksi \t Vlera"); 22 23 //paraqitja e indeksit dhe vleres se vargut 24 for(int counter = 0; counter < array.length; counter++) 25 System.out.println(counter + "\t" + array[counter]) ; 26 } 27 } 28 } java InitArray Gabim: Ri-shenoni komanden e tere, duke perfshire madhesine e vargut, vleren fillestare dhe vleren inkrementuese


68 Kapitulli 5. Vargjet java InitArray 5 0 4 Indeksi Vlera 0 0 1 4 2 8 3 12 4 16 java InitArray 8 1 2 Indeksi Vlera 0 1 1 3 2 5 3 7 4 9 5 11 6 13 7 15 Dalja e ekzekutimit të parë të programit tregon që aplikacioni pranon një numër të pamjaftueshëm të argumenteve të vijës komanduese. Ekzekutimi i dytë përdor argumentet 5, 0 dhe 4 për të specifikuar madhësinë e vargut (5), vlera e elementit të parë (0) dhe vlera inkrementuese për secilën vlerë në vargun (4). Dalja korresponduese tregon se këto vlera krijojnë një varg që përmban numrat e plotë 0, 4, 8, 12 dhe 16. Dalja e ekzekutimit të tretë tregon se argumentet e vijës komanduese 8, 1 dhe 2 prodhojnë një varg me 8 elemente të cilët janë numrat e plotë tek jo-negativë nga 1 deri në 15.


5.9. Detyra praktike 69 5.9 Detyra praktike 5.9.1 Vargjet Le të deklarojmë a si vijon: int a[] = new int[100]; Në detyrat e mëposhtme nevojitet të zhvilloni programe të vogla për probleme relativisht të thjeshta. Detyra 5.9.1.1 Maksimumi Shkruani një fragment kodi që llogarit vlerën maksimale në vargun a.  Detyra 5.9.1.2 Maxima Shkruani një fragment kodi që numëron numrin e indekseve k ku a[k] është maksimal.  Detyra 5.9.1.3 Afërsia Ne i quajmë dy indekse p dhe q të lidhur nëse dhe vetëm nëse a[p] == q dhe a[q] == p. Printoni një listë të të gjithë çifteve të lidhura (p, q) për të cilët p <= q.  Detyra 5.9.1.4 Hapat Shkruani një fragment kodi që numëron numrin e indekseve k për të cilët a[k] < a[k + 1].  Detyra 5.9.1.5 Nënsekuenca më e gjatë në varg Shkruani një fragment kodi që llogarit gjatësinë e (nën)sekeuncës më të gjatë në vargun a.  5.9.2 Modifikimi i vargjeve Detyra 5.9.2.1 Faktorieli Shkruani një fragment kodi që cakton faktorielin e k (d.m.th., k!) në a[k] për çdo indeks valid k të vargut a.  Detyra 5.9.2.2 Histogram Supozoni se vargu a përmban vetëm shifra decimale. Numëroni për çdo shifër k numrin e paraqitjeve të shifrës k në vargun a dhe ruaji ato në h[k]. 


70 Kapitulli 5. Vargjet 5.9.3 Vargjet shumë-dimensionale Detyra 5.9.3.1 Trekëndëshi i Pascal-it Në vazhdim është dhënë një pjesë fillestare e trekëndëshit të Pascal-it: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 Në trekëndëshin e Pascal-it, secili numër (jo i barabartë me një) është shuma e fqinjut të tij të sipërm dhe të sipërm në të majtë. Shkruani një program që ruan 15 rreshtat e parë të trekëndëshit të Pascal-it në një varg dy-dimensional. Programi duhet gjithashtu të printojë këto rreshta të trekëndëshit në ekran. 


71 Kapitulli 6 Rekursioni Recursion is recursion is recursion is recursion is recursion is recursion is recursion is Rekursioni është fenomeni që një funksion definohet në aspekt të vetes (me fjalë tjera, ai thërret veten). Nuk ka ndonjë dallim ndërmjet thirrjes së një funksioni rekursiv dhe një funksioni të rregullt. Rekursioni nuk është ndërtim i një gjuhe të re. Është thjesht një zbatim i asaj që keni mësuar tashmë në lidhje me thirrjet e funksionit. Megjithatë, kërkon një stil të ri të të menduarit në lidhje me zgjidhjet e problemeve. Çelësi është që nuk zgjidhni problemin në mënyrë të drejtpërdrejtë, por reduktoni problemin në një instancë më të vogël të saj. Në fillim, ky stil i të menduarit mund të jetë pak konfuz. Pasi të mësoheni me atë, ju do ta shihni se ai rezulton në algoritme të mira, kompakte dhe elegante që zgjidhin probleme të komplikuara shumë më lehtë se algoritmet jo-rekursive. Gjykimi rekursiv është aktualisht shumë i zakonshëm në matematikë. Për shembull, bashkësia e numrave natyrorë rekursivisht definohet si vijon: • 0 është një numër natyror. • x është një numër natyror nëse x - 1 është një numër natyror (për x > 0). Rasti i dytë në këtë definim është rekursiv: definon një numër natyror në aspekt të një numri natyror! Shpesh, rekursioni është një mënyrë natyrale dhe elegante për të definuar funksionet (matematikore). Megjithatë, duhet të jeni të kujdesshëm. Nëse implementoni funksionet rekursive në një gjuhë programuese, pastaj duhet të sigurohuni se funksioni terminon, d.m.th., nuk duhet të thërrasë veten pafundësisht. Për shembull, funksioni i mëposhtëm f në numrat natyrorë është rekursiv, por nuk është definuar mirë: f(n) = f(n + 1) − 1 Problemi është që funksioni iteron përgjithmonë, pa arritur afër në një zgjidhje. Megjithatë, nëse ne zgjerojmë definimin me një rast bazë, atëherë definimi është krejtësisht mirë: f(0) = 0, f(n) = f(n + 1) − 1 Vini re se funksioni f aktualisht është funksioni identitet, d.m.th., funksioni f(n) = n. Në përgjithësi, preferojmë të definojmë një funksion rekursiv në aspekt të një rasti më të vogël (d.m.th., vlera më e vogël për argument(et)). Prandaj, ne transformojmë,


72 Kapitulli 6. Rekursioni duke përdorur veprimet e thjeshta aritmetikore, definimin e mësipërm në definimin ekuivalent të mëposhtëm (dhe të preferuar): f(0) = 0, f(n + 1) = f(n) + 1 Në JAVA, mund të implementohen funksionet rekursive natyrshëm meqë JAVA lejon vetë-referencat e funksioneve. Përsërisim, në implementimet aktuale të funksioneve rekursive, duhet të keni kujdes që funksionet të terminojnë. Për çdo thirrje rekursive të një funksioni, kompajleri gjeneron kodin që rezervon memorien për të gjitha variablat lokale dhe parametrat e funksionit. Këto variabla ruhen në një pjesë të memories që quhet stek (ang. stack). Programeri nuk duhet të shqetësohet në lidhje me stekun dhe alokimin e memories nga steku. E gjithë kjo trajtohet nga kompajleri. Megjithatë, steku është i kufizuar në madhësi, kështu që rekursioni indefinitiv do të kalojë jashtë hapësirës së stekut dhe programi do të thyhet: ne e quajmë këtë stack overflow. Duke hartuar kujdesshëm funksionet rekursive dhe gjithmonë duke kontrolluar nëse do të arrijmë rastin(et) bazë, mund ta shmangim atë. Secili problem që mund të zgjidhet në mënyrë iterative (për shembull, duke përdorur një cikël while), mund gjithashtu të zgjidhet duke përdorur rekursionin. E kundërta është gjithashtu e vërtetë: secili algoritëm rekursiv mund të konvertohet në një algoritëm iterativ. Megjithatë, konvertimi i një algoritmi rekursiv në një algoritëm iterativ mund të jetë i komplikuar, meqë mund të jetë e nevojshme që vetë të implementohet (simulohet) steku. Në përgjithësi, nëse ju nevojitet të zgjedhni ndërmjet një algoritmi rekursiv dhe iterativ, versioni iterativ ka një përparësi meqë kodi iterativ nuk është (shumë) më i komplikuar se kodi rekursiv. Janë dy arsye kryesore për këtë: një algoritëm iterativ është zakonisht më i shpejtë dhe nuk ka rrezik të thyerjes së programit për shkak të gabimit stack overflow. 6.1 Shembull: funksioni rekursiv për faktorielin Për ta bërë shpjegimin e rekursionit më pak abstrakt le të marrim një shembull konkret. Faktorieli i një numri natyror rekursivisht definohet si vijon: 0! = 1 n! = n · (n − 1)!+ për një numër natyror n > 0 Në një funksion rekursiv gjithashtu dallojmë një ose më shumë raste bazë dhe një ose më shumë raste rekursive. Rastet bazë janë rastet ku përgjigjja jepet në mënyrë të drejtpërdrejtë. Zakonisht, rasti bazë jepet për argumentet më pak të mundshme të funksionit. Definimi rekursiv i faktorielit ka një rast bazë: 0! = 1. Rastet rekursive kërkojnë të paktën një hap rekursiv për të llogaritur përgjigjen. Për një definim të saktë rekursiv, është e nevojshme që argumentet në hapin rekursiv të jenë gjithmonë më të vegjël në një farë kuptimi se argumentet në hapin aktual. Këtu, ’më e vogël’ nuk duhet të jetë ’më e vogël’ në kuptimin numerik, por më afër në një nga rastet bazë.


6.2. Shembull tjetër: Fibonacci 73 Për shembull, llogaritja e 6! redukton në llogaritjen e 5!, ku n = 5! është më afër rastit bazë n = 0 se argumenti origjinal n = 6. Duke zbatuar rekursivisht definimin mund të llogarisim 6! si vijon: 6! = 6 · 5! = 6 · 5 · 4! = 6 · 5 · 4 · 3! = 6 · 5 · 4 · 3 · 2! = 6 · 5 · 4 · 3 · 2 · 1! = 6 · 5 · 4 · 3 · 2 · 1 · 0! = 6 · 5 · 4 · 3 · 2 · 1 · 1 = 720 Një implementim rekursiv i faktorielit në JAVA ngjan me definimin e mëposhtëm: 1 int fact(int n) { 2 if(n == 0) { 3 /*best case*/ 4 return 1; 5 } 6 /*recursive case*/ 7 return n * fact(n - 1); 8 } Sigurisht, është e lehtë të implementojmë një funksion iterativ për faktorielin. 1 int fact(int n) 2 int f = 1; 3 while(n > 0) { 4 f *= n; 5 n--; 6 } 7 return f; 8 } Cili implementim është më i mirë, është çështje e preferencës. Funksioni rekursiv mund të jetë pak më i ngadalshëm, meqë nevojiten të kryhen operacionet e stekut për çdo cdo thirrje rekursive të funksionit. Në anën tjetër, kompajlerët modernë janë shumë të mirë në optimizimin e kodit rekursiv, dhe ka shumë gjasa që kompajleri do të konvertojë funksionin rekursiv në kodin iterativ të makinës. Në këtë rast nuk do të vini re ndonjë dizavantazh të performancës për implementimin rekursiv. 6.2 Shembull tjetër: Fibonacci Sekuenca Fibonacci është emëruar pas Leonardo Fibonacci, gjithashtu i njohur edhe si Leonardo i Pisës (rreth 1170 - 1250 AD). Ai prezantoi sekuencën si një model matematikor për rritjen e një popullimi të lepujve. Sekuenca është nxjerrë nga supozimet e mëposhtme: • Fillojmë me një çift të lepujve të rinjë. • Një çift i lepujve rritet pas një viti. • Çdo vit, një çift i rritur i lepujve prodhon pasardhës: një çift i ri i lepujve. • Lepujt nuk vdesin.


74 Kapitulli 6. Rekursioni Verifikoni vetë që numri i çifteve të lepujve të rritur për vit jepet nga sekuenca e mëposhtme: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ... Prezantojmë shënimin F(n) për numrin e çifteve të lepujve të rritur në vitin n. Nuk është e vështirë për të gjetur se funksioni F(n) jepet nga përsëritja (rekurenca) e mëposhtme: F(0) = 0 F(1) = 1 F(n) = F(n − 2) + F(n − 1) për një numër natyror n > 1 Qartësisht, rekursioni për F(n) ka dy raste bazë: rastet n = 0 dhe n = 1. Në të dy rastet, përgjigjja jepet në mënyrë të drejtpërdrejtë. Na duhen dy raste bazë si një rezultat i strukturës i rastit rekursiv. Në rastin rekursiv, për të llogaritur F(n), na duhen vlerat e F(n − 1) dhe F(n). Prandaj, për tu siguruar se rekursioni terminon, na duhen dy raste bazë të njëpasnjëshme: një rast bazë tek dhe një çift. Bindni veten që rekursioni nuk terminon nëse përjashtojmë një nga rastet bazë. Është e lehtë të implementojmë funksionin fibonacci rekursivisht në JAVA: 1 int fibonacci(int n) { 2 /*2 rastet baze: F(0) dhe F(1) = 1*/ 3 if((n == 0) || (n == 1)) { 4 return n; 5 } 6 /*rasti rekursiv*/ 7 return fibonacci(n - 2) + fibonacci(n - 1); 8 }


6.3. Detyra praktike 75 6.3 Detyra praktike 6.3.1 Rekursioni Në detyrat e mëposhtme nevojitet të zhvilloni programe të vogla për probleme relativisht të thjeshta. Detyra 6.3.1.1 Segment sum Shkruani një funksion rekursiv segmentSum që implementon specifikimin e mëposhtëm: int segmentSum(int length, int seq [], int left, int right) { // PRE: 0 <= left <= right <= length // RETURN: (SUM i: left <= i < right: seq[i]) }  Detyra 6.3.1.2 Segment maximum Shkruani një funksion rekursiv segmentMax që implementon specifikimin e mëposhtëm: int segmentMax(int length, int seq [], int left, in tright) { // PRE: 0 <= left <= right <= length // RETURN: (SUM i: left <= i < right: seq[i]) }  Detyra 6.3.1.3 Numri i njësheve në përfaqësimin binar Shkruani një funksion rekursiv oneBits(int n) që kthen numrin e biteve njëshe në përfaqësimin binar të numrit të plotë pozitiv n. Për shembull, përfaqësimi binar i numrit 42 është 00101010, pra oneBits(42) duhet të kthejë 3.  Detyra 6.3.1.4 Numri i nënsekuencave me shumën/prodhimin e dhënë Jepet një varg arr me 100 numra të plotë: int arr[100]; Një nënsekuencë e arr nuk është e detyrueshme të jetë një sekuencë e vazhdueshme e elementeve të marrë nga vargu arr. Vini re se kjo dallon nga një bashkësi, meqë një element mund të paraqitet më shumë se njëherë. Shkruani një funksion rekursiv subSum që llogarit numrin e nënsekuencave të arr shuma e të cilave është e barabartë me një sum të dhënë. Shkruani një funksion rekursiv të ngjashëm subProduct që llogarit numrin e nënsekuencave me një prodhim të dhënë. 


76 Kapitulli 6. Rekursioni Detyra 6.3.1.5 Numri i nënsekuencave me një gjatësi të dhënë Shkruani një funksion që llogarit numrin e nënsekuencave me gjatësinë m nga një varg me një gjatësi të dhënë n.  Detyra 6.3.1.6 Printimi i të gjitha nënsekuencave me një gjatësi të dhënë Shkruani një funksion që printon në ekran të gjitha nënsekuencat me gjatësinë m nga një varg me gjatësinë e dhënë n.  Detyra 6.3.1.7 Numri i faktorëve numra të thjeshtë Shkruani një funksion rekursiv numPrimeFactors(int n) që kthen numrin e faktorëve numra të thjeshtë të numrit të plotë pozitiv n. Për shembull, numPrimeFactors(24) duhet të kthejë 4, meqë 24 == 2 * 2 * 2 * 3.  Detyra 6.3.1.8 Numri i faktorëve unikë numra të thjeshtë Shkruani një funksion rekursiv numUniquePrimeFactors(int n) që kthen numrin e faktorëve unikë që janë numra të thjeshtë të numrit të plotë pozitiv n. Për shembull, numUniquePrimeFactors(24) duhet të kthejë 2, meqë janë vetëm dy faktorë unikë numra të thjeshtë: 2 dhe 3. 


77 Shtesa A Shembuj dhe Detyra A.1 Konceptet bazë të programimit Detyra. A.1.1 Një kompani paguan pagën e plotë për 40 orët e para të punuara për secilin punëtor dhe gjysmën e pagës për të gjitha orët e punës mbi 40. Shkruani një program në JAVA që përcakton pagën bruto për secilin nga punëtorët. Si hyrje jepet një listë e punëtorëve, numri i orëve të punuara për ata punëtorë dhe pagën për orë. Programi duhet të pranojë këtë informacion për secilin punëtor, pastaj duhet të përcaktojë dhe paraqesë pagën bruto të punëtorit. Përdorni klasën Scanner për të pranuar të dhënat hyrëse. Detyra. A.1.2 Le të supozojmë që tejkalimi i shpejtësisë dënohet me 30 euro plus 5 euro për çdo km/orë mbi kufirin plus një dënim prej 200 eurove për çdo shpejtësi mbi 180 km/orë. Shkruani një program që pranon kufirin e shpejtësisë dhe shpejtësinë e matur dhe tregon nëse shpejtësia ishte legale ose mbi-shpejtësi dhe nëse është e dyta programi le të tregon se sa do të ishte dënimi. Detyra. A.1.3 Të shkruhet një program në JAVA që mundëson konvertimin e orëve të dhëna si hyrje në sekonda. Detyra. A.1.4 Të shkruhet programi që realizon konvertimin e temperaturës nga Celsius në Farenheit, duke përdorur formulën: c = (f − 32) · 5 9 . Detyra. A.1.5 Të shkruhet programi në JAVA që si hyrje merr gjatësitë e tre brinjëve të një trekëndëshi dhe si rezultat tregon nëse trekëndëshi është këndrejtë, barabrinjës, barakrahësh apo brinjëndryshëm. Detyra. A.1.6


78 Shtesa A. Shembuj dhe Detyra Të shkruhet programi në JAVA që si hyrje merr një numër të plotë dhe si rezultat tregon nëse numri është çift apo tek. Detyra. A.1.7 Të shkruhet programi në JAVA që si hyrje merr një numër të plotë dhe si rezultat tregon nëse numri është natyror apo jo. Detyra. A.1.8 Të shkruhet programi në JAVA që si hyrje merr tre numra të plotë a, b dhe c si hyrje dhe si rezultat tregon nëse këta tre numra formojnë një treshe Pitagoriane. Detyra. A.1.9 Punëtorët në një kompani paguhen për orët e punës me 7.25 euro për 40 orë në javë. Ata do të paguhen për çdo orë shtesë me gjysmën e pagës së tyre bazë. Për më tepër, ata do të pranojnë një përqindje për shitjet që ata realizojnë përderisa drejtojnë arkën. Përqindja bazohet në formulën e mëposhtme: Vëllimi i shitjeve Përqindja 1.0 - 99.99 euro 5% të shitjeve totale 100.00 - 299.99 euro 10% të shitjeve totale ≤ 300.00 euro 15% të shitjeve totale Shkruani një program në JAVA që merr si hyrje numrin e orëve të punuara dhe numrin e përgjithshëm të shitjeve, llogarit pagën dhe si rezultat e paraqet atë si rezultat. Detyra. A.1.10 Janë dy rrathë C1 me rrezen r1, koordinatën e qendrës (x1, y1) dhe C2 me rrezen r2 dhe koordinatën e qendrës (x2, y2). Shkruani një program në JAVA i cili teston nëse: ”C2 është në C1”, ”C1 është në C2”, ”Perimetri i C1 dhe C2 priten”, dhe ”C1 dhe C2 nuk janë të mbivendosur”. Detyra. A.1.11 Shkruani një program në JAVA që kthen si rezultat nëse viti i dhënë si hyrje është vit i brishtë apo jo. Viti është i brishtë nëse është i plotëpjestueshëm me 4 por jo me 100 (p.sh., 1796 është vit i brishtë sepse është i plotëpjestueshëm me 4 por jo me 100). Viti që është i plotëpjestueshëm edhe me 4 edhe me 100 është vit i brishtë nëse është gjithashtu i plotëpjestueshëm me 400 (p.sh., 2000 është vit i brishtë, por viti 1800 nuk është). Detyra. A.1.12 Të shkruhet një program në JAVA i cili simulon kalkulatorin që kryen operacionet themelore aritmetikore: mbledhjen (+), zbritjen (-), shumëzimin (+), dhe pjesëtimin (/). Programi i jep mundësi përdoruesit të zgjedhë operacionin që dëshiron ta kryejë nga menu-ja. Poashtu programi duhet të mundësojë përdoruesin të japë vlerat e operandeve si hyrje.


A.1. Konceptet bazë të programimit 79 Detyra. A.1.13 Shkruani një program në JAVA i cili kontrollon nëse tre gjatësitë e dhëna të tre brinjëve formojnë një trekëndësh të drejtë. Programi printon "Po"nëse brinjët e dhëna formojnë një trekëndësh të drejtë, përndryshe printo "Jo". Detyra. A.1.14 Shkruani një program në JAVA i cili kontrollon nëse një pikë P(x, y) është në një trekëndësh ose jo. Një trekëndësh është i formuar nga tre pika A(x1, y1), B(x2, y2) dhe C(x3, y3). Sqarim: Së pari duhet të llogaritni sipërfaqen e trekëndëshit ABC sipas formulës S = [x1(y2 - y3) + x2(y3 - y1) + x3(y1 - y2)] / 2. Llogaritni sipërfaqen e trekëndëshit PAB duke përdorur formulën e njëjtë. Le të jetë S1. Llogaritni sipërfaqen e trekëndëshit PBC. Le të jetë S2. Llogaritni sipërfaqen e trekëndëshit PAC. Le të jetë S3. Nëse P është në trekëndësh, atëherë A1 + A2 + A3 duhet të jetë e barabartë me A. Detyra. A.1.15 Shkruani një program në JAVA i cili gjen numrin e ditëve në një muaj, nëse si hyrje jepen muaji dhe viti (në numër të plotë). Detyra. A.1.16 Shkruani një program në JAVA i cili merr një numër të plotë nga përdoruesi, ndërmjet 1 dhe 7, dhe paraqet emrin e ditës së javës. Detyra. A.1.17 Shkruani një program në JAVA i cili zgjidh një ekuacion kuadratik nëse si hyrje jepen koeficientët a, b dhe c (përdorni if, else if dhe else). Detyra. A.1.18 Shkruani një program në JAVA i cili teston nëse një vlerë e dhënë double apo float është vlerë e fundme me presje dhjetore ose jo. Detyra. A.1.19 Shkruani një program në JAVA i cili merr nga përdoruesi një karakter të vetëm nga alfabeti. Programi printon zanore ose bashkëtingëllore, varësisht prej hyrjes së përdoruesit. Nëse hyrja e përdoruesit nuk është një shkronjë (ndërmjet a dhe z ose A dhe Z), ose është një string me gjatësi > 1, printon një mesazh gabimi. Detyra. A.1.20 Shkruani një program në JAVA i cili pranon një numër të plotë (n) dhe llogarit vlerën e n + nn + nnn.


80 Shtesa A. Shembuj dhe Detyra Detyra. A.1.21 Shkruani një program në JAVA i cili llogarit shumën e dy numrave të plotë dhe kthen true nëse shuma është e barabartë me një numër të tretë të plotë. Detyra. A.1.22 Shkruani një program në JAVA që pranon tre numra të plotë nga përdoruesi dhe kthen true nëse dy ose më shumë prej tyre kanë të njëjtë shifrën më të djathtë. Detyra. A.1.23 Shkruani një program në JAVA i cili merr tre numra prej përdoruesit dhe printon numrin më të madh. Detyra. A.1.24 Shkruani një program në JAVA i cili kontrollon nëse tre gjatësi të brinjëve (numra të plotë) mund të formojnë një trekëndësh ose jo. Detyra. A.1.25 Shkruani një program në JAVA i cili teston nëse një numër i dhënë (numër i plotë pozitiv) është një katror perfekt i një numri ose jo. Detyra. A.1.26 Shkruani një program në JAVA i cili pranon tre numra të plotë nga përdoruesi dhe kthen true nëse numri i dytë është më i madh se numri i parë dhe numri i tretë është më i madh se numri i dytë.


A.2. Iterimi 81 A.2 Iterimi Detyra. A.2.1 Një email adresë ka një format valid sipas së cilës identifikohet adresa. Formati i vetëm i adresave që përdoren ditët e sotme përfshin emrin e përdoruesit, simbolin ‘@’ dhe domenin. Të shkruhet programi që identifikon nëse stringu i dhënë si hyrje është email adresë valide apo jo. Detyra. A.2.2 Të shkruhet një program në JAVA që si hyrje merr një string dhe si rezultat kthen numrin e zanoreve që përmban stringu. (P.sh. Stringu është “Përshëndetje nga JAVA”. Rezultati duhet të jetë ‘a’ është paraqitur 3 herë, ‘e’ është paraqitur 2 herë, ‘ë’ është paraqitur 2 herë, ‘i’ është paraqitur 0 herë, ‘o’ është paraqitur 0 herë, ‘u’ është paraqitur 0 herë, ‘y’ është paraqitur 0 herë). Detyra. A.2.3 Shkruani një program në JAVA i cili lexon një numër të plotë n dhe gjen numrin e kombinimeve të a, b, c dhe d (0 ≤ a, b, c,d ≤ 9) ku (a + b + c + d) duhet të jetë e barabartë me n. Detyra. A.2.4 Shkruani një program në JAVA i cili numëron shkronjat, hapësirat, numrat dhe karakteret tjera në një string të dhënë si hyrje. Detyra. A.2.5 Të implementohet një funksion në JAVA që llogarit faktorielin e një numri. Të realizohet kjo detyrë duke përdorur ciklin si strukturë përsëritëse. Detyra. A.2.6 Të implementohet një funksion në JAVA që llogarit faktorielin e një numri. Të realizohet kjo detyrë duke përdorur rekursionin si strukturë përsëritëse. Detyra. A.2.7 Të implementohet një funksion në JAVA që llogarit sekuencën fibonacci. Të realizohet kjo detyrë duke përdorur rekursionin. Detyra. A.2.8 Të krijohet një funksion në JAVA që mundëson konvertimin e numrit decimal në binar. Detyra. A.2.9 Të shkruhet programi që mundëson të llogaritet shumëzimi i numrave përmes mbledhjes.


82 Shtesa A. Shembuj dhe Detyra Detyra. A.2.10 Një kompani e madhe paguan shitësit e tij në bazë të komisionit. Shitësi merr $200 për javë plus 9% të shitjeve të tyre bruto për atë javë. Për shembull, një shitës që shet mall me vlerë $5000 në një javë merr $200 plus 9% të $5000, ose një shumë prej $650. Si hyrje ofrohet një listë e produkteve të shitura nga secili shitës. Vlerat e këtyre produkteve janë si vijon: Produkti Vlera 1 239.99 2 129.75 3 99.95 4 350.89 Shkruani një aplikacion në JAVA që merr si hyrje produktet e shitura të një shitësi për javën e fundit, llogarit dhe paraqet fitimet e këtij shitësi. Nuk ka kufizim për numrin e produkteve që ai mund të shet. Detyra. A.2.11 Një numër i Armstrongut është një numër i plotë pozitiv që është i barabartë me shumën e shifrave të tij të ngritur në fuqinë e numrit të shifrave. Për shembull, 371 ka tre shifra, 3 3 + 7 3 + 1 3 = 27 + 343 + 1 = 371. Shkruani një program që pranon një numër të plotë pozitiv dhe përcakton nëse numri është i Armstrongut. Detyra. A.2.12 Një numër i përsosur është një numër i plotë pozitiv që është i barabartë me shumën e pjesëtuesëve të tij. Një pjesëtues është një numër i plotë pozitiv, përveç vetë numrit, që e ndan numrin në mënyrë të barabartë (d.m.th., pa pjesën e mbetur). Për shembull, 6 është një numër i përsosur sepse shuma e pjesëtuesëve të tij 1, 2 dhe 3 është e barabartë me 6. 8 nuk është një numër i përsosur sepse 1, 2, 4 nuk japin 8 si rezultat. Shkruani një program që pranon një numër të plotë pozitiv dhe përcakton nëse numri është i përsosur. Gjithashtu, shfaqni të gjithë pjesëtuesit e numrit. Detyra. A.2.13 Të shkruhet programi që jep si rezultat numrin e shifrave të një numri të plotë të marrë si hyrje. Detyra. A.2.14 Të shkruhet programi që llogarit shumën e numrave nga 1 deri në n. Detyra. A.2.15 Të shkruhet programi që llogarit prodhimin e numrave nga 1 deri në n. Detyra. A.2.16 Të shkruhet programi që mundëson të llogaritet fuqizimi i numrave përmes mbledhjes.


A.2. Iterimi 83 Detyra. A.2.17 Në një trekëndësh kënddrejtë gjatësitë e brinjëve të tij janë numra të plotë. Bashkësia e tre numrave të plotë për gjatësitë e brinjëve të një trekëndëshi kënddrejtë quhet treshja Pitagoriane. Gjatësitë e tre brinjëve duhet të plotësojnë kushtin që shuma e katrorëve të dy kateteve është e barabartë me katrorin e hipotenuzës. Shkruani një program në JAVA që paraqet një tabelë të tresheve Pitagoriane (kateta1, kateta2, hipotenuza), për kufirin deri në 500. Përdorni një cikël me tre for-a të mbivendosur që provon të gjitha mundësitë. Detyra. A.2.18 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 8 7 6 5 4 3 8 7 6 5 4 8 7 6 5 8 7 6 8 7 8 Detyra. A.2.19 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: x o o o x x x o x x x x x x x x x o x x x o o o x Detyra. A.2.20 Shkruani një program në JAVA i cili paraqet modelin si më poshtë sipas një numri të dhënë si hyrje. Për shembull, nëse numri në hyrje është 10, atëherë dalja duhet të jetë: 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10


84 Shtesa A. Shembuj dhe Detyra Detyra. A.2.21 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: 1 1 1 1 1 0 0 2 2 0 0 0 3 0 0 0 4 4 0 0 5 5 5 5 5 Detyra. A.2.22 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: x x x x x x o o o x x o o o x x o o o x x x x x x Detyra. A.2.23 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: x o o o o x x o o o x x x o o x x x x o x x x x x Detyra. A.2.24 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: 1 2 3 4 5 6 7 8 9 10 Detyra. A.2.25 Shkruani një program në JAVA i cili paraqet modelin si më poshtë me një numër i cili përsëritet në një rresht: 1 2 2 3 3 3 4 4 4 4


A.2. Iterimi 85 Detyra. A.2.26 Shkruani një program në JAVA i cili paraqet strukturën vijuese: ******** ******* ****** ***** **** *** ** * Detyra. A.2.27 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: @ @@ @@@ @@@@ @@@@@ @@@@@@ @@@@@@@ @@@@@@@@ Detyra. A.2.28 Shkruani një program në JAVA i cili printon trekëndëshin e Floyd-it. Për shembull nëse hyrja është 5, atëherë dalja do të jetë: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Detyra. A.2.29 Shkruani një program në JAVA i cili printon trekëndëshin e Pascal-it. Për shembull nëse hyrja është 6, atëherë dalja do të jetë: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1


86 Shtesa A. Shembuj dhe Detyra Detyra. A.2.30 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: 0 3 0 2 0 1 0 0 1 3 1 2 1 1 2 3 2 2 3 3 Detyra. A.2.31 Shkruani një program në metodën main() i cili pasi të jetë ekzekutuar duket kështu: 0 0 1 0 1 1 2 0 2 1 2 2 3 0 3 1 3 2 3 3 Detyra. A.2.32 Detyra juaj është të zhvilloni një pjesë të vogël të softuerit të spreadsheet. Shkruani një program në JAVA i cili mbledh kolonat dhe rreshtat e një tabele të dhënë: Për hyrjen 4 rreshta/kolona: 25 69 51 26 68 35 29 54 54 57 45 63 61 68 47 59 Rezultati: 25 69 51 26 171 68 35 29 54 186 54 57 45 63 219 61 68 47 59 235 208 229 172 202 811 Detyra. A.2.33 Shkruani një program që printon numrat 10 deri në 49 si në vijim: 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Zhvilloni kodin ashtu që të punojë me çfarëdo rangu numrash. Kjo mund të bëhet në dy mënyra: me deklarimet for të mbivendsoura ose me aritmetikën modulare (nëse pjesëtoni një numër me 10 dhe mbetja është 9, atëherë numri është 9, 19, 29...).


A.2. Iterimi 87 Detyra. A.2.34 Shkruani një program në JAVA i cili paraqet strukturën vijuese rombike sipas një numri të dhënë si hyrje. Nëse numri në hyrje është 6, atëherë dalja duhet të jetë: * *** ***** ******* ********* *********** ********* ******* ***** *** * Detyra. A.2.35 Shkruani një program në JAVA i cili paraqet strukturën vijuese rombike sipas një numri të dhënë si hyrje. Nëse numri në hyrje është 6, atëherë dalja duhet të jetë: 1 212 32123 4321234 543212345 65432123456 543212345 4321234 32123 212 1 Detyra. A.2.36 Shkruani një program në JAVA i cili paraqet strukturën vijuese rombike të karaktereve. A ABA ABCBA ABCDCBA ABCDEDCBA ABCDEFEDCBA ABCDEDCBA ABCDCBA ABCBA ABA A


88 Shtesa A. Shembuj dhe Detyra Detyra. A.2.37 Shkruani një program në JAVA i cili kontrollon nëse një numër është ’Automorphic’ ose jo. Në matematikë një numër automorphic është një numër katrori i të cilëve "përfundon"me të njëjtën shifër si vetë numri. Për shembull, 5 2 = 25, 62 = 36, 762 = 5776 dhe 896252 = 793212890625. Detyra. A.2.38 Mesatarja aritmetike është vlera mesatare e vlerave të caktuara në një varg të numrave. Pëcaktohet sipas formulës: mbledhja e n numrave të pjesëtuar nga numri i numrave (vlera n). Të shkruhet programi që llogarit mesataren aritmetike të numrave të dhënë si hyrje. Detyra. A.2.39 Mesatarja gjeometrike përdoret për gjetjen e mesatares së përqindjeve. Përkufizohet sipas formulës: rrënja e n-të e prodhimit të n numrave. Të shkruhet programi që llogarit mesataren gjeometrike të numrave të dhënë nga përdoruesi. Detyra. A.2.40 Shkruani një program në JAVA i cili pjesëton dy numra të plotë të dhënë si hyrje duke përdorur operatorin e zbritjes. Detyra. A.2.41 Shkruani një program në JAVA i cili printon numrat ndërmjet 1 dhe 100 të cilët janë të pjesëtueshëm me 3, 5 dhe me të dytë. Detyra. A.2.42 Shkruani një program në JAVA i cili printon numrat tek nga 1 deri në 99. Printoni një numër për rresht. Detyra. A.2.43 Shkruani një program në JAVA i cili kontrollon nëse një numër është një ’Harshad Number’ ose jo. Një harshad number është një numër i plotë që është i plotëpjestueshëm me shumën e shifrave të tij. Për shembull, numri 200 është një numër harshad sepse shuma e shifrave të tij 2 dhe 0 dhe 0 është 2 (2 + 0 + 0) dhe 200 është i plotëpjestueshëm me 2. Numri 172 nuk është një numër harshad sepse shuma e shifrave 1 dhe 7 dhe 2 është 10 (1 + 7 + 2) dhe 172 nuk është i plotëpjestueshëm me 10. Detyra. A.2.44 Shkruani një program në JAVA i cili kontrollon nëse një numër i dhënë është ’Disarium number’. Një Disarium numër është i definuar sipas procesit vijues: Shuma e shifrave të tij të ngritura në fuqinë e pozitave të tyre është e barabartë me numrin origjinal. Për shembull numri 175 është një numër Disarium meqë 1 1 + 3 2 + 5 3 = 135. Disa numra të tjerë Disarium janë 89, 175, 518, etj.


A.2. Iterimi 89 Detyra. A.2.45 Shkruani një program në JAVA i cili gjen dhe printon 10 numrat e parë ’happy’. Happy number: Duke filluar me një numër të plotë pozitiv, zëvendësoni numrin me shumën e katrorëve të shifrave të tij, dhe përsërit procesin derisa numri të jetë barabartë me 1, ose përsëritet pafundësisht në një cikël që nuk përfshin 1. Shembull: 19 është një numër happy 1 2 + 9 2 = 82 8 2 + 2 2 = 68 6 2 + 8 2 = 100 1 2 + 0 2 + 0 2 = 1 Dhjetë numrat e parë ’happy’ janë: 1, 7, 10, 13, 19, 23, 28, 31. Detyra. A.2.46 Shkruani një program në JAVA i cili kontrollon nëse një numër është ’Pronic Number’. Pronic Number është një numër i cili është prodhimi i dy numrave të plotë të njëpasnjëshëm, që është një numër i formës n × (n + 1). Disa numra të parë pronic janë: 0, 2, 6, 12, 20, 30, 42, 56, 72, 90, 110, 132, 156, ... etj. Detyra. A.2.47 Shkruani një program në JAVA i cili llogarit shumën e 100 numrave të parë të thjeshtë. Detyra. A.2.48 Shkruani një program në JAVA që si hyrje merr një numër të plotë dhe printon tabelën e tij të shumëzimit deri në 10. Detyra. A.2.49 Shkruani një program në JAVA i cili mbledh dy numra binarë. Detyra. A.2.50 Shkruani një program në JAVA i cili konverton një numër decimal në numër heksadecimal. Detyra. A.2.51 Shkruani një program në JAVA i cili konverton një numër decimal në numër binar. Detyra. A.2.52 Shkruani një program në JAVA i cili konverton një numër decimal në numër oktal. Detyra. A.2.53 Shkruani një program në JAVA i cili konverton një numër binar në numër decimal.


90 Shtesa A. Shembuj dhe Detyra Detyra. A.2.54 Shkruani një program në JAVA i cili konverton një numër binar në heksadecimal. Detyra. A.2.55 Shkruani një program në JAVA i cili konverton një numër binar në numër oktal. Detyra. A.2.56 Shkruani një program në JAVA i cili konverton një numër oktal në numër decimal. Detyra. A.2.57 Shkruani një program në JAVA i cili konverton një numër oktal në numër binar. Detyra. A.2.58 Shkruani një program në JAVA i cili konverton një numër oktal në heksadecimal. Detyra. A.2.59 Shkruani një program në JAVA i cili konveron një numër heksadecimal në numër decimal. Detyra. A.2.60 Shkruani një program në JAVA i cili konverton një numër heksadecimal në numër binar. Detyra. A.2.61 Shkruani një program në JAVA i cili konverton një numër heksadecimal në numër oktal. Detyra. A.2.62 Shkruani një program në JAVA i cili fillon me një numër të plotë n, pjesëton n me 2 nëse n është çift ose shumëzon me 3 dhe i shton 1 nëse n është tek, përsërit procesin derisa n = 1. Detyra. A.2.63 Shkruani një program në JAVA i cili krijon dhe printon numrat unikë tre-shifrorë duke përdorur 1, 2, 3, 4. Gjithashtu, numëroni sa numra të tillë tre-shifrorë ekzistojnë. Detyra. A.2.64 Shkruani një program në JAVA i cili gjen numrin e kombinimeve që plotësojnë p + q + r + s = n ku n është një numër <= 4000 dhe p, q,r,s është në rangun nga 0 deri në 1000.


A.2. Iterimi 91 Detyra. A.2.65 Shkruani një program në JAVA që konverton sekondat në orë, minuta dhe sekonda. Detyra. A.2.66 Shkruani një program në JAVA që llogarit x n%y ku x, y dhe n janë numra të plotë. Detyra. A.2.67 Shkruani një program në JAVA i cili gjen të gjithë treshet unike të tillë që shuma e të tre elementeve [x,y, z(x ≤ y ≥ z)] është e barabartë me një numër specifik. Detyra. A.2.68 Shkruani një program në JAVA i cili llogarit shumën e n numrave të parë të thjeshtë. Detyra. A.2.69 Shkruani një program në JAVA i cili pranon një numër tek (n duhet të jetë më e madhe se ose e barabartë me 4 dhe më e vogël ose e barabartë me 50,000, Goldbach number) nga përdoruesi dhe krijon kombinime që shpreh numrin e dhënë si një shumë e dy numrave të thjeshtë. Printo numrin e kombinimeve. Detyra. A.2.70 Shkruani një program në JAVA i cili lexon n shifra të zgjedhur nga 0 deri në 9 dhe printon numrin e kombinimeve ku shuma e shifrave të tyre është e barabartë me një numër tjetër (s). Mos përdorni shifrat e njëjta në një kombinim. Për shembull, kombinimet ku n = 3 dhe s = 6 janë si vijon: 1 + 2 + 3 = 6 0 + 1 + 5 = 6 0 + 2 + 4 = 6 Detyra. A.2.71 Shkruani një program në JAVA i cili printon të gjithë faktorët që janë numra të thjeshtë të një numri të dhënë si hyrje. Detyra. A.2.72 Shkruani një program në JAVA i cili paraqet n elementet e numrave natyralë tek dhe shumën e tyre. Detyra. A.2.73 Në matematikë, sita e Eratosthenes është një algoritëm i lashtë për të gjetur të gjithë numrat e thjeshtë më të mëdhenj se një numër i dhënë si hyrje. Shkruani një program në JAVA i cili printon të gjithë numrat e thjeshtë më të vegjël se ose të barabartë me një numër të dhënë.


92 Shtesa A. Shembuj dhe Detyra Detyra. A.2.74 Shkruani një program në JAVA i cili printon tabelën e shumëzimit të një numri të plotë të dhënë si hyrje. Detyra. A.2.75 Shkruani një program në JAVA i cili teston nëse ekzistojnë dy numra të plotë x dhe y i tillë që x 2 + y 2 është e barabartë me një numër të dhënë pozitiv. Detyra. A.2.76 Shkruani një program në JAVA i cili pranon si hyrje një numër të plotë dhe konverton atë në numër binar. Pastaj numëron numrin e bitëve zero të numrit binar. Detyra. A.2.77 Shkruani një program në JAVA i cili përdor algoritmin e Euklidit për të llogaritur pjesëtuesin më të madh të përbashkët të dy numrave të plotë të dhënë si hyrje. Detyra. A.2.78 (**) Nëse vizatoni një vijë të drejtë në një rrafsh, rrafshi ndahet në dy regjione. Për shembull, nëse tërhiqni dy vija të drejta paralele, merrni tre sipërfaqe, dhe nëse vizatoni vertikalisht një mbi tjetrën 4 sipërfaqe. Shkruani një program në JAVA i cili krijon numrin maksimal të regjioneve që fitohen nga vizatimi i n vija të drejta. Për hyrjen 5, numri i regjioneve do të jetë 16. Detyra. A.2.79 (**) Shkruani një program në JAVA i cili krijon një varg spiral të gjatësisë n * n nga një numër i plotë n i dhënë si hyrje. Nëse hyrja është 5, vargu spiral do të jetë: 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 Detyra. A.2.80 (**) Shkruani një program në JAVA i cili llogarit rrënjën katrore të një numri të plotë. Detyra. A.2.81 (**) Shkruani një program në JAVA i cili kontrollon nëse secila shkronjë e një fjale të dhënë është më e vogël se ajo para saj. Për hyrjen ABCD, dalja do të jetë true. Detyra. A.2.82 (**) Shkruani një program në JAVA i cili kontrollon nëse dy stringje të dhënë si hyrje janë izomorfikë ose jo. Për shembull stringjet abca dhe zbxz janë izomorfike.


Click to View FlipBook Version