This shows you the differences between two versions of the page.
|
poo:laboratoare:07 [2025/11/17 21:25] george.tudor1906 [Problema 4] |
poo:laboratoare:07 [2025/11/20 08:01] (current) george.tudor1906 [Problema 4] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ===== Laboratorul 07. ===== | ===== Laboratorul 07. ===== | ||
| - | Arhiva laborator: {{:poo:laboratoare:arhiva7.zip| Arhiva}} | + | Arhiva laborator: {{:poo:laboratoare:arhiva_lab7.zip| Arhiva}} |
| Line 35: | Line 35: | ||
| <note tip> | <note tip> | ||
| <code java> | <code java> | ||
| - | Comparator comparator () ; //comparator folosit (null pentru comparatia naturală) | + | Comparator comparator(); //comparator folosit (null pentru comparatia naturală) |
| boolean add(Object o); //adaugă un elemnt în mulțime dacă nu există deja și sortează mulțimea | boolean add(Object o); //adaugă un elemnt în mulțime dacă nu există deja și sortează mulțimea | ||
| Object first(); //primul obiect din mulțime | Object first(); //primul obiect din mulțime | ||
| Line 53: | Line 53: | ||
| ==== Problema 4 ==== | ==== Problema 4 ==== | ||
| - | Realizați un program care citește un fișier text și afișează, pentru **fiecare cuvânt distinct**, numerele liniilor în care apare și, la final, numărul total de apariții ale acelui cuvânt. Se va utiliza un **dicționar ordonat alfabetic** după cuvânt, implementat ca **TreeMap<String, LinkedList<Integer>>**: cheia este cuvântul, iar valoarea este lista numerelor de linie pentru **fiecare apariție** (dacă același cuvânt apare de mai multe ori pe aceeași linie, numărul liniei se repetă în listă). | + | Realizați un program care citește un fișier text și afișează, pentru **fiecare cuvânt distinct**, numerele liniilor în care apare și, la final, numărul total de apariții ale acelui cuvânt. Se va utiliza un **dicționar ordonat alfabetic** după cuvânt, implementat ca **TreeMap<String, LinkedList<Integer> >**: cheia este cuvântul, iar valoarea este lista numerelor de linie pentru **fiecare apariție** (dacă același cuvânt apare de mai multe ori pe aceeași linie, numărul liniei se repetă în listă). |
| Pentru afișare se va itera cu un **Iterator** peste mulțimea intrărilor dicționarului obținută prin **Map.entrySet()**. Pentru fiecare intrare, se va tipări **cuvântul** pe o linie separată urmat, pe liniile următoare, de lista numerelor de linie (în ordinea colectării), iar la final "Total: N", unde N este dimensiunea listei aferente cuvântului. Fiecare cuvânt începe pe o linie nouă. | Pentru afișare se va itera cu un **Iterator** peste mulțimea intrărilor dicționarului obținută prin **Map.entrySet()**. Pentru fiecare intrare, se va tipări **cuvântul** pe o linie separată urmat, pe liniile următoare, de lista numerelor de linie (în ordinea colectării), iar la final "Total: N", unde N este dimensiunea listei aferente cuvântului. Fiecare cuvânt începe pe o linie nouă. | ||
| Line 62: | Line 62: | ||
| ==== Problema 5 ==== | ==== Problema 5 ==== | ||
| - | Program pentru crearea și afișarea unui dicționar cu numele fișierelor dintr-un director împreună cu dimensiunea lor exprimată în kiloocteți (ca număr întreg). Numele reprezintă cheia, iar dimensiunea este valoarea asociată cheii. | + | Realizați un program care, pentru un director dat, construiește și afișează un dicționar cu **numele fișierelor** (cheia) și **dimensiunea lor** exprimată în kiloocteți (KiB) ca număr întreg (valoarea). Dicționarul se va construi **inițial** folosind HashMap<String, Integer>, apoi se va **reorganiza** într-un TreeMap<String, Integer> pentru afișarea alfabetică a numelor. Dimensiunea în KiB se calculează prin rotunjire în sus: KiB = (bytes + 1023) / 1024. |
| - | Programul va folosi succesiv clasele **//HashMap//** și **//TreeMap//**. | + | |
| - | Afișarea se va face atât în ordinea alfabetică a numelor cât și în ordinea dimensiunii fișierelor (două afișări). | + | Programul va produce două afișări separate: |
| + | * **în ordine alfabetică după nume** - folosind TreeMap (ordonarea naturală a cheilor String). | ||
| + | * î**n ordine descrescătoare după dimensiune** - obținută prin transformarea mulțimii de intrări (entrySet()) într-o listă și sortarea ei cu Collections.sort / List.sort după dimensiune (descrescător). | ||
| + | |||
| + | |||
| + | Pentru fiecare afișare, fiecare linie va conține numele fișierului urmat de dimensiunea în KiB (de ex.: readme.txt - 5 KiB). Programul primește calea directorului ca argument; dacă lipsește, se poate folosi directorul curent. | ||
| <note tip> | <note tip> | ||
| - | ''entrySet'' din ''Map'' transformă colecția în ''Set'' de intrari; | + | ''entrySet'' din ''Map'' transformă colecția în ''Set'' de intrări; |
| ''Collections.sort'' sortează o colectie după un criteriu definit. | ''Collections.sort'' sortează o colectie după un criteriu definit. | ||
| </note> | </note> | ||
| + | |||
| + | |||
| + | |||
| + | ==== Problema 6 ==== | ||
| + | Se cere realizarea unui program care implementează o **memorie cache cu capacitate fixă** și politică **LRU**: la depășirea capacității este eliminată intrarea folosită cel mai demult. "Folosire" înseamnă acces prin get (citire) sau put (inserare/actualizare). Implementarea se va baza exclusiv pe colecțiile standard Java. | ||
| + | |||
| + | Cache-ul va fi realizat ca o clasă **LruCache** care **extinde** **LinkedHashMap** în regim de //access-order// (ordonare după ultimul acces), prin apelarea constructorului potrivit și suprascrierea metodei removeEldestEntry. Eliminarea celui mai vechi element din punct de vedere al accesului trebuie să se producă automat imediat după o operație care ar face cache-ul să depășească capacitatea. | ||
| + | |||
| + | Programul citește dintr-un fișier text o **succesiune** de operații asupra cache-ului și afișează atât **rezultatul operațiilor de tip GET**, cât și **starea finală a cache-ului în ordinea LRU**. Fișierul conține câte o instrucțiune pe linie, în formatul: | ||
| + | * //PUT <cheie><valoare>// - inserează sau actualizează intrarea; la actualizare intrarea devine "cea mai recent folosită". | ||
| + | * //GET <cheie>// - afișează valoarea asociată sau NULL dacă lipsește; la acces reușit, intrarea devine "cea mai recent folosită". | ||
| + | * Liniile goale sau cele care încep cu # sunt ignorate. Cheile și valorile se tratează ca șiruri simple (fără spații în interior). | ||
| + | |||
| + | **Ordinea de afișare a cache-ului**: se iterează în ordinea //access-order// a LinkedHashMap (de la cea mai veche la cea mai recentă). Se tipărește câte o intrare pe linie, în forma //<cheie>=<valoare>//. Între rezultatele GET și listarea finală se afișează o linie separatoare //---//. | ||
| + | |||
| + | Programul primește două argumente din linia de comandă: **capacitatea** cache-ului (număr întreg strict pozitiv) și **calea fișierului de operații**. | ||
| + | |||
| + | Programul va conține următoarele elemente **obligatorii**: | ||
| + | * <code java> | ||
| + | // O clasă fără generics: | ||
| + | |||
| + | class LruCache extends LinkedHashMap { | ||
| + | public LruCache(int capacity) { ...} // seteaza access-order = true | ||
| + | protected boolean removeEldestEntry(Map.Entry eldest) { ... } // eliminare cand size() > capacity | ||
| + | } | ||
| + | |||
| + | // Cheile null sunt interzise (verificate în put). | ||
| + | |||
| + | // Capacity se memorează în obiect și este strict pozitiv. | ||
| + | </code> | ||
| + | |||
| + | |||
| + | * <code java> | ||
| + | // O metodă statică ce execută operațiile citite din fișier și returnează cache-ul: | ||
| + | |||
| + | public static LruCache runOps(String opsFile, int capacity) throws IOException {...} | ||
| + | |||
| + | // Citește fișierul, interpretează liniile în ordine, pentru GET afișează imediat rezultatul (valoare sau NULL). | ||
| + | |||
| + | // Ignoră liniile invalide (nu oprește programul). | ||
| + | </code> | ||
| + | |||
| + | |||
| + | * <code java> | ||
| + | // O metodă statică pentru afișarea stării curente a cache-ului în ordinea LRU: | ||
| + | |||
| + | public static void printCache(LruCache cache){...} | ||
| + | |||
| + | // Parcurge intrările cache.entrySet() și tipărește <cheie>=<valoare> pe linie. | ||
| + | </code> | ||
| + | |||
| + | |||
| + | În metoda main se validează argumentele, se apelează runOps(...), se afișează linia ---, apoi printCache(...). | ||
| + | |||
| + | <note tip> | ||
| + | Pentru fișierul de intrare din arhivă (capacitate 3, loadfactor 0.75), output-ul trebuie să fie: | ||
| + | |||
| + | <code java> | ||
| + | 1 | ||
| + | NULL | ||
| + | 3 | ||
| + | NULL | ||
| + | 30 | ||
| + | NULL | ||
| + | 5 | ||
| + | 6 | ||
| + | --- | ||
| + | C=30 | ||
| + | E=5 | ||
| + | F=6 | ||
| + | </code> | ||
| + | |||
| + | Explicația se găsește la fiecare pas în fișierul de intrare. | ||
| + | </note> | ||
| + | |||