This shows you the differences between two versions of the page.
|
programare:laboratoare:lab12 [2025/12/14 02:26] darius.neatu |
programare:laboratoare:lab12 [2026/01/11 17:19] (current) teodor.birleanu [PCLP Laborator12: Optimizarea programelor cu operații pe biți] |
||
|---|---|---|---|
| Line 2: | Line 2: | ||
| **Responsabili:** | **Responsabili:** | ||
| - | * [[neatudarius@gmail.com|Darius Neațu (2019 - Prezent )]] | + | * [[neatudarius@gmail.com|Darius Neațu (2019 - Prezent)]] |
| * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip (2019 - Prezent)]] | * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip (2019 - Prezent)]] | ||
| - | * [[rares96cheseli@gmail.com|Rareș Cheșeli (2018, 2017)]] | + | * [[teodor.matei.birleanu@gmail.com|Bîrleanu Teodor Matei (2025 - prezent)]] |
| + | * [[rares96cheseli@gmail.com|Rareș Cheșeli (2017 - 2018)]] | ||
| ==== Obiective ==== | ==== Obiective ==== | ||
| Line 445: | Line 446: | ||
| </spoiler> | </spoiler> | ||
| + | ==== Exerciții ==== | ||
| + | Exercițiile pentru laborator se găsesc pe [[https://acs-pclp.github.io/laboratoare/12 | PPCLP Laborator12: Optimizarea programelor cu operații pe biți]]. | ||
| - | ==== Exerciții ==== | ||
| - | |||
| - | ==Precizari generale== | ||
| - | Rezolvați împreună cu asistentul pe tablă, exercițiile 0-4, apoi rezolvați invidual exercițiul 5. | ||
| - | |||
| - | == 0: Verificare că un număr e par == | ||
| - | Să se verifice folosind operații pe biți că un număr natural n e par. | ||
| - | <code C> | ||
| - | int is_even(int n); | ||
| - | </code> | ||
| - | |||
| - | == 1. Calcul putere a lui 2 (0p) == | ||
| - | Să se scrie o funcție care să calculeze $2^n$, unde $ n <= 30 $. | ||
| - | <code C> | ||
| - | int pow2(int n); | ||
| - | </code> | ||
| - | Răspundeți la întrebarea: **are sens** să scriem o funcție? | ||
| - | |||
| - | == 2. Negarea biților unui număr n (0p) == | ||
| - | Să se scrie o funcție care să nege biții unui număr n (32 biți). | ||
| - | <code C> | ||
| - | int flip_bits(int n); | ||
| - | </code> | ||
| - | Răspundeți la întrebarea: **are sens** să scriem o funcție? | ||
| - | |||
| - | == 3. Afișarea biților unui număr n (0p)== | ||
| - | Să se scrie o funcție care să afișeze toți biții unui număr întreg pe 32 biți. | ||
| - | <code C> | ||
| - | void print_bits(int n); | ||
| - | </code> | ||
| - | |||
| - | |||
| - | == 4. Verificare că un număr este putere al lui 2 (0p)== | ||
| - | Să se scrie o funcție care verifică dacă un număr întreg n pe 32 biți este puterea a lui 2. Funcția va returna 1 dacă n este putere a lui 2, 0 altfel. | ||
| - | <code C> | ||
| - | int is_power2(int n); | ||
| - | </code> | ||
| - | |||
| - | <spoiler Hint> | ||
| - | Analizați reprezentarea în baza 2 a lui n (ex. n = 16 si n = 5). | ||
| - | </spoiler> | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | \\ | ||
| - | Implementați invidual următoarea problemă. | ||
| - | |||
| - | |||
| - | == 5. bitset (10p )== | ||
| - | O mulțime de numere întregi poate fi reprezentată astfel: spunem că un număr **i ** aparține unei mulțimi S dacă bit-ul al i-lea din vectorul S are valoarea 1. | ||
| - | |||
| - | Pentru eficientă, vectorul S va conține date de tipul **unsigned char** (reamintim ca **sizeof(unsigned char) == 1 byte** adică **8 biți**). | ||
| - | |||
| - | <note> | ||
| - | Pentru a folosi cu ușurință același cod facând schimbări minime (de exemplu schimbăm dimensiunea maximă a unei mulțimi), putem să ne definim propriul tip astfel: | ||
| - | |||
| - | <code C> | ||
| - | #define SET_SIZE 100 // aceasta este o macrodefiniție (momentan o putem privi ca pe O CONSTANTA CARE ARE VALOAREA 100 | ||
| - | typedef unsigned char SET[SET_SIZE]; // definesc tipul SET, care este un vector cu maxim 100 de elemente de tip unsigned char | ||
| - | </code> | ||
| - | |||
| - | Cele două linii de mai sus vor fi puse imediat dupa includerea directivelor header! | ||
| - | |||
| - | </note> | ||
| - | |||
| - | |||
| - | |||
| - | === 5.1 === | ||
| - | |||
| - | Implementați următoarele funcții. Realizați un program în C prin care să demonstrați că funcțiile implementate funcționează. | ||
| - | |||
| - | <note> | ||
| - | Există un [[https://ocw.cs.pub.ro/courses/programare/laboratoare/lab07-bitset-example | exemplu]] detaliat care vă explică cum functionează aceastea. | ||
| - | |||
| - | Treceți la subpunctul următor abia după ce v-ați asigurat că acestea funcționează. | ||
| - | </note> | ||
| - | |||
| - | * **adăugarea** unui element în mulțime | ||
| - | <code C> | ||
| - | // insert_in_set(s, n) - adauga numarul n in multimea s | ||
| - | void insert_in_set(SET s, unsigned int n); | ||
| - | </code> | ||
| - | |||
| - | * **ștergerea** unui element din mulțime | ||
| - | <code C> | ||
| - | // delete_from_set(s, n) - scoate numarul n din multime s | ||
| - | void delete_from_set(SET s, unsigned int n); | ||
| - | </code> | ||
| - | |||
| - | * **verificarea** faptului că un element n **aparține** unei mulțimi | ||
| - | <code C> | ||
| - | // is_in_set(s, n) - returneaza 1 daca n este in s, 0 altfel | ||
| - | int is_in_set(SET s, unsigned int n); | ||
| - | </code> | ||
| - | |||
| - | * **ștergerea** tuturor elementelor din mulțime | ||
| - | <code C> | ||
| - | // delete_all_from_set(s) - elimina toate elementele din multime | ||
| - | void delete_all_from_set(SET s); | ||
| - | </code> | ||
| - | |||
| - | * calcularea **cardinalul** unei mulțimi | ||
| - | <code C> | ||
| - | // card_set(s) - returneaza cardinalul multimii s | ||
| - | int card_set(SET s); | ||
| - | </code> | ||
| - | |||
| - | * verificarea faptului că mulțimea este **vidă** | ||
| - | <code C> | ||
| - | // is_empty_set(s) - verifica daca multimea este sau nu goala | ||
| - | // returneaza 1 daca este, 0 daca nu este | ||
| - | int is_empty_set(SET s); | ||
| - | </code> | ||
| - | |||
| - | * o funcție care **să citească de la tastatură** o mulțime | ||
| - | <code C> | ||
| - | // read_set(s) - functia citeste numarul n de elemente care se afla in a | ||
| - | // apoi citeste cele n numere si le insereaza in a | ||
| - | // va returna numarul n citit (numarul de elemente) | ||
| - | int read_set(SET s); | ||
| - | </code> | ||
| - | |||
| - | * o funcție care **să afișeze** pe ecran elementele care se află într-o mulțime | ||
| - | <code C> | ||
| - | // print_set(s) - functia printeaza elementele multimii s | ||
| - | void print_set(SET s); | ||
| - | </code> | ||
| - | | ||
| - | Urmăriți acest [[https://ocw.cs.pub.ro/courses/programare/laboratoare/lab07-bitset-example | exemplu cu bitset]] pentru a înțele cum funcționeazăaceste operații. | ||
| - | |||
| - | === 5.2 === | ||
| - | Realizati un program care, utilizând metodele defite anterior, citește 2 mulțimi A (n și B și afișează: $ A U B, A ∩ B, A - B, B - A $. | ||
| - | |||
| - | Pentru a realiza acest lucru, va trebui să implementați următoarele funcții: | ||
| - | * **reuniunea** a două mulțimi (**1p**) | ||
| - | <code C> | ||
| - | // c = a U b | ||
| - | void merge_set(SET a, SET b, SET c); | ||
| - | </code> | ||
| - | |||
| - | * **intersecția** a două mulțimi (**1p**) | ||
| - | <code C> | ||
| - | // c = a n b | ||
| - | void intersect_set(SET a, SET b, SET c); | ||
| - | </code> | ||
| - | |||
| - | * **diferența** a două mulțimi (**1p**) | ||
| - | <code C> | ||
| - | // c = a \ b | ||
| - | void diff_set(SET a, SET b, SET c); | ||
| - | </code> | ||
| - | |||
| - | În final va trebui sa creați o funcție ** main ** și să faceți un program care rezolvă cerința folosind funcțiile implementate. | ||
| - | |||
| - | ==== B1. Optimizations ==== | ||
| - | O să învățați pe viitor că nu toate înstrucțiunile sunt la fel din punct de vedere al timpului de execuției. Ca un punct de start, gândiți-vă că dacă ați face pe foaie o adunare sau o înmultire, durează mai mult să înmulțiți decât să adunați. Această dificulate o are și procesorul din laptopul vostru! | ||
| - | |||
| - | Pentru a-l ajuta și a face programul mai rapid, putem înlocui operații costisitoare (** * **, ** / **) cu altele mai puțin costistoare (** + **, ** - **). Cele mai rapide instrucțiuni sunt cele care lucrează direct pe biți (deoarece numerele sunt stocate în memorie în binar, deci este modul natural de lucru pentru calculator). | ||
| - | |||
| - | Acest exercițiu vă propune să aplicați aceste optimizări pe codul vostru! | ||
| - | |||
| - | <spoiler Hint> | ||
| - | Pentru a completa acest bonus, **NU** aveți voie să folosiți operatorii ** /, *, % ** ! Încercați să folosiți operații pe biți! | ||
| - | </spoiler> | ||
| - | |||
| - | ==== B2. MSB/LSB ==== | ||
| - | Să se scrie o câte o funcție pentru aflarea MSB(Most significant bit), respectiv LSB(Least significant bit), pentru un număr n pe 32 biți. | ||
| - | <code C> | ||
| - | int get_lsb(int n); | ||
| - | int get_msb(int n); | ||
| - | </code> | ||
| - | |||
| - | <spoiler Hint> | ||
| - | Analizați reprezentarea în baza 2 a lui n. | ||
| - | </spoiler> | ||
| - | |||
| - | |||
| - | |||
| - | ==== Probleme de interviu ==== | ||
| - | Pentru cei interesați, recomandăm rezolvarea și următoarelor probleme, care sunt des întâlnite la interviuri. | ||
| - | <note warning> | ||
| - | Atenție! Problemele din această categorie au un nivel de dificultate ridicat, peste cel cerut la cursul de PC. | ||
| - | |||
| - | Recomandăm totuși rezolvarea acestor probleme pentru cei care doresc să aprofundeze lucrul cu operații pe biți. | ||
| - | </note> | ||
| - | |||
| - | <spoiler Swap bits> | ||
| - | Se dă un număr n natural pe 32 de biți. Se cere să se calculeze numărul obținut prin interschimbarea biților de rang par cu cel de rang impar. | ||
| - | |||
| - | Exemplu: n = 2863311530 = > m = 1431655765 | ||
| - | |||
| - | <note> | ||
| - | Hint: Reprezentarea numerelor în baza 2 ([http://www.binaryhexconverter.com/decimal-to-binary-converter | convertor]]). | ||
| - | </note> | ||
| - | |||
| - | </spoiler> | ||
| - | |||
| - | <spoiler Element unic din șir> | ||
| - | Fie un șir cu ** 2n + 1 ** numere întregi, dintre care n numere apar de câte 2 ori, iar unul singur este unic. | ||
| - | Să se gasească elementul unic. | ||
| - | |||
| - | Exemplu: | ||
| - | n = 5 și sirul [1, 4, 4, 1, 5] | ||
| - | Numărul unic este 5. | ||
| - | <note> | ||
| - | Hint: Încercați să nu folosiți tablouri. | ||
| - | </note> | ||
| - | |||
| - | Follow-up 1: Șirul are $2*n + (2 * p + 1)$ numere. Se sție că un singur număr apare de un număr impar de ori (2p + 1), iar celelalte apar de un număr par de ori. Cum găsiți numărul care apare de un număr impar de ori? | ||
| - | |||
| - | Exemplu: | ||
| - | n = 5 și sirul [1, 1, 4, 4, 4, 4, 5, 5, 5] | ||
| - | Răspunsul este 5. | ||
| - | |||
| - | Follow-up 2: Șirul are $2n + 2$ numere, n numere apar de câte 2 ori, iar 2 numere sunt unice. Cum găsiți cele 2 numer unice? | ||
| - | |||
| - | Exemplu: | ||
| - | n = 5 și sirul [1, 4, 4, 1, 5, 6] | ||
| - | Numărele unice sunt 5 și 6. | ||
| - | |||
| - | TODO: sursă | ||
| - | </spoiler> | ||
| - | |||
| - | <spoiler Căutare binară pe biți> | ||
| - | Realizează o funcție de căutare pe binară, utilizând operații pe biți pentru optimizarea acestei implementări. | ||
| - | |||
| - | Follow up: Puteți găsi alt algoritm care să nu se bazeze pe împarțirea vectorului în două și compararea elementului din mijloc cu cel cautat? | ||
| - | |||
| - | <note> | ||
| - | Hint: | ||
| - | [[http://www.infoarena.ro/problema/cautbin | caut bin]] și [[http://www.infoarena.ro/multe-smenuri-de-programare-in-cc-si-nu-numai | Multe "smenuri" de programare in C/C++... si nu numai!]] | ||
| - | </note> | ||
| - | |||
| - | </spoiler> | ||
| - | |||
| - | |||
| - | |||
| - | <spoiler Jocul NIM> | ||
| - | Se dau n grămezi, fiecare conţinând un anumit număr de pietre. Doi jucători vor începe să ia alternativ din pietre, astfel: la fiecare pas, jucătorul aflat la mutare trebuie să îndepărteze un număr nenul de pietre dintr-o singură grămadă. Câştigătorul este cel care ia ultima piatră. | ||
| - | Să se determine dacă jucătorul care ia primele pietre are strategie sigură de câştig. | ||
| - | |||
| - | Exemple | ||
| - | n = 4, gramezi = [1 3 5 7], raspuns = NU | ||
| - | n = 3, gramezi = [4 8 17], raspuns = DA | ||
| - | |||
| - | <note> | ||
| - | Hint: [[http://www.infoarena.ro/problema/nim | nim]] | ||
| - | </note> | ||
| - | |||
| - | </spoiler> | ||
| - | |||
| - | <spoiler Sushi> | ||
| - | Enunt: [[http://www.infoarena.ro/problema/sushi | sushi ]] | ||
| - | </spoiler> | ||