This is an old revision of the document!
Această etapă își propune să sublinieze importanța abstractizării. Va trebui să vă definiți propriul TDA (tip de date abstract) și să oferiți o interfață completă (un set de constructori și operatori) prin care utilizatorul poate manipula valorile tipului, independent de implementarea din spate. Apoi, este esențial ca voi înșivă să folosiți TDA-ul doar prin intermediul interfeței (în etapa 4 veți înțelege și mai bine de ce este esențial).
Veți începe rezolvarea etapei prin a implementa TDA-ul queue
în fișierul queue.rkt.
Acest tip reprezintă o coadă (first-in-first-out) ca pe o structură:
(define-struct queue (left right size-l size-r))
right = '(1)
, right = '(2 1)
left = '()
din right = '(2 1)
⇒ left = '(2)
, right = '(1)
(primul pop din right îl extrage pe 2 și îi face push în left) ⇒ left = '(1 2)
, right = '()
(apoi pop din right îl extrage pe 1 și îi face push în left)left = '()
, right = '(2 1)
⇒ left = '(1 2)
, right = '()
(după mutarea elementelor) ⇒ left = '(2)
, right = '()
(după scoaterea primului element)Sarcina voastră este să implementați interfața TDA-ului queue:
empty-queue : -> queue (constructor nular pentru o coadă goală) queue-empty? : queue -> Bool (operator care verifică dacă o coadă este goală) enqueue : Elem x queue -> queue (operatorul de adăugare în coadă) dequeue : queue -> queue (operatorul de scoatere din coadă) top : queue -> Elem (operatorul de vizualizare a elementului din vârful cozii)
Această reprezentare pentru coadă asigură cost amortizat O(1) pentru operațiile de enqueue și dequeue. Vom folosi această reprezentare pentru câmpul queue al structurii counter, întrucât este mai eficientă decât reprezentarea cu liste Racket din etapele 1 și 2.
După ce ați finalizat implementarea TDA-ului, continuați dezvoltarea simulatorului în fișierul supermarket.rkt.
În primul rând, va trebui să adaptați o serie de funcții de la etapa 2 astfel încât ele să țină cont de noua reprezentare (în care câmpul queue din structura counter este de tip coadă (queue) - TDA-ul implementat de voi; este o coincidență că numele câmpului coincide cu numele tipului, în niciun caz nu era necesar acest lucru).
În plus față de etapa anterioară, în această etapă simulatorul trebuie să modeleze trecerea timpului. Până acum, simulatorul trata așezările la cozi, întârzierile și deschiderile de noi case ca și cum s-ar produce în ordine, dar la un același moment de timp. Acest lucru nu corespunde realității - între diversele evenimente este firesc să treacă timp, timp în care clienții avansează la case și, la un moment dat, părăsesc supermarketul.
Exceptând adaptările menționate, funcțiile principale pe care va trebui să le implementați sunt:
(pass-time-through-counter minutes)
Exemplu:
((pass-time-through-counter 5) (counter 1 12 7 (make-queue '() '((ada . 7)) 0 1)))
⇒
(counter 1 7 2 (queue '() '((ada . 7)) 0 1))
(serve requests fast-counters slow-counters)
requests
în care elementele sunt:Exemplu:
(serve '((ana 14) (mia 2) 5 (ion 7) (delay 1 2) 7) (list (empty-counter 1)) (list (empty-counter 2) (empty-counter 3)))
pentru ITEMS = 5:
C2 = (counter 2 14 14 (queue '() '((ana . 14)) 0 1))
C1 = (counter 1 2 2 (queue '() '((mia . 2)) 0 1))
C1 = (counter 1 0 0 (queue '() '() 0 0))
C2 = (counter 2 9 9 (queue '() '((ana . 14)) 0 1))
C3 = (counter 3 0 0 (queue '() '() 0 0))
'((1 . mia))
(mia de la C1)C3 = (counter 3 7 7 (queue '() '((ion . 7)) 0 1))
C1 = (counter 1 2 2 (queue '() '() 0 0))
C1 = (counter 1 0 0 (queue '() '() 0 0))
C2 = (counter 2 2 2 (queue '() '((ana . 14)) 0 1))
C3 = (counter 3 0 0 (queue '() '() 0 0))
'((1 . mia) (3 . ion))