Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pp:26:teme:racket-supermarket [2026/03/12 09:06]
mihaela.balint created
pp:26:teme:racket-supermarket [2026/03/26 08:55] (current)
mihaela.balint
Line 1: Line 1:
-===== Etapa =====+===== Etapa =====
  
-Această etapă își propune exploatarea faptului că funcțiile sunt valori ​de ordinul întâiVa trebui să folosiți funcții curry și să abstractizațfuncții cu implementări similare. De asemenea, vă încurajăm să valorificați oportunitățile de utilizare a funcțiilor anonime și funcționalelor,​ deși enunțul nu impune acest lucru.+Etapa 4 oferă un exemplu interesant ​de utilizare a fluxurilorVeț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
  
-În această etapănumărul de case din supermarket nu mai este fixatVom avea: +Din nourezolvarea etapei începe cu implementarea TDA-ului ''​queue''​ în fișierul **queue.rkt**
-  * o listă fast-counters ​de case care acceptă doar clienți care au cumpărat maxim ITEMS produse + 
-  * o listă slow-counters de case deschise tuturor clienților +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ă: 
-Pentru ​ca în etapa următoare să putem determina ordinea ieșirii clienților din supermarket,​ introducem acum un nou câmp în structura counter+<​code ​scheme
-<​code ​lisp+(define-struct queue (left right size-l size-r))
-(define-struct ​counter (index tt et queue))+
 </​code>​ </​code>​
-  * et +  * o adăugare în coadă ​este o adăugare în stiva ''​right''​ (ca înainte) 
-    * vine de la "exit time", și reprezintă timpul rămas până când primul client din coadă ​va părăsi această casă +  o extragere din coadă este o extragere din stiva ''​left'' ​(ca înainte
-    depinde de numărul de produse cumpărate de acest client ​(1 produs = 1 minutși de eventualele întârzieri suferite de casa respectivă ​ +  * după fiecare operație ''​enqueue''​ sau ''​dequeue'' ​trebuie ​menținut invariantul ​ ''​%%size(left) ≥ size(right)%%'';​ astfelniciun ''​dequeue''​ nu va găsi stiva ''​left''​ vidă  
- +  * când o operație ''​enqueue''​ sau ''​dequeue''​ produce ​situația ​''​%%size(left= size(right) - 1%%'',​ aplicăm o **rotație**:​  
-În această etapă, simulatorul ​trebuie ​să modeleze atât situațiile de la etapa anterioarăcât și 2 noi situații: +    * mutăm "în mod leneș" toate elementele din ''​right''​ în ''​left''​ 
-  * situația ​în care cel mai avansat client ​(din punct de vedere al exit time-uluipărăsește supermarket-ul ​ +    ce înseamnă "leneș": elementele vor fi mutate, ​de faptunul câte unul, pe măsură ce extragem elemente din ''​left'',​ nu toate deodată (dacă ​s-ar muta deodată nu am rezolva problema complexității, ci doar am deplasa-asupra altor operații
-  situația în care este necesară deschiderea unor noi case pentru a micșora media timpilor totali ​de așteptare +   
- +Veți redefini interfața din etapa 3Noile implementări depind de implementarea ​funcției de rotație:
-În primul rândva trebui ​să adaptațserie de funcții de la etapa 1 astfel încât ele să țină cont de noua reprezentare (adică de numărul variabil de case șde prezența câmpului ''​%%'​et%%''​ în structura de tip casă). +
- +
-Exceptând aceste adaptărifuncțiile principale pe care va trebui să le implementați sunt: +
 <​file>​ <​file>​
-(update f counters index)+(rotate left right Acc)
 </​file>​ </​file>​
-  * update aplică transformarea f casei din counters care are indexul index, și întoarce lista counters actualizată +  * ''​rotate''​ calculează (cu evaluare întârziată) rezultatul ''​%%left ++ (reverse right)%%''​ 
-  ​+  * rotația se efectuează doar atunci când ''​%%size(left) = size(right) - 1%%'',​ așadar găsește un număr echilibrat de elemente în cele două stive 
 +  * la fiecare extragere ​din ''​left''​extragem ("​pop"​) ​și un element din ''​right''​ pe care îl adăugăm ("​push"​) în acumulatorul ''​Acc''​ 
 +  ​* când ''​left''​ 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 ''​left''​ 
 Exemplu: ​ Exemplu: ​
-<​code ​lisp+<​code ​scheme
-(update ​(λ (C) (struct-copy counter C [tt 0])) +(rotate ​(stream-cons 1 (stream-cons 2 (stream-cons 3 empty-stream))) 
-        ​(list (counter 1 2 2 '()) (counter 2 5 '())+        '(7 6 4
-        ​2)+        ​empty-stream)
 </​code>​ </​code>​
-=>  +=> 
-''​%%(list (counter ​1 2 2 '()) (counter 2 0 5 '​()))%%'' ​+''​%%#<​stream>​%%''​ \\ 
 +Mai precis, rezultatul este de forma: 
 +<code scheme>​ 
 +(stream-cons ​ 
 +             ​(rotate (stream-cons ​2 (stream-cons 3 empty-stream)) 
 +                     '​(4) 
 +                     ​(stream-cons 7 empty-stream))) 
 +</​code>​ 
 +și, conform comportamentului constructorului ''​stream-cons'',​ apelul recursiv al funcției ''​rotate'​' ​este întârziat. 
 +Când accesăm restul acestui flux (de exemplu, la ''​dequeue''​), evaluăm apelul întârziat,​ obținând un rezultat de forma ''​%%(stream-cons 2 (rotate ....))%%''​, etc. 
  
-<​file>​ +După ce ați finalizat implementarea TDA-ului, continuați implementarea în fișierul **etapa4.rkt**. 
-(remove-first-from-counter C) +   
-</​file>​ +Față de etapa anterioară,​ simulatorul tratează două cereri noi: 
-  ​* remove-first-from-counter scoate prima persoană din coada casei C +  * ''​(close index)''​ solicită închiderea casei cu indexul ''​index'', ​și redistribuirea clienților din coadă (cu excepția primului) 
-  * tt-ul și et-ul casei C trebuie ajustate în consecință  +  ''​(open index)''​ solicită deschiderea casei cu indexul ''​index''​ 
-    orice întârziere avea casa, ea dispare +Apare distincția între case deschise și case închise: în această etapă, cererile de tip "așezare la o casă",​ respectiv "​ensure"​ iau în considerare doar casele deschise. Modul în care reprezentați starea caselor (deschisă/​închisăeste la alegerea voastră.
-    * dispar produsele clientului care pleacă ​(și minutele asociate acestora+
-    * nicio altă casă nu este afectată (este ca și cum ar fi trecut timpul doar pe la casa C; acest lucru se va schimba ​în etapa 3)+
  
-Exemplu: + 
-<​code ​lisp+Exemplu ​pentru ''​ITEMS = 5''​
-(remove-first-from-counter (counter 1 50 5 '((ana . 3) (leo 35) (mia . 10))))+<​code ​scheme
 +(serve '((ana 7) (mia 2) 5 (ion 8) (dan 6) (close 2) (delay 1 15) (ema 2) (open 2) 2 (geo 5) (close 1) (ensure 7)) 
 +       (list (empty-counter 1)) 
 +       (list (empty-counter 2) (empty-counter ​3))) 
 +</​code>​ 
 +  * avem o casă fast (o numim ''​C1''​) și două case slow (le numim ''​C2''​ și ''​C3''​) 
 +  * când ilustrăm starea caselor: 
 +    * o casă este o colecție de ''​index'',​ ''​tt'',​ ''​et''​ și ''​queue''​ (dar puteți modifica structura, dacă doriți) 
 +    * vizualizăm elementele fluxurilor între acolade (în loc să scriem ''#<​stream>'',​ ceea ce nu este tocmai informativ) 
 +  * primele două cereri distribuie cei doi clienți astfel: 
 +    * ''​ana''​ la ''​C2''​ => ''​%%C2 = (counter ​2 7 7 (queue {(ana . 7)} '​() ​0))%%''​  
 +    * ''​mia''​ la ''​C1''​ => ''​%%C1 = (counter 1 2 2 (queue {(mia . 2)} '() 1 0))%%''​ 
 +    * obs: în etapa trecută ''​ana''​ și ''​mia''​ apăreau ca elemente în stiva ''​right'';​ acum ele sunt în stiva ''​left'',​ deoarece s-a efectuat o rotație, necesară pentru menținerea invariantului ''​%%size(left) ≥ size(right)%%''​  
 +  * apoi trec ''​5'' minute, după care situația este: 
 +    * ''​mia''​ a ieșit de la ''​C1'',​ care a rămas goală => ''​%%C1 = (counter 1 0 0 (queue {} '() 0 0))%%''​ 
 +    * la ''​C2''​ au trecut ''​5''​ minute => ''​%%C2 = (counter 2 2 2 (queue {(ana . 7)} '() 1 0))%%''​ 
 +    * ''​C3''​ a rămas cum era: goală și neîntârziată => ''​%%C3 = (counter ​0 0 (queue {} '(0 0))%%''​ 
 +  * următoarele două cereri distribuie cei doi clienți astfel: 
 +    * ''​ion''​ la ''​C3''​ => ''​%%C3 = (counter 3 8 8 (queue {(ion 8)} '() 1 0))%%''​ 
 +    * ''​dan''​ la ''​C2''​ => ''​%%C2 = (counter 2 8 2 (queue {(ana . 7)} '((dan . 6)) 1 1))%%''​ 
 +  * ''​C2''​ se închide => ''​ana''​ rămâne la ''​C2'',​ iar ''​dan''​ se mută la ''​C3''​ 
 +    * => ''​%%C2 = (counter 2 2 2 (queue {(ana . 7)} '() 1 0))%%''​ și nu mai primește clienți 
 +    * => ''​%%C3 = (counter 3 14 8 (queue {(ion . 8)} '((dan . 6)) 1 1))%%''​ 
 +  * ''​C1''​ este întârziată cu ''​15''​ minute => ''​%%C1 = (counter 1 15 15 (queue {} '() 0 0))%%''​ 
 +  * ''​ema''​ se așază la ''​C3''​ => ''​%%C3 = (counter 3 16 8 (queue {(ion . 8) <​flux-neevaluat-care-va-produce-dan-și-ema>​} '() 3 0))%%''​ 
 +    * ''​C2''​ are ''​tt''​ mai mic, însă ''​C2''​ este închisă, deci se alege între ''​C1''​ și ''​C3''​ 
 +  * ''​C2''​ se deschide, fără să producă alte modificări 
 +  * apoi trec ''​2''​ minute, după care situația este: 
 +    * întârzierea de la ''​C1''​ s-a consumat parțial => ''​%%C1 = (counter 1 13 13 (queue {} '() 0 0))%%''​ 
 +    * ''​ana''​ a ieșit de la ''​C2''​ => ''​%%C2 = (counter 2 0 0 (queue {} '() 0 0))%%''​ 
 +    * la ''​C3''​ au trecut ''​2''​ minute => ''​%%C3 = (counter 3 14 6 (queue {(ion . 8) <​flux...>​} '() 3 0))%%''​ 
 +  * ''​geo''​ se așază la ''​C2''​ => ''​%%C2 = (counter 2 5 5 (queue {(geo . 5)} '() 1 0))%%''​ 
 +  * ''​C1''​ se închide, fără să producă alte modificări 
 +  * ''​ensure''​ compară media timpilor totali ai caselor deschise cu ''​7''​ 
 +    * ''​tt2''​ + ''​tt3''​ = ''​5''​ + ''​14''​ = ''​19''​ => ''​tt-mediu = 19 / 2 > 7''​ 
 +    * ''​tt1''​ nu participă la medie întrucât ''​C1''​ este închisă 
 +    * se adaugă o casă slow goală (''​C4''​) => ''​tt-mediu = 19 / 3 ≤ 7''​ (deci ne oprim aici cu adăugarea) 
 +Rezultat final: 
 +<code scheme>​ 
 +(list 
 + '​((1 . mia) (2 ana)
 + (cons 2 (queue #<​stream>​ '() 1 0)) 
 + (cons 3 (queue #<​stream>​ '() 3 0)))
 </​code>​ </​code>​
-=>  
-''​%%(counter 1 45 35 '((leo . 35) (mia . 10)))%%''​ 
- 
-<​file>​ 
-(serve requests fast-counters slow-counters) 
-</​file>​ 
-  * serve primește o listă de cereri (așezări la coadă, întârzieri,​ ieșiri de la casă, ajustări ale numărului de case) și le tratează în ordine, în sensul că actualizează casele din fast-counters și slow-counters pe măsură ce situația lor evoluează 
- 
-Exemplu: ​ 
-<code lisp> 
-(serve '((ana 8) (mia 2) (mara 14) (ion 7) (remove-first) (ensure 5) (remove-first)) 
-       (list (empty-counter 1) (empty-counter 2)) 
-       (list (empty-counter 3) (empty-counter 4))) 
-</​code> ​       pentru ITEMS = 5:  
-  * observăm că avem 2 case fast (pentru simplitate le vom numi C1 și C2) și 2 case slow (le vom numi C3 și C4) 
-  * primele 4 cereri distribuie cei 4 clienți astfel: 
-    * ana la C3 (prima casă slow cu tt=0) => ''​%%C3 = (counter 3 8 8 '((ana . 8)))%%''​ 
-    * mia la C1 (prima casă fast cu tt=0) => ''​%%C1 = (counter 1 2 2 '((mia . 2)))%%''​ 
-    * mara la C4 (casa slow cu tt minim) ​ => ''​%%C4 = (counter 4 14 14 '​((mara . 14)))%%''​ 
-    * ion la C3 (casa slow cu tt minim) ​  => ''​%%C3 = (counter 3 15 8 '((ana . 8) (ion . 7)))%%''​ 
-  * remove-first caută cel mai avansat client pentru a-l scoate de la casă 
-    * cel mai avansat client este mia (et=2) 
-    * ea este scoasă de la C1             => ''​%%C1 = (counter 1 0 0 '​())%%''​ (observați tt și et) 
-  * ensure compară media timpilor totali cu 5 
-    * tt1 + tt2 + tt3 + tt4 = 0 + 0 + 15 + 14 = 29 => ttmed = 29 / 4 > 5 
-    * se adaugă o casă slow goală (C5) => ttmed = 29 / 5 > 5 
-    * se adaugă o casă slow goală (C6) => ttmed = 29 / 6 ≤ 5 (deci putem trece la cererea următoare) 
-  * remove-first caută cel mai avansat client pentru a-l scoate de la casă 
-    * cel mai avansat client este ana (et=8)  ​ 
-    * ea este scoasă de la C3             => ''​%%C3 = (counter 3 7 7 '((ion . 7)))%%''​ (observați tt și et) 
  
pp/26/teme/racket-supermarket.1773299183.txt.gz · Last modified: 2026/03/12 09:06 by mihaela.balint
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