Table of Contents

Laboratorul 07.

Arhiva laborator: Arhiva

Problema 1

Se cere realizarea unui program care citește un fișier text și afișează cuvintele distincte.

În această problemă, prin “cuvânt” înțelegem o secvență de caractere obținută prin separare atât după spații, cât și după semnele uzuale de punctuație. Tokenizarea se va face exclusiv cu StringTokenizer, folosind o listă de delimitatori care include cel puțin: spațiul ' ', tabul '\t', virgula ,, punctul ., punct și virgulă ;, două puncte :, semnele !?, ghilimele ”', paranteze ()[]{}, cratime, etc. Se vor ignora tokenurile vide (dacă apar). Compararea cuvintelor este case-sensitive („Ana” și „ana” sunt diferite).

Afișarea se face fără a apela nicio funcție de sortare sau de inversare a ordinii din afara colecției și se face în două etape: mai întâi se construiește un TreeSet<String> cu ordonare naturală (crescătoare), folosind constructorul fără argument și care este populat cu toate cuvintele distincte extrase din fișier. Apoi, plecând strict de la setul obținut la pasul anterior, construiți al doilea TreeSet<String> - creați o instanță nouă inițializată cu un comparator descrescător și adăugați în ea toate elementele din primul set, fără a reciti fișierul. Al doilea set trebuie să rezulte exclusiv prin această reconstrucție - nu se folosesc sortări sau inversări externe precum Collections.sort, List.sort, descendingSet(), etc..

Se vor implementa două metode, apelate din main:

În main se apelează pe rând cele două metode și se afișează cuvintele, câte un cuvânt pe linie: mai întâi în ordine crescătoare, apoi o linie separatoare —, urmată de ordinea descrescătoare.

Se poate folosi ca fișier de intrare fișierul test01.txt din arhivă!

Problema 2

Definiți o clasă LinkedSet care modelează o mulțime de elemente distincte, implementată peste o listă înlănțuită. Clasa va extinde LinkedList și va implementa Set, iar elementele vor fi de tip Object. Scopul este ca structura să se comporte ca un Set - să nu accepte duplicate, dar să păstreze ordinea de inserare specifică listei.

Vor fi supradefinite cele trei metode indicate mai jos, astfel încât să respecte unicitatea:

Pentru verificarea egalității se folosește metoda equals a obiectelor introduse.

Pentru testare puteți folosi clasa existentă în Test2.java.

Problema 3

Se cere realizarea unei clase SListSet care modelează o mulțime ordonată de obiecte peste o listă înlănțuită. Clasa extinde LinkedList și implementează SortedSet (fără generics; elementele sunt de tip Object). Ordinea elementelor este dată de un Comparator furnizat la creare sau, dacă acesta este null, de ordinea naturală a elementelor. Două elemente sunt considerate duplicate atunci când comparația lor dă zero (compare(a, b) == 0), iar mulțimea nu trebuie să conțină două astfel de elemente. Nu se acceptă valori null. Dacă parametrul Comparator este null, toate elementele introduse trebuie să fie Comparable - în caz contrar se aruncă o excepție clară (de exemplu ClassCastException / IllegalArgumentException).

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
Object first(); //primul obiect din mulțime
Object last(); // ultimul obiect din mulțime
SortedSet subSet(Object from, Object to); // copie ordonată a intervalului [from, to)
SortedSet headSet(Object to); // copie ordonată a intervalului (primul_element, to)
SortedSet tailSet(Object from); copie ordonată a intervalului [from, ultimul_element)
SListSet reversed(); // întoarce o copie a mulțimii ordonată descrescător, construită pe baza comparatorului curent (dacă există) sau a ordinii naturale; populați exclusiv din elementele setului curent, fără recitirea fișierului și fără sortări/inversări externe.

Se vor defini doi constructori:

Programul va folosi SListSet pentru a afișa cuvintele distincte dintr-un fișier text (test1.txt), în ordine crescătoare și în ordine descrescătoare, fără a apela sortări din afara colecției. Delimitarea cuvintelor este identică cu Problema 1.

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

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

Fișierul de intrare recomandat: test4.txt din arhivă.

Problema 5

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 produce două afișări separate:

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.

entrySet din Map transformă colecția în Set de intrări;

Collections.sort sortează o colectie după un criteriu definit.

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:

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:

În metoda main se validează argumentele, se apelează runOps(…), se afișează linia —, apoi printCache(…).

Pentru fișierul de intrare din arhivă (capacitate 3, loadfactor 0.75), output-ul trebuie să fie:

1
NULL
3
NULL
30
NULL
5
6
---
C=30
E=5
F=6

Explicația se găsește la fiecare pas în fișierul de intrare.