This is an old revision of the document!
Etapa 4 oferă un exemplu interesant de utilizare a fluxurilor. Veți reimplementa TDA-ul queue pentru a obține un plus de performanță și, cu condiția să fi respectat bariera de abstractizare în etapa 3, funcțiile implementate anterior vor funcționa fără modificări pe noua reprezentare.
Din nou, rezolvarea etapei începe cu implementarea TDA-ului queue în fișierul queue.rkt.
Din motive de performanță detaliate în schelet, reținem câmpul left al structurii queue ca flux (în contrast cu reprezentarea ca listă din etapa 3). Definiția structurii nu se modifică:
(define-struct queue (left right size-l size-r))
right (ca înainte)left (ca înainte)enqueue sau dequeue trebuie menținut invariantul size(left) ≥ size(right); astfel, niciun dequeue nu va găsi stiva left vidă enqueue sau dequeue produce situația size(left) = size(right) - 1, aplicăm o rotație: right în leftleft, nu toate deodată (dacă s-ar muta deodată nu am rezolva problema complexității, ci doar am deplasa-o asupra altor operații)Veți redefini interfața din etapa 3. Noile implementări depind de implementarea funcției de rotație:
(rotate left right Acc)
rotate calculează (cu evaluare întârziată) rezultatul left ++ (reverse right)size(left) = size(right) - 1, așadar găsește un număr echilibrat de elemente în cele două stiveleft, extragem (“pop”) și un element din right pe care îl adăugăm (“push”) în acumulatorul Accleft devine goală, right conține un singur element (size(left) = size(right) - 1), iar Acc conține toate elementele aflate inițial în right, în ordine inversă; acum adăugăm elementul din right la începutul Acc (în timp O(1)), și acesta este exact conținutul cu care trebuie să reinițializăm stiva leftExemplu:
(rotate (stream-cons 1 (stream-cons 2 (stream-cons 3 empty-stream))) '(7 6 5 4) empty-stream)
⇒
#<stream>
Mai precis, rezultatul este de forma:
(stream-cons 1 (rotate (stream-cons 2 (stream-cons 3 empty-stream)) '(6 5 4) (stream-cons 7 empty-stream)))
și, după cum știm din comportamentul constructorului stream-cons, apelul recursiv al funcției rotate este întârziat.
Dacă ulterior vom accesa restul acestui flux, vom evalua noul apel al lui rotate și vom obține un rezultat de forma (stream-cons 2 (rotate ....)), etc.
După ce ați finalizat implementarea TDA-ului, continuați dezvoltarea simulatorului în fișierul supermarket.rkt.
Simulatorul trebuie să modeleze toate situațiile de la etapa anterioară, plus situația în care o casă este închisă.
Exemplu:
(serve '((ana 7) (mia 2) 5 (ion 8) (close 2) (delay 1 10) (dan 2) 3 (ensure 5)) (list (empty-counter 1)) (list (empty-counter 2) (empty-counter 3)))
pentru ITEMS = 5:
C2 = (counter 2 7 7 (queue {(ana . 7)} '() 1 0)) C1 = (counter 1 2 2 (queue {(mia . 2)} '() 1 0))C1 = (counter 1 0 0 (queue {} '() 0 0))C2 = (counter 2 2 2 (queue {(ana . 7)} '() 1 0))C3 = (counter 3 0 0 (queue {} '() 0 0))C3 = (counter 3 8 8 (queue {(ion . 8)} '() 1 0))C1 = (counter 1 10 10 (queue {} '() 0 0))C3 = (counter 3 10 8 (queue {(ion . 8)} '((dan . 2)) 1 1))C1 = (counter 1 7 7 (queue {} '() 0 0))C2 = (counter 2 0 0 (queue {} '() 0 0))C3 = (counter 3 7 5 (queue {(ion . 8)} '((dan . 2)) 1 1))