This shows you the differences between two versions of the page.
pp:24:teme:racket-st [2024/03/14 21:14] mihaela.balint |
pp:24:teme:racket-st [2024/03/21 11:34] (current) mihaela.balint [Changelog] |
||
---|---|---|---|
Line 2: | Line 2: | ||
* Data publicării: 03.03.2024 | * Data publicării: 03.03.2024 | ||
- | * Data ultimei modificări: 03.03.2024 ([[pp:24:teme:racket-st#changelog]]) | + | * Data ultimei modificări: 21.03.2024 ([[pp:24:teme:racket-st#changelog]]) |
* Tema (o arhivă .zip cu toate fișierele .rkt folosite în etapa curentă) se va încărca pe [[https://vmchecker.cs.pub.ro/ui/#PP|vmchecker]] | * Tema (o arhivă .zip cu toate fișierele .rkt folosite în etapa curentă) se va încărca pe [[https://vmchecker.cs.pub.ro/ui/#PP|vmchecker]] | ||
===== Descriere generală și organizare ===== | ===== Descriere generală și organizare ===== | ||
Line 262: | Line 262: | ||
* longest-common-substring primește două texte ''text1'' și ''text2'' și calculează cel mai lung subșir comun al acestora, astfel: | * longest-common-substring primește două texte ''text1'' și ''text2'' și calculează cel mai lung subșir comun al acestora, astfel: | ||
* construiește arborele de sufixe ST1 pentru ''text1'' | * construiește arborele de sufixe ST1 pentru ''text1'' | ||
- | * determină toate sufixele S ale textului ''text2'' (fără marcajul de final $, pentru ca acesta să nu fie numărat drept caracter comun celor 2 texte) | + | * determină toate sufixele S ale textului ''text2'' (fără marcajul de final ''$'', pentru ca acesta să nu fie numărat drept caracter comun celor 2 texte) |
* pentru fiecare sufix din S (de la cel mai lung la cel mai scurt), caută cea mai lungă potrivire a acestuia cu textul ''text1'' (parcurgând căile relevante în ST1); cea mai lungă asemenea potrivire este rezultatul final | * pentru fiecare sufix din S (de la cel mai lung la cel mai scurt), caută cea mai lungă potrivire a acestuia cu textul ''text1'' (parcurgând căile relevante în ST1); cea mai lungă asemenea potrivire este rezultatul final | ||
* dacă există mai multe cele mai lungi subșiruri comune, funcția îl întoarce pe cel care a fost găsit primul urmând pașii de mai sus | * dacă există mai multe cele mai lungi subșiruri comune, funcția îl întoarce pe cel care a fost găsit primul urmând pașii de mai sus | ||
Line 296: | Line 296: | ||
* -10p: repeated-substring-of-given-length nu manipulează arborele doar prin intermediul operatorilor tipului ST | * -10p: repeated-substring-of-given-length nu manipulează arborele doar prin intermediul operatorilor tipului ST | ||
* -20p: aplicări repetate ale acelorași funcții pe aceleași argumente (în loc de a evalua expresiile o singură dată și a prelua rezultatele în variabile cu ajutorul let-urilor) - nu se va aplica nicio depunctare pentru o scăpare izolată, dar se va aplica depunctarea în întregime pentru "scăpări" multiple | * -20p: aplicări repetate ale acelorași funcții pe aceleași argumente (în loc de a evalua expresiile o singură dată și a prelua rezultatele în variabile cu ajutorul let-urilor) - nu se va aplica nicio depunctare pentru o scăpare izolată, dar se va aplica depunctarea în întregime pentru "scăpări" multiple | ||
+ | |||
+ | ===== Etapa 4 ===== | ||
+ | |||
+ | În etapa 3 ați putut observa că anumite aplicații (căutarea unui subșir în text, căutarea unui subșir de o anumită lungime care se repetă în text) nu necesită decât explorarea parțială a arborelui de sufixe asociat textului, prin urmare ar fi mai eficient ca acest arbore să fie construit "leneș", pe măsură ce diverse porțiuni din el sunt necesare. | ||
+ | |||
+ | În acest scop, în etapa 4, veți modifica implementarea tipului ST astfel încât fiecare arbore (și, la rândul lor, toți subarborii aferenți) să fie nu o listă de ramuri, ci un flux de ramuri. Dacă aceasta ar fi singura modificare, singurele funcții care ar trebui redefinite ar fi constructorii și operatorii tipului ST (presupunând că ați respectat **bariera de abstractizare** a acestui tip). | ||
+ | |||
+ | Întrucât arborii sunt construiți pe baza tuturor sufixelor unui text, veți modifica de asemenea reprezentarea tuturor sufixelor unui text - ele vor fi reținute într-un flux, nu într-o listă cum s-a întâmplat până acum. Pentru că multe funcții din etapele anterioare primeau ca argumente sau întorceau liste de sufixe, va trebui să redefiniți, de asemenea, toate aceste funcții. Așa cum este explicat în scheletul de cod, această redefinire "în masă" putea fi evitată dacă am fi lucrat de la început cu conceptul de "colecție de sufixe", în loc să presupunem că acestea vor fi grupate neapărat într-o listă. Una din cerințele etapei este să realizați acum acest re-design (implementând un nou tip de date Collection), și să observați cum el vă ajută să jonglați cu ușurință între reprezentările alternative pentru colecțiile de sufixe. | ||
+ | |||
+ | Este important să distingeți între colecțiile care devin fluxuri și cele care își păstrează vechea reprezentare: | ||
+ | * arborii devin fluxuri de ramuri | ||
+ | * ramurile rămân perechi etichetă-subarbore | ||
+ | * listele de sufixe/cuvinte devin fluxuri de sufixe/cuvinte | ||
+ | * sufixele/cuvintele/etichetele/textele rămân liste de caractere | ||
+ | |||
+ | Dintr-un anumit punct de vedere este o etapă ușoară, întrucât nu necesită implementarea unor funcții noi, ci doar ajustarea celor vechi (plus definirea tipului Collection). Dificultatea etapei constă în următoarele aspecte: | ||
+ | * aveți mai multă independență și responsabilitate în ceea ce privește designul programului | ||
+ | * vă veți defini singuri constructorii și operatorii utili pentru tipul Collection (fără să se spună în schelet fiecare funcție de care aveți nevoie) | ||
+ | * nu vom descrie din nou fiecare funcție care trebuie "ajustată", întrucât comportamentul este același cu cel anterior, diferă eventual doar modul de reprezentare a datelor; voi înșivă trebuie să acționați conform specificației de mai sus și să înțelegeți când parametrii/rezultatul unei funcții au devenit, din liste, fluxuri | ||
+ | * sunteți responsabili pentru eficiența implementărilor, astfel încât, la rularea testelor, să vă încadrați în limita de timp impusă pe vmchecker; jumătate din teste folosesc un text lung, pentru care o implementare corectă cu fluxuri ar trebui să fie mult mai rapidă decât implementarea anterioară cu liste | ||
+ | * fără o înțelegere foarte bună a datelor cu care lucrați, nu veți ști când trebuie utilizate liste și funcții pe liste și când trebuie utilizate fluxuri și funcții pe fluxuri | ||
+ | |||
+ | Scopul etapei este consolidarea cunoștințelor legate de: | ||
+ | * **fluxuri** | ||
+ | * **abstractizare** (pe de o parte veți observa efectul respectării sau nerespectării barierei de abstractizare în etapele anterioare, pe de altă parte veți face un re-design care să abstractizeze și mai mult soluția, care va deveni astfel mai flexibilă) | ||
+ | |||
+ | În realitate, implementarea cu fluxuri ne ajută doar atunci când evităm astfel explorarea unei porțiuni semnificative din arbore. Pentru aplicații precum găsirea celui mai lung subșir comun a două texte, care necesită căutarea în întreg arborele, este mai eficientă reprezentarea cu liste, pentru că operațiile pe liste sunt mai rapide decât cele pe fluxuri. În săptămânile următoare, veți vedea că în limbajul Haskell nu avem dificultatea acestei alegeri, întrucât în acest limbaj toate listele sunt, de fapt, fluxuri. Sperăm că tema noastră v-a ajutat să înțelegeți mai bine anumite concepte din programare și v-a trezit interesul pentru ce va urma. | ||
+ | |||
+ | ==== Depunctări generate de nerespectarea cerințelor din enunț ==== | ||
+ | Baremul depunctărilor posibile în etapa 4 este: | ||
+ | * -10p: anumite funcții din fișierul etapa4.rkt sunt scrise să ruleze pe fluxuri, nu pe colecții (adică folosesc operatori de tip stream-*, nu pe cei de tip collection-* implementați de voi, cu care s-ar putea jongla ușor între reprezentarea cu liste și cea cu fluxuri) | ||
+ | * -6p*n: unde n = numărul de funcții dintre cele testate la exercițiul 1 (din checker) care, în loc să lucreze pe fluxuri, fac conversii între cele două tipuri de date pentru a lucra pe liste | ||
+ | * -30p: ''%%suffixes->st%%'', în loc să lucreze pe fluxuri, face conversii între cele două tipuri de date pentru a lucra pe liste | ||
+ | În afară de aceste depunctări, nota va fi, în principiu, cea obținută pe vmchecker. Întrucât nu putem anticipa cât de bine va discerne timeout-ul de pe vmchecker între soluțiile implementate conform specificației și celelalte, ne rezervăm dreptul să efectuăm ajustări manuale în ambele sensuri: | ||
+ | * vom depuncta (total) soluțiile implementate cu liste care reușesc să ia punctaj (probabil parțial) pe vmchecker | ||
+ | * vom oferi punctaj (parțial sau total) soluțiilor care **sunt implementate corect cu fluxuri**, dar care nu se încadrează în timp din cauza unor probleme de eficiență la alte niveluri | ||
+ | * vom acorda punctajul total când problemele de eficiență sunt minore, soluția fiind totuși destul de rapidă (nu necesită mai mult decât dublul timpului cerut pe vmchecker) | ||
+ | * vom acorda 50% din punctaj când problemele de eficiență sunt majore | ||
===== Precizări ===== | ===== Precizări ===== | ||
Line 311: | Line 349: | ||
* {{:pp:24:teme:racket:etapa2.zip|etapa 2}} | * {{:pp:24:teme:racket:etapa2.zip|etapa 2}} | ||
* {{:pp:24:teme:racket:etapa3.zip|etapa 3}} | * {{:pp:24:teme:racket:etapa3.zip|etapa 3}} | ||
+ | * {{:pp:24:teme:racket:etapa4.zip|etapa 4}} | ||
===== Changelog ===== | ===== Changelog ===== | ||
+ | * 21.03 (ora 11:30) - Am adăugat o mică depunctare (10p) în etapa 4, pentru cazul în care funcțiile redefinite sunt redefinite exclusiv pentru fluxuri (folosind operatori de tip stream-*), nu pentru colecții (folosind operatori de tip collection-*), nerealizând astfel abstractizarea cerută în enunț (care ne permite să lucrăm alternativ cu liste sau cu fluxuri, efectuând modificări doar în interfața tipului Collection, nu și în restul funcțiilor). | ||
+ | * 18.03 (ora 11:45) - Am publicat etapa 4. | ||
* 14.03 (ora 21:15) - Am publicat etapa 3. | * 14.03 (ora 21:15) - Am publicat etapa 3. | ||
* 14.03 (ora 15:05) - Am adăugat o observație în etapa 2, la descrierea funcției ''%%suffixes->st%%'': funcția nu își sortează alfabetul; ramurile arborelui generat vor fi ordonate conform ordinii caracterelor din alfabetul primit ca argument. | * 14.03 (ora 15:05) - Am adăugat o observație în etapa 2, la descrierea funcției ''%%suffixes->st%%'': funcția nu își sortează alfabetul; ramurile arborelui generat vor fi ordonate conform ordinii caracterelor din alfabetul primit ca argument. | ||
Line 321: | Line 362: | ||
* [[https://hollywood.zbh.uni-hamburg.de/uploads/pubs/pdf/GieKur1995a.pdf|A comparison of imperative and purely functional suffix tree constructions]] | * [[https://hollywood.zbh.uni-hamburg.de/uploads/pubs/pdf/GieKur1995a.pdf|A comparison of imperative and purely functional suffix tree constructions]] | ||
* [[https://en.wikipedia.org/wiki/Suffix_tree|Suffix tree - Wikipedia]] | * [[https://en.wikipedia.org/wiki/Suffix_tree|Suffix tree - Wikipedia]] | ||
- | |||
- | |||