This is an old revision of the document!
Tema urmărește familiarizarea cu specificul implementării structurilor de date în limbajele funcționale, problema eficienței fiind centrală. În limbajele imperative, eficiența este parțial alimentată de posibilitatea modificărilor distructive; de exemplu, actualizând în timp constant un element dintr-un vector. Prin contrast, în limbajele funcționale, modificările distructive sunt de obicei evitate, cu consecința persistenței structurilor de date. Cu alte cuvinte, dacă în abordarea imperativă dispunem de obicei doar de ultima variantă a unei structuri, care încorporează întregul istoric de modificări ale acesteia, în abordarea funcțională putem dispune simultan de toate versiunile intermediare ale acelei structuri. Ultima constrângere pare să impună costuri semnificative asupra implementării funcționale a structurilor de date, cu pierderi importante de eficiență. Vestea bună este că o reproiectare perspicace a acestor structuri poate recupera eficiența operațiilor; astfel, se combină complexitatatea comparabilă cu cea a structurilor imperative cu beneficiile purității funcționale.
Tema propune drept studiu de caz implementarea în Haskell a unei cozi de priorități, utilizând heap-uri binomiale. Implementarea imperativă standard a unui heap utilizează vectori și mizează pe accesul aleator în timp constant. După cum știm, listele înlănțuite din limbajele funcționale nu se pretează unei abordări fundamentate pe accesul aleator, care se realizează în timp liniar. Prin urmare, vom utiliza o reprezentare alternativă, în forma listelor de arbori binomiali, care oferă o complexitate logaritmică pentru toate operațiile, inclusiv pentru cea de combinare a două heap-uri, care în abordarea imperativă standard se realizează în timp liniar.
Tema este împărțită în 3 etape:
Deadline-ul depinde de semigrupa în care sunteți repartizați. Restanțierii care refac tema și nu refac laboratorul beneficiază de ultimul deadline, și anume în zilele de 02.05, 09.05, respectiv 16.05.
Rezolvările tuturor etapelor pot fi trimise până în ziua laboratorului 10 (deadline hard pentru toate etapele). Orice exercițiu trimis după un deadline soft se punctează la jumătate. Cu alte cuvinte, nota finală pe etapă se calculează conform formulei: n = (n1 + n2) / 2 (n1 = nota obținută înainte de deadline; n2 = nota obținută după deadline). Când toate submisiile preced deadline-ul, nota pe ultima submisie constituie nota finală (întrucât n1 = n2).
În fiecare etapă, veți valorifica ce ați învățat în săptămâna anterioară și veți avea la dispoziție un schelet de cod, cu toate că rezolvarea se bazează în mare măsură pe etapele anterioare. Enunțul caută să ofere o imagine de ansamblu atât la nivel conceptual, cât și în privința aspectelor care se doresc implementate, în timp ce detaliile se găsesc direct în schelet.
Operațiile pe heap-uri binomiale (cum este adăugarea unui nou element) sunt foarte similare conceptual celor pe numere binare (de exemplu, incrementare). Prin urmare, această etapă are un rol pregătitor, propunând o reprezentare a numerelor binare și definirea unor operații standard cu acestea. Heap-urile binomiale vor fi introduse propriu-zis în etapa 2.
Construcțiile și mecanismele de limbaj pe care le veți exploata în rezolvare sunt:
Modulul de interes din schelet este BinaryNumber
, care conține reprezentarea numerelor binare și operațiile pe care trebuie să le implementați:
BinaryNumber
definește reprezentarea numerelor binaretoDecimal
convertește din reprezentarea binară în cea zecimalătoBinary
realizează conversia inversăinc
și dec
incrementează, respectiv decrementează cu 1 un număr binar, ținând cont bineînțeles de transport, respectiv împrumutadd
adună două numere binarestack
pregătește terenul pentru înmulțirea a două numere binare, simulând maniera în care am dispune numerele pe hârtie, unul sub celălaltmultiply
realizează înmulțiri propriu-zise.
Găsiți detaliile despre funcționalitate și constrângeri de implementare, precum și exemple, direct în schelet. Aveți de completat definițiile care încep cu *** TODO ***
.
Pentru rularea testelor, încărcați în interpretor modulul TestBinaryNumber
și evaluați main
.
Este suficient ca arhiva pentru vmchecker să conțină modulul BinaryNumber
.
case
și gărzi, în locul if-urilor imbricate.