Tema 2 - The Library of HashBabel

Responsabili:

  • Data publicării: 11.04.2022
  • Deadline HARD: 10.05.2022 23:55:00

Actualizări

  • Modificare sistem de punctare (doar ponderea) + flag Makefile: 14.04.2022
  • Adaugare checker si punctaj: 14.04.2022
  • Tratare caz special pentru operatia ADD_BOOK
  • Modificare checker coding style: 07.05.2022
  • Adaugire privind folosirea scheletului de laborator: 07.05.2022

Obiective

  • Aprofundarea cunoștințelor în utilizarea limbajului C.
  • Implementarea și utilizarea structurii de date dictionar.
  • Familiarizarea cu implementarea unei structuri de date generice.
  • Implementarea unui sistem de gestiune pentru biblioteca.

Introducere

Este inceptul secolului al XVII-lea si un nou concept apare in randul oamenilor intelectuali: un manuscris menit sa realizeze conexiunea dintre doua limbaje diferite. Hipsterii vremii i-au spus heșteibăl sau heșmep, dar pana la urma a devenit social acceptat termenul de dictionar.

Cetateni din toate clasele sociale se inghesuie, mai ceva ca la tigai, sa puna mana pe un dictionar, asa ca administratia orasului se gandeste sa centralizeze treaba.

Pentru ca esti invatatul orasului (ai zis o gluma cu Da Vinci la un party), primesti cel mai important job: administrarea unei biblioteci unde oamenii pot veni sa imprumute carti (dictionare).

Cerintă

Pentru rezolvarea temei, va trebui sa implementati doua componente:

  • Structura de Hashtable (dictionar) generica.
  • Logica din spatele bibliotecii (baza de date si sistemul de imprumuturi).

Structura Hashtable

Trebuie sa implementati o structura de tip dictionar care sa respecte urmatoarele restrictii:

  • Sa fie generica (sa poata suporta orice tip de date, atat pentru chei cat si pentru valori).
  • Sa foloseasca o functie de hashing eficienta, astfel incat sa provoace cat mai putine coliziuni.
  • Sa trateze coliziunile prin chaining (asemenea implementarii din cadrul laboratorului).
  • Sa prezinte functionalitatea de resize.

Hashtable-ul trebuie sa aiba implementate cel putin urmatoarele functionalitati (precum modelul din laborator):

* Put(key, value)
* Remove(key)
* Get(key)
* Has_Key(key)

Resizing

Atunci cand un hashtable este foarte “aglomerat”, complexitatea unei operii devine prea mare pentru functionalitati care ar trebuie sa aibe O(1) pe caz general. De ex: daca avem un hashtable cu 10 bucket-uri (implementare prin chaining) si adaugam 1000 de intrari (perechi key-value), inseamna ca pe caz general fiecare operatie trebuie sa faca 100 de pasi (cate elemente sunt in medie intr-un bucket). Pentru a rezolva aceasta problema, adaugam mecanismul de resize.

Notam cu E numarul de elemente (intrari) din hashtable si cu B numarul de bucketuri.

load_factor = E / B

Daca load_factor > 1, inseamna ca structura este prea aglomerata, prin urmare se realizeaza operatia de resize (pentru tema am ales valoarea 1 ca limita superioara, insa aceesta nu este standard). NU va trebui sa implementati si cazul in care load_factor este prea mic.

Pasi resize
  • Se dubleaza vectorul de bucket-uri (se realoca cu dimensiunea 2 * B).
  • Din cauza pasului anterior, toate intrarile din hasthtable se afla acum la pozitii gresite, deoarece functia de hash a folosit vechea valoare a lui B atunci cand a aplicat operatia de modulo. Astfel, toate intrarile trebuie adaugate in noua versiune de hashtable (rehashing).

Nu aveti voie sa folositi o valoare mare ca dimensiune initiala a vectorului de bucket-uri, astfel incat sa nu se activeze niciodata mecanismul de resizing. Dimenensiunea initiala trebuie sa fie un numar natural cel mult egal cu 10.

Se garanteaza ca testele sunt suficient de mari astfel incat sa verifice implementarea mecanismului de resizing (daca nu este implementat, operatiile vor dura prea mult timp).

Biblioteca

Locuitorii orasului, cei ce intretin aceasta biblioteca, ajutand-o sa se dezvolte zilnic, vor fi numiti in continuare useri. Folosind implementarea de mai sus, va trebui sa simulati un sistem de gestiune al unei biblioteci ce suporta interactiunea cu utilizatori, prin citirea unui numar de comenzi. Acestea se opresc atunci cand ultima comanda citita are valoare “EXIT”.

Dictionar

In continuare vom numi dictionar (sau carte) o colectie de definitii. O definitie este o pereche formata din def_key si def_val. De exemplu, pentru un dictionar cu numele “Dictionar Roman-Englez”, o posibila reprezentare a colectiei ar putea fi (unde o intrare este o pereche de forma def_key:def_val) :

Spre deosebire de un dictionar traditional, intrarile nu trebuie sortate dupa cheie. Imaginea de mai sus nu reprezinta asezarea efectiva in memorie. Atat def_key cat si val_key sunt siruri de caractere formate dintr-un singur cuvant. Trebuie sa implementati o baza de date ce simuleaza rafturile bibliotecii, pe care se afla carti de tipul dictionar.

Atat intreaga biblioteca, cat si fiecare carte in parte, trebuie implementate folosind structura de hashtable definita anterior.

Comenzi biblioteca / dictionar

O carte poate fi adaugata sau stearsa din biblioteca. De asemenea, aflandu-ne in plin proces de dezvoltare, intr-o carte se poate adauga sau sterge o definitie.

  • ADD_BOOK <book_name> <def_number>
    • <def_key1> <def_val1>
    • <def_key2> <def_val2>
    • <def_key3> <def_val3>.
    • …….

Comanda adauga cartea citita in biblioteca (daca exista o carte cu acelasi nume atunci se va actualiza valoarea acesteia: va avea loc operatia de update). Numele cartii poate contine mai multe cuvinte si va fi delimitat de caracterul ' ” '. Lungimea totala a lui book_name NU depaseste 40 de caractere. Def_number reprezinta numarul de definitii din carte. Pe urmatoarele def_number linii se gasesc perechi de forma (def_key, val_key). Atat def_key cat si val_key sunt stringuri ce NU au lungimea mai mare de 20 de caractere.

  • GET_BOOK <book_name>. Comanda afiseaza in formatul de mai jos detaliile cartii ce are numele book_name. In cazul in care cartea nu se afla in biblioteca se va afisa mesajul: “The book is not in the library.”. Atunci cand este afisat, numele unei carti nu mai trebuie sa fie delimitat de caracterul ' ” '. Format afisare (conceptele de rating si purchases sunt detaliate in sectunile de mai jos):

Name:book_name Rating:book_rating Purchase:book_purchases

  • RMV_BOOK <book_name>. Comanda va sterge din biblioteca cartea cu numele respectiv. In cazul in care cartea nu se afla in biblioteca se va afisa mesajul: “The book is not in the library.”
  • ADD_DEF <book_name> <def_key> <def_val>. Comanda insereaza o noua definitie in cartea precizata. In cazul in care exista deja o definitie cu aceeasi cheie, valoarea va fi actualizata cu cea noua. In cazul in care cartea nu se afla in biblioteca se va afisa mesajul: “The book is not in the library.”.
  • GET_DEF <book_name> <def_key>. Comanda va afisa valoarea definitiei corespunzatoare din cartea specificata. In cazul in care cartea nu se afla in biblioteca se va afisa mesajul: “The book is not in the library.”. Daca definitia nu se afla in carte, se va afisa mesajul: “The definition is not in the book.”.
  • RMV_DEF <book_name> <def_key>. Comanda sterge definitia corespunzatoare din cartea specificata. In cazul in care cartea nu se afla in biblioteca se va afisa mesajul: “The book is not in the library.”. Daca definitia nu se afla in carte, se va afisa mesajul: “The definition is not in the book.”

Comenzi useri

Pentru gestionarea userilor in memorie, se va folosi, de asemenea, un hashtable (aceeasi structura generica folosita pentru biblioteca). Userul poate imprumuta, returna sau pierde o carte. De asemenea, la returnarea fiecari carti, acesta ofera si un calificativ (similar GoodReads sau IMDb).

In plus, zilele acestea, in oras se va desfasura o competitie de lectura, pentru a determina cei mai etici cititori. La finalul acesteia, se va afisa clasamentul userilor si clasamentul celor mai populare carti.

Pentru a fi departajati, fiecare user va avea asociat un punctaj. La inscrierea in sistem, toti primesc 100p. Atunci cand acestia imprumuta o carte, vor fi nevoiti sa precizeze si un numar de zile pana la returnare. Daca un user inapoieaza o carte mai repede decat termenul limita, numarul de puncte creste. Daca intarzie cu returnarea cartii sau pierde cartea, numarul de puncte scade.

Un user care ajunge sa aiba punctaj negativ este banat din sistem. Un user banat nu mai are voie sa interactioneze cu biblioteca si nici nu va aparea in clasamentul final. Un user banat nu are voie sa fie reintrodus in sistem.

  • ADD_USER <user_name>. Adauga un nou user in sistem.
    • Daca userul exista deja se va afisa: “User is already registered.” Lungimea numelui NU depaseste 20 de caractere.
  • BORROW <user_name> <book_name> <days_available> (cartea va ramane in baza de date, dar va fi marcata ca unreachable pana cand va fi returnata). Un user poate imprumuta o carte doar daca a returnat-o pe cea precedenta.
    • Daca userul nu exista in sistem se va afisa mesajul: “You are not registered yet.”.
    • Daca userul este banat, se va afisa mesajul “You are banned from this library.”.
    • In cazul in care cartea nu se afla in biblioteca se va afisa mesajul: “The book is not in the library.”.
    • In cazul in care cartea este imprumutata altcuiva se va afisa mesajul: “The book is borrowed.”.
    • Daca vrea sa imprumute o carte, dar el figureaza in sistem cu alta carte deja imprumutata se va afisa mesajul: “You have already borrowed a book.”.
  • RETURN <user_name> <book_name> <days_since_borrow> <rating>. Userul a returnat o carte, specificand numarul de zile trecute de la imprumut, dar si ratingul acordat cartii.
    • Daca exista o intarziere la returnare userul va pierde un numar de puncte egal cu (numarul de zile de intarziere * 2).
    • Daca userul returneaza cartea mai devreme decat termenul limita, va fi recompensat cu 1 punct / zi.
    • Daca punctajul unui user ajunge negativ (< 0), atunci acesta va fi banat(nu va mai avea voie in biblioteca) si se va afisa mesajul “The user <user_name> has been banned.”
    • Se garanteaza ca vor da return doar userii deja inregistrati in sistem.
    • Daca userul care vrea sa returneze o carte este banat, se va afisa mesajul “You are banned from this library.”.
    • Daca userul vrea sa returnareze o alta carte fata de cea pe care a imprumutat-o se va afisa mesajul: “You didn't borrow this book.”.
    • Daca userul vrea sa returneze o carte, dar el nu are nicio carte imprumutata se afiseaza “You didn't borrow this book.”.
  • LOST <user_name> <book_name>. Userul a pierdut cartea, ceea ce inseamna ca va fi stearsa definitiv din biblioteca.
    • Userului i se vor scadea 50p.
    • Daca punctajul unui user ajunge negativ (< 0), atunci acesta va fi banat(nu va mai avea voie in biblioteca) si se va afisa mesajul “The user <user_name> has been banned.”.
    • Se garanteaza ca userul pierde cartea pe care a imprumutat-o si care figureaza in sistem, ca fiind imprumutata de catre el.
    • Daca userul nu exista in sistem se afiseaza mesajul: “You are not registered yet.”.
    • Daca userul este banat, se va afisa mesajul “You are banned from this library.”.

Sfarsitul comenzilor

Atunci cand comanda citita are valoarea “EXIT”, inseamna ca ziua s-a incheiat si putem inchide biblioteca. Mai ramane un singur lucru de facut, afisarea TOP_BOOKS si TOP_USERS.

TOP_BOOKS

Se afiseaza topul cartilor, in ordine descrescatoare dupa rating. Rating-ul se calculeaza ca suma note useri / numar de imprumuturi. Purchases reprezinta numarul total de imprumuturi finalizate cu succes (un imprumut este finalizat daca s-a oferit rating pentru carte). Rating-ul se va afisa cu eroare de 3 zecimale. Daca exista 2 carti cu acelasi rating, se va afisa mai intai cartea cu cele mai multe reviewuri. Daca exista 2 carti cu acelasi rating si acelasi numar de imprumuturi, se vor ordona crescator lexicografic dupa numele cartii. Format afisare:

Books ranking:

  • 1. Name: Rating: Purchases:
  • 2. Name: Rating: Purchases:
  • 3. …
TOP_USERS

Se va afisa topul userilor, in ordine descrescatoare dupa punctaj. Doar userii nebanati vor fi afisati in top. Daca exista mai multi useri cu acelasi punctaj, se vor afisa in ordine lexicografica dupa nume. Format afisare:

Users ranking:

  • 1. Name: Points:
  • 2. Name: Points:
  • 3. …

Exemplu

Input
ADD_BOOK "dex" 3
minge rotund
animal vietate
pufoaica haina
GET_DEF "dex" animal
ADD_DEF "dex" birou masa
GET_BOOK "dex"
ADD_DEF "dex" minge bila
ADD_DEF "dex" minge bila
RMV_DEF "dex" animal
GET_DEF "dex" animal
GET_BOOK "dex"
GET_BOOK "alabala"
ADD_USER ana 
ADD_USER ana
GET_DEF "dex" minge
GET_BOOK "dex"
ADD_USER rappyzaur
BORROW rappyzaur "dex" 10
RETURN rappyzaur "dex" 8 4
BORROW ana "dex" 10
GET_DEF "dex" birou
RETURN ana "dex" 17 5
BORROW ana "dex" 10
RETURN ana "dex" 7 2
EXIT
Output
vietate 
Name:dex Rating:0.000 Purchases:0
The definition is not in the book.
Name:dex Rating:0.000 Purchases:0
The book is not in the library.
User is already registered.
bila 
Name:dex Rating:0.000 Purchases:0
masa 
Books ranking:
1. Name:dex Rating:3.667 Purchases:3
Users ranking:
1. Name:rappyzaur Points:104
2. Name:ana Points:99

TL; DR

  • implementarea unui hashtable generic care trateaza coliziunile cu chaining.
  • hashtable-ul trebuie sa aiba implementata functionalitatea de resizing.
  • atat biblioteca, fiecare carte, cat si baza de date pentru useri trebuie implementate folosind hashtable-ul generic.
  • elementele unei carti sunt definitii; o definitie este o pereche (key, value).
  • elementele bibliotecii sunt cartile (adica un hashtable ce contine alte hashtable-uri).
  • comenzile trebuie rezolvate folosind functionalitatea hashtable-ului (de ex: pentru GET_DEF se foloseste functia get()).
  • testele de intrare vor contine comenzi de biblioteca si comenzi de user amestecate.
  • se citeste de la standard input (stdin) si se afiseaza la standard ouput (stdout).

Depunctari

Neimplementarea unui hasthable generic. Ar trebui sa puteti folosi aceeasi implementare atat pentru implementarea bibliotecii, a cartilor si a bazei de date pentru useri. -20p

Alocarea statica acolo unde se putea aloca dinamic (unde nu se cunoaste dimensiunea datelor se va aloca dinamic) -20p

Utilizarea variabilelor globale -20p

Eliberarea memoriei se va verifica folosind utilitarul Valgrind. O temă ce conține memory leaks va atrage după sine punctajul de 0p pe testul respectiv.

Alocarea initiala a unui hashtable prea mare (care nu respecta numarul de buckets precizat in enunt initial) si pentru care nu este nevoie de resize: -20p

Este obligatorie implementarea unui hashtable: nerespectarea acestei cerinte va aduce dupa sine punctajul 0 pe tema.

Nu copiați! Toate soluțiile vor fi verificate folosind o unealtă de detectare a plagiatului. În cazul detectării unui astfel de caz, atât plagiatorul cât și autorul original (nu contează cine e) vor primi punctaj 0 pe toate temele! De aceea, vă sfătuim să nu vă lăsați rezolvări ale temelor pe calculatoare partajate (la laborator etc), pe mail/liste de discuții/grupuri etc.

Checker

Checker: 2-checker-library.zip.

Temele vor fi trimise pe vmchecker. Atenție! Temele trebuie trimise în secțiunea Structuri de Date (CA).

Arhiva trebuie să conțină:

  • sursele .c și .h
  • fișier Makefile cu două reguli:
    • regula build: în urma căreia se generează un executabil numit main
    • regula clean care şterge executabilul si fișierele obiect
  • Compilarea trebuie sa se realizeze cu flagurile -Wall -Wextra -std=c99
  • fișier README care să conțină detalii despre implementarea temei. Găsiți aici un model de README pe care vă rugăm să îl respectați pe cât posibil.
Punctaj
  • 80p teste
  • 10p coding style
  • 10p README

FAQ

Q: Se pot folosi flag-uri de optimizare?

A: Nu aveți voie să folosiți flag-uri de optimizare în Makefile (-O3, -O2, etc.).

Q: Tema 2 se poate face în C++?

A: Nu.

Q: Se pot folosi variabile globale?

A: Nu.

Q: Putem folosi scheletul de cod din laboratorul 4 (dictionar)?

A: DA :D. Puteti folosi atat scheletul pus la dispozitie de echipa de SDA cat si propria voastra rezolvare a laboratorului (nu aveti voie sa folositi rezolvarea colegului). De asemenea, nu aveti voie sa copiati rezolvarea hashtable-ului din scheletul altor laboratoare(7, 8, 9…).

Suport, întrebări și clarificări

Pentru întrebări sau nelămuriri legate de temă folosiți forumul temei.Orice întrebare e recomandat să conțină o descriere cât mai clară a eventualei probleme. Întrebări de forma: “Nu merge X. De ce?” fără o descriere mai amănunțită vor primi un răspuns mai greu.

ATENȚIE să nu postați imagini cu părți din soluția voastră pe forumul pus la dispoziție sau orice alt canal public de comunicație. Dacă veți face acest lucru, vă asumați răspunderea dacă veți primi copiat pe temă.

sd-ca/2021/teme/tema2-2022.txt · Last modified: 2022/10/03 15:10 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0