Differences

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

Link to this comparison view

pa:laboratoare:laborator-01 [2018/03/02 14:15]
traian.rebedea [Turnurile din Hanoi]
pa:laboratoare:laborator-01 [2022/03/21 23:11] (current)
radu.nichita [Exerciții]
Line 1: Line 1:
 ====== Laborator 01: Divide et Impera ====== ====== Laborator 01: Divide et Impera ======
-Responsabili:​ 
-  * [[visanr95@gmail.com|Radu Vișan]] 
-  * [[cristb@gmail.com|Cristian Banu]] 
-  * [[neatudarius@gmail.com|Darius Neațu]] 
  
  
 ===== Obiective laborator ===== ===== Obiective laborator =====
  
-  * Înțelegerea conceptului teoretic din spatele descompunerii+  * Înțelegerea conceptului teoretic din spatele descompunerii ​unei probleme
   * Rezolvarea de probleme abordabile folosind conceptul ​ de Divide et Impera   * Rezolvarea de probleme abordabile folosind conceptul ​ de Divide et Impera
  
  
-===== Precizari initiale ​=====+===== Precizări inițiale ​=====
 <​note>​ <​note>​
-Toate exemplele de cod se gasesc in {{pa:new_pa:demo-lab01.zip}}.+Toate exemplele de cod se găsesc pe pagina [[https://​github.com/​acs-pa/​pa-lab/​tree/​main/​demo/​lab01|pa-lab::demo/lab01]].
  
-Acestea ​apar incorporate si in textul laboratorului pentru a facilita parcurgerea ​cursiva ​laboratorului.+Exemplele de cod apar încorporate și în textul laboratorului pentru a facilita parcurgerea ​cursivă ​acestuia. ATENȚIE! Varianta actualizată a acestor exemple se găsește întotdeauna pe GitHub.
 </​note>​ </​note>​
  
-  * Toate bucatile ​de cod prezentate ​in partea ​introductiva ​a laboratorului (inainte ​de exercitii) au fost testate. Cu toate acestea, este posibil ca din cauza mai multor factori (formatare, caractere invizibile puse de browser etc) un simplu copy-paste ​sa nu fie de ajuns pentru a compila codul. +  * Toate bucățile ​de cod prezentate ​în partea ​introductivă ​a laboratorului (înainte ​de exerciții) au fost testate. Cu toate acestea, este posibil ca din cauza mai multor factori (formatare, caractere invizibile puse de browser etc.) un simplu copy-paste ​să nu fie de ajuns pentru a compila codul. 
-  * Va rugam sa incercati si codul din arhiva ​** demo-lab01.zip**, inainte ​de a raporta ca ceva nu merge:D +  * Vă rugam să compilați ​**DOAR** codul de pe GitHub. Pentru raportarea problemelor,​ contactați unul dintre maintaineri.  
-  * Pentru orice problema legata ​de continutul ​acestei pagini, ​va rugam sa dati email unuia dintre responsabili.+  * Pentru orice problemă legată ​de conținutul ​acestei pagini, ​vă rugam să dați e-mail ​unuia dintre responsabili.
  
 ===== Importanţă – aplicaţii practice ===== ===== Importanţă – aplicaţii practice =====
Line 35: Line 31:
 ===== Prezentarea generală a problemei ===== ===== Prezentarea generală a problemei =====
  
-O descriere a tehnicii D&I: “Divide and Conquer algorithms break the problem into several sub-problems that are similar to the original problem but smaller in size, solve the sub-problems recursively,​ and then combine these solutions to create a solution to the original problem.” ​[7]+O descriere a tehnicii D&I: “Divide and Conquer algorithms break the problem into several sub-problems that are similar to the original problem but smaller in size, solve the sub-problems recursively,​ and then combine these solutions to create a solution to the original problem.”
  
-Deci un algoritm D&I **împarte problema** în mai multe subprobleme similare cu problema inițială şi de dimensiuni mai mici, **rezolva sub-problemele** recursiv şi apoi **combina ​soluțiile** obţinute pentru a obține soluția problemei inițiale.+Deci un algoritm D&I **împarte problema** în mai multe subprobleme similare cu problema inițială şi de dimensiuni mai mici, **rezolvă subproblemele** recursiv şi apoi **combină ​soluțiile** obţinute pentru a obține soluția problemei inițiale.
  
 Sunt trei pași pentru aplicarea algoritmului D&I: Sunt trei pași pentru aplicarea algoritmului D&I:
  
   * **Divide**: împarte problema în una sau mai multe //probleme similare de dimensiuni mai mici//.   * **Divide**: împarte problema în una sau mai multe //probleme similare de dimensiuni mai mici//.
-  * **Impera** (stăpânește): ​rezolva subprobleme ​recursiv; dacă dimensiunea sub-problemelor este mica se rezolva ​iterativ. +  * **Impera** (stăpânește): ​rezolvă subproblemele ​recursiv; dacă dimensiunea sub-problemelor este mică, ​se rezolvă ​iterativ. 
-  * **Combină**:​ combină soluțiile ​sub-problemelor ​pentru a obține soluția problemei inițiale.+  * **Combină**:​ combină soluțiile ​subproblemelor ​pentru a obține soluția problemei inițiale.
  
 Complexitatea algoritmilor D&I se calculează după formula: Complexitatea algoritmilor D&I se calculează după formula:
Line 49: Line 45:
 $T(n) = D(n) + S(n) + C(n)$, $T(n) = D(n) + S(n) + C(n)$,
  
-unde $D(n)$, $S(n)$ şi $C(n)$ reprezintă complexitățile celor 3 pași descriși mai sus: divide, stăpânește respectiv combină.+unde $D(n)$, $S(n)$ şi $C(n)$ reprezintă complexitățile celor 3 pași descriși mai sus: divide, stăpâneșterespectiv combină.
  
 ===== Probleme clasice ===== ===== Probleme clasice =====
  
 ==== MergeSort ==== ==== MergeSort ====
-=== Enunt ===+=== Enunț ​===
 Sortarea prin interclasare (MergeSort [[http://​www.sorting-algorithms.com/​merge-sort|[1]]]) este un algoritm de sortare de vectori ce folosește paradigma D&I: Sortarea prin interclasare (MergeSort [[http://​www.sorting-algorithms.com/​merge-sort|[1]]]) este un algoritm de sortare de vectori ce folosește paradigma D&I:
  
Line 62: Line 58:
  
 === Pseudocod === === Pseudocod ===
-Mai jos gasiti ​algoritmul MergeSort scris in pseudocod.+Mai jos găsiți ​algoritmul MergeSort scris în pseudocod.
  
 <spoiler Pseudocod>​ <spoiler Pseudocod>​
Line 96: Line 92:
  
 <spoiler Implementare in C++> <spoiler Implementare in C++>
-Mai jos puteti ​gasi o implementare ​in C++.+Mai jos puteti ​găsi o implementare ​în C++.
  
 <code cpp> <code cpp>
Line 176: Line 172:
  
  
-  * **complexitate ​temporala** : $T=O(n * log(n))$ +  * **complexitate ​temporală** : $T=O(n * log(n))$ 
-    * Ce inseamna aceasta metricaMasoara ​efectiv **timpul de executie** al algoritmului (nu include citiri, ​afisari ​etc).+    * Ce înseamnă această metricăMăsoara ​efectiv **timpul de execuție** al algoritmului (nu include citiri, ​afișări ​etc).
   * **complexitate spatiala** : $S=O(n)$   * **complexitate spatiala** : $S=O(n)$
-    * Ce inseamna aceasta ​metrica? ​Masoara ​efectiv **memoria ​suplimentara** folosita ​de algoritm (in acest caz ne referim strict la buffer-ul temporar).+    * Ce înseamnă această ​metrica? ​Măsoara ​efectiv **memoria ​suplimentară** folosită ​de algoritm (în acest caz ne referim strict la buffer-ul temporar).
  
 <​note>​ <​note>​
-Retineti ​cele doua conventii ​despre ​complexitati ​de mai sus. Le vom folosi pentru restul semestrului.+Rețineți ​cele două convenții ​despre ​complexități ​de mai sus. Le vom folosi pentru restul semestrului.
 </​note>​ </​note>​
 ==== Binary Search ==== ==== Binary Search ====
-=== Enunt ===+=== Enunț ​===
 Se dă un **vector sortat crescător** ($v[1]$, $v[2]$, ..., $v[n]$) ce conține valori reale distincte și o valoare x.  Se dă un **vector sortat crescător** ($v[1]$, $v[2]$, ..., $v[n]$) ce conține valori reale distincte și o valoare x. 
  
-Sa se găsească la ce **poziție** apare x în vectorul dat.+Să se găsească la ce **poziție** apare x în vectorul dat.
  
 === Rezolvare === === Rezolvare ===
-BinarySearch (Cautare Binara), se rezolva cu un algoritm D&I:+BinarySearch (Căutare Binară), se rezolva cu un algoritm D&I:
  
   * **Divide**: împărțim vectorul în doi sub-vectori de dimensiune n/2.   * **Divide**: împărțim vectorul în doi sub-vectori de dimensiune n/2.
Line 214: Line 210:
  
 === Complexitate === === Complexitate ===
-  * **complexitate ​temporala** : $T = O(log (n))$ +  * **complexitate ​temporală** : $T = O(log (n))$ 
-    * se deduce din recurenta ​$T(n)=T(n/​2) + O(1)$   +    * se deduce din recurența ​$T(n)=T(n/​2) + O(1)$   
-  ​* **complexitate ​spatiala** : $S=O(1)$+  * **complexitate ​spațială** : $S=O(1)$
     * nu avem structuri de date complexe auxiliare     * nu avem structuri de date complexe auxiliare
-    * atragem ​atentia ca acest algoritm se poate implementa ​si **recursiv**,​ caz in care complexitatea ​spatiala ​devine $O(log(n))$, ​intrucat salvam ​pe stiva $O(log(n))$ parametri (intregireferinte)+    * atragem ​atenția că acest algoritm se poate implementa ​și **recursiv**,​ caz în care complexitatea ​spațiala ​devine $O(log(n))$, ​întrucât salvăm ​pe stivă ​$O(log(n))$ parametri (întregireferințe)
  
 ==== Turnurile din Hanoi ==== ==== Turnurile din Hanoi ====
-=== Enunt === +=== Enunț ​=== 
-Se considera ​3 tije $S$ (**sursa**),​ $D$ (**destinatie**),​ $aux$ (**auxiliar**) şi n discuri de dimensiuni distincte ($1, 2, ..., n$ - ordinea crescătoare a dimensiunilor) situate inițial toate pe tija $S$ în ordinea $1,2,...,n$ (de la vârf către baza). ​+Se consideră ​3 tije $S$ (**sursa**),​ $D$ (**destinatie**),​ $aux$ (**auxiliar**) şi n discuri de dimensiuni distincte ($1, 2, ..., n$ - ordinea crescătoare a dimensiunilor) situate inițial toate pe tija $S$ în ordinea $1,2,...,n$ (de la vârf către baza). ​
  
 Singura operație care se poate efectua este de a selecta un disc ce se află în vârful unei tije şi plasarea lui în vârful altei tije astfel încât să fie așezat deasupra unui disc de dimensiune mai mare decât a sa.  Singura operație care se poate efectua este de a selecta un disc ce se află în vârful unei tije şi plasarea lui în vârful altei tije astfel încât să fie așezat deasupra unui disc de dimensiune mai mare decât a sa. 
  
-Sa se găsească un algoritm prin care se mută toate discurile de pe tija $S$ pe tija $D$ (problema turnurilor din Hanoi).+Să se găsească un algoritm prin care se mută toate discurile de pe tija $S$ pe tija $D$.(problema turnurilor din Hanoi).
  
-=== Solutie ​===+=== Soluție ​===
 Pentru rezolvarea problemei folosim următoarea strategie [[http://​www.mathcs.org/​java/​programs/​Hanoi/​index.html|[9]]]:​ Pentru rezolvarea problemei folosim următoarea strategie [[http://​www.mathcs.org/​java/​programs/​Hanoi/​index.html|[9]]]:​
  
-  * mutam primele $n-1$ discuri de pe tija S pe tija aux folosindu-ne de tija D. +  * mutăm ​primele $n-1$ discuri de pe tija S pe tija aux folosindu-ne de tija D. 
-  * mutam discul n pe tija D. +  * mutăm ​discul n pe tija D. 
-  * mutam apoi cele $n-1$ discuri de pe tija aux pe tija D folosindu-ne de tija S.+  * mutăm ​apoi cele $n-1$ discuri de pe tija aux pe tija D folosindu-ne de tija S.
  
-Ideea din spate este ca avem mereu o singura ​sursa si o singura destinatie sa atingem un scop. Intotdeauna ​a 3-a tija va fi considerata auxiliara si poate fi folosita ​pentru a atinge scopul propus.+Ideea din spate este că avem mereu o singura ​sursă ​si o singură destinație să atingem un scop. Întotdeauna ​a 3-a tija va fi considerată auxiliară și poate fi folosită ​pentru a atinge scopul propus.
  
 === Algoritm === === Algoritm ===
Line 255: Line 251:
  
 === Complexitate === === Complexitate ===
-  * **complexitate ​temporala** : $T(n) = O(2^n)$ +  * **complexitate ​temporală** : $T(n) = O(2^n)$ 
-    * se deduce din recurenta ​$T(n)=2*T(n - 1) + O(1)$   +    * se deduce din recurența ​$T(n)=2*T(n - 1) + O(1)$   
-  ​* **complexitate ​spatiala** : $S(n) = O(n)$+  * **complexitate ​spațială** : $S(n) = O(n)$
     * la un moment dat, nivelul maxim de recursivitate este n     * la un moment dat, nivelul maxim de recursivitate este n
  
  
 ==== ZParcurgere ==== ==== ZParcurgere ====
-=== Enunt === +=== Enunț ​=== 
-Gigel are o tabla patratica ​de dimensiuni $2^n * 2^n$. Ar vrea sa scrie pe patratelele ​tablei numere naturale cuprinse ​intre $1$ si $2^n * 2^n$ conform unei parcurgeri mai deosebite pe care o numeste ​**Z-parcurgere**. ​+Gigel are o tablă pătratică ​de dimensiuni $2^n * 2^n$. Ar vrea să scrie pe pătrățelele ​tablei numere naturale cuprinse ​între ​$1$ si $2^n * 2^n$ conform unei parcurgeri mai deosebite pe care o numește ​**Z-parcurgere**. ​
  
-O Z-parcurgere ​viziteaza ​recursiv cele patru cadrane ale tablei ​in ordinea: **stanga-sus**, **dreapta-sus**,​ **stanga-jos**, **dreapta-jos**.+O Z-parcurgere ​vizitează ​recursiv cele patru cadrane ale tablei ​în ordinea: **stânga-sus**, **dreapta-sus**,​ **stânga-jos**, **dreapta-jos**.
  
-La un moment dat Gigel ar vrea sa stie ce **numar de ordine** trebuie ​sa scrie conform Z-parcurgerii pe anumite ​patratele ​date prin coordonatele lor $( x, y )$. Gigel incepe umplerea tablei **intotdeauna** din coltul ​din stanga-sus.+La un moment datGigel ar vrea să știe ce **număr ​de ordine** trebuie ​să scrie conform Z-parcurgerii pe anumite ​pătrațele ​date prin coordonatele lor $( x, y )$. Gigel incepe umplerea tablei **întotdeauna** din colțul ​din stânga-sus.
    
 <spoiler Exemplu 1> <spoiler Exemplu 1>
 $n = 1$ si $(x, y) = (2, 2)$ $n = 1$ si $(x, y) = (2, 2)$
  
-Raspuns: $4$+Răspuns: $4$
  
-Explicatie: Matricea ​arata ca in exemplul ​urmator.+Explicație: Matricea ​arată ​ca în exemplul ​următor.
 |1|2| |1|2|
 |3|4| |3|4|
Line 283: Line 279:
 $n = 2$ si $(x, y) = (3, 3)$ $n = 2$ si $(x, y) = (3, 3)$
  
-Raspuns: $13$+Răspuns: $13$
  
-Explicatie: Matricea ​arata ca in exemplul ​urmator.+Explicație: Matricea ​arată ​ca în exemplul ​următor.
 |1|2|5|6| |1|2|5|6|
 |3|4|7|8| |3|4|7|8|
Line 292: Line 288:
 </​spoiler>​ </​spoiler>​
  
-=== Solutie ​=== +=== Soluție ​=== 
-Analizand ​modul in care se **completeaza** tabloul/​matricea din enuntobservam ca la fiecare etapa impartim ​matricea (**problema**) ​in 4 submatrici (**4 subprobleme**). De asemenea, ​sirul de numere pe care dorim sa il punem in matrice se imparte in 4 secvente, fiecare ​corespunzand ​unei submatrici.+Analizând ​modul în care se **completează** tabloul/​matricea din enunțobservăm că la fiecare etapa împărțim ​matricea (**problema**) ​în 4 submatrici (**4 subprobleme**). De asemenea, ​șirul ​de numere pe care dorim să il punem în matrice se împarte în 4 secvente, fiecare ​corespunzând ​unei submatrici.
  
-Observam ​astfel ​ca problema ​suporta ​**descompunerea** ​in **subprobleme disjuncte** ​si cu **structura similara**, ceea ce ne face sa ne gandim ​la o solutie ​cu Divide et Impera.+Observăm ​astfel ​că problema ​suportă ​**descompunerea** ​în **subprobleme disjuncte** ​și cu **structura similara**, ceea ce ne face să ne gândim ​la o soluție ​cu Divide et Impera.
    
  
 === Complexitate === === Complexitate ===
-  * **complexitate ​temporala** : $T = O(n)$+  * **complexitate ​temporală** : $T = O(n)$
     * $\log_{4} (2^n) = \frac{1}{2} \log _{2} (2^n) =  \frac{1}{2} n $  ​     * $\log_{4} (2^n) = \frac{1}{2} \log _{2} (2^n) =  \frac{1}{2} n $  ​
-  ​* **complexitate ​spatiala** : $S=O(n)$ +  * **complexitate ​spatială** : $S=O(n)$ 
-    * stocam ​parametri pentru recursivitate  +    * stocăm ​parametri pentru recursivitate  
-    * solutia se poate implementa si iterativ, caz in care $S = O(1)$; deoarece ​dimensinile spatiului ​de cautare ​sunt $2^n * 2^n$, n este foarte mic ($n <= 15$), de aceea o solutie iterativa nu aduce nici un castig ​**efectiv** ​in aceasta situatie+    * solutia se poate implementa si iterativ, caz in care $S = O(1)$; deoarece ​dimensiunile spațiului ​de căutare ​sunt $2^n * 2^n$, n este foarte mic ($n <= 15$), de aceea o solutie iterativa nu aduce nici un câștig ​**efectiv** ​în această situație.
  
 ===== Concluzii ===== ===== Concluzii =====
  
-Divide et impera este o tehnică folosită pentru a realiza ​solutii ​pentru o anumita ​clasa de probleme: acestea contin **subprobleme disjuncte** ​si cu **structura similara**. În cadrul acestei tehnici se disting trei etape: divide, stăpânește și combină.+Divide et impera este o tehnică folosită pentru a realiza ​soluții ​pentru o anumita ​clasă ​de probleme: acestea contin **subprobleme disjuncte** ​și cu **structură similară**. În cadrul acestei tehnici se disting trei etape: divide, stăpânește și combină.
  
 Mai multe exemple de algoritmi care folosesc tehnica divide et impera puteți găsi la [[http://​www.cs.berkeley.edu/​~vazirani/​algorithms/​chap2.pdf|[11]]]. Mai multe exemple de algoritmi care folosesc tehnica divide et impera puteți găsi la [[http://​www.cs.berkeley.edu/​~vazirani/​algorithms/​chap2.pdf|[11]]].
  
-===== Exercitii ​=====+===== Exerciții ​=====
 <​note>​ <​note>​
-In acest laborator vom folosi scheletul ​de laborator ​din arhiva {{pa:new_pa:skel-lab01.zip}}.+Scheletul ​de laborator ​se găsește pe pagina [[https://​github.com/​acs-pa/​pa-lab/​tree/​main/​skel/​lab01|pa-lab::skel/lab01]].
 </​note>​ </​note>​
  
 === Count occurrences === === Count occurrences ===
-Se da un sir sortat **v** cu **n** elemente. ​Gasiti numarul ​de elemente egale cu **x** din sir.+Se dă un șir sortat **v** cu **n** elemente. ​Găsiți numărul ​de elemente egale cu **x** din șir.
  
 <spoiler Exemplu 1> <spoiler Exemplu 1>
Line 324: Line 320:
 |v|1|2|4|10|10|20| |v|1|2|4|10|10|20|
  
-Raspuns: $2$+Răspuns: $2$
  
-Explicatie: 10 apare de 2 ori in sir.+Explicație: 10 apare de 2 ori in sir.
  
 </​spoiler>​ </​spoiler>​
  
 Task-uri: Task-uri:
-   * Aceasta ​problema ​este deja rezolvata. Pentru a va acomoda cu scheletul, va trebui sa faceti cativa pasi+   * Aceasta ​problemă ​este deja rezolvată. Pentru a vă acomoda cu scheletul, va trebui sa faceți câțiva pași
-     ​* ​Rulati ​comanda $./​check.sh$ si cititi cum se foloseste checker-ul. +     ​* ​Rulați ​comanda $./​check.sh$ si cititi cum se foloseste checker-ul. 
-     ​* ​Rulati ​comanda necesara pentru a rula task-ul 1. Sursa nu implementeaza corect algoritmul si returneaza valori default. Din acest motiv primiti mesajul **WRONG ANSWER**. +     ​* ​Rulați ​comanda necesara pentru a rula task-ul 1. Sursa nu implementeaza corect algoritmul si returneaza valori default. Din acest motiv primiti mesajul **WRONG ANSWER**. 
-     * Copiati ​urmatoarea sursa in folderul ​corespunzatorRulati ​comanda ​anterioaraObservati ​mesajele ​afisate cand ati rezolvat corect un task.+     * Copiati ​următoarea sursă în folderul ​corespunzătorRulați ​comanda ​anterioarăObservați ​mesajele ​afișate când ați rezolvat corect un task.
 <spoiler Solutie C++> <spoiler Solutie C++>
 Sursa **main.cpp** asociata cu task 1 este mai jos. Sursa **main.cpp** asociata cu task 1 este mai jos.
Line 343: Line 339:
 class Task { class Task {
 public: public:
- void solve() { +    ​void solve() { 
- read_input();​ +        read_input();​ 
- print_output(get_result());​ +        print_output(get_result());​ 
- }+    }
  
 private: private:
- void read_input() { +    int n, x
- ifstream fin("​in"​);​ +    ​vector<​int> v;
- fin >> ​n; +
- for (int i = 0, e; i < n; i++) { +
- fin ​>> e; +
- v.push_back(e); +
-+
- fin >> x; +
- fin.close();​ +
- }+
  
- int find_first() { +    void read_input() { 
- int left = 0, right = - 1, mid, res = -1; +        ​ifstream fin("​in"​);​ 
- while (left <= right) { +        fin >> n; 
- mid = (left + right) / 2+        for (int = 0, e; i < n; i++) { 
- if (v[mid] >= x+            fin >> e
- res = mid+            ​v.push_back(e); 
- right = mid - 1; +        
- else { +        fin >> x
- left = mid + 1+        ​fin.close()
- +    }
-+
- return res+
- }+
  
- int find_last() { +    ​int find_first() { 
- int left = 0, right = n - 1, mid, res = -1; +        int left = 0, right = n - 1, mid, res = -1; 
- while (left <= right) { +        while (left <= right) { 
- mid = (left + right) / 2; +            mid = (left + right) / 2; 
- if (v[mid] ​<= x) { +            if (v[mid] ​>= x) { 
- res = mid; +                res = mid; 
- left ​= mid 1; +                ​right ​= mid 1; 
- } else { +            } else { 
- right ​= mid 1; +                ​left ​= mid 1; 
- +            
- +        
- return res; +        return ​(res != -1 && v[res] == x) ? res : -1
- }+    }
  
- int get_result() { +    ​int find_last() { 
- int first find_first(); +        int left 0, right = n - 1, mid, res = -1; 
- int last find_last(); +        while (left <= right{ 
- if (first == -1 || last =-1+            ​mid ​= (left + right/ 2
- return 0+            if (v[mid] <x) { 
- +                res mid; 
- return ​last first + 1; +                left mid + 1
- }+            } else 
 +                right = mid - 1
 +            
 +        } 
 +        ​return ​(res != -1 && v[res] == x) ? res : -1; 
 +    }
  
- void print_output(int result) { +    ​int get_result() { 
- ofstream fout("​out"​); +        int first = find_first(); 
- fout << result+        int last = find_last()
- fout.close(); +        ​if ​(first == -1 || last == -1
- }+            return 0; 
 +        } 
 +        return last - first + 1
 +    }
  
- int n, x+    void print_output(int result) { 
- vector<int> v;+        ofstream fout("​out"​)
 +        ​fout ​<< result; 
 +        fout.close();​ 
 +    }
 }; };
  
 +// [ATENTIE] NU modifica functia main!
 int main() { int main() {
- Task task; +    // * se aloca un obiect ​Task pe heap 
- task.solve(); +    // (se presupune ca e prea mare pentru a fi alocat pe stiva) 
- return 0;+    // * se apeleaza metoda solve() 
 +    // (citire, rezolvare, printare) 
 +    // * se distruge obiectul si se elibereaza memoria 
 +    auto* task = new (std::​nothrow) Task{}// hint: cppreference/​nothrow 
 +    if (!task) { 
 +        std::cerr << "new failed\n";​ 
 +        return -1; 
 +    } 
 +    task->solve(); 
 +    ​delete task; 
 +    ​return 0;
 } }
 </​code>​ </​code>​
Line 468: Line 475:
  }  }
  }  }
- return res;+ return ​(res != -1 && v[res] == x) ? res : -1;
  }  }
  
Line 482: Line 489:
  }  }
  }  }
- return res;+ return ​(res != -1 && v[res] == x) ? res : -1;
  }  }
  
Line 508: Line 515:
 </​spoiler>​ </​spoiler>​
  
-   ​* ​Intelegeti solutia oferita impreuna ​cu asistentul vostru. +   ​* ​Înțelegeți soluția oferită împreună ​cu asistentul vostru. 
-   * Care este complexitatea ​solutiei ​(timp + spatiu)? De ce?+   * Care este complexitatea ​soluției ​(timp + spațiu)? De ce?
  
 === SQRT === === SQRT ===
-Se da un numar real **n**. ​Scrieti ​un algoritm de complexitate **O(log n)** care sa calculeze $sqrt(n)$ cu o precizie de $0.001$. ​+Se dă un număr ​real **n**. ​Scrieți ​un algoritm de complexitate **O(log n)** care să calculeze $sqrt(n)$ cu o precizie de $0.001$. ​
  
 <spoiler Exemplu 1> <spoiler Exemplu 1>
 $ n = 0.25 $ $ n = 0.25 $
  
-Raspuns: orice valoare intre $0.499$ si $0.501$ (inclusiv)+Răspuns: orice valoare intre $0.499$ si $0.501$ (inclusiv)
 </​spoiler>​ </​spoiler>​
  
 <​note>​ <​note>​
-Pentru a putea trece testele, trebuie sa afisati ​rezultatul cu **cel putin ** 4 zecimale.+Pentru a putea trece testele, trebuie sa afișați ​rezultatul cu **cel puțin ​** 4 zecimale.
  
 </​note>​ </​note>​
  
 === ZParcurgere === === ZParcurgere ===
-Rezolvati ​problema ZParcurgere folosind scheletul pus la dispozitieEnuntul si explicatiile ​le gasiti in partea de seminar.+Rezolvați ​problema ZParcurgere folosind scheletul pus la dispozițieEnunțul și explicațiile ​le găsiți în partea de seminar.
  
-=== Exponentiere logaritmica ​=== +=== Exponențiere logaritmică ​=== 
-Se dau doua numere naturale **base** ​si  ​**exponent**. ​Scrieti ​un algoritm de complexitate $O(log (exponent))$ care sa calculeze ${base} ^ {exponent} \ \% \  MOD $. +Se dau două numere naturale **base** ​și  ​**exponent**. ​Scrieți ​un algoritm de complexitate $O(log (exponent))$ care să calculeze ${base} ^ {exponent} \ \% \  MOD $. 
  
 <​note>​ <​note>​
-Intrucat ​expresia $ {base} ^ {exponent} $ este foarte mare, dorim sa aflam doar **restul** ​impartirii ​lui la un numar **MOD**.+Întrucât ​expresia $ {base} ^ {exponent} $ este foarte mare, dorim să aflăm ​doar **restul** ​împărțirii ​lui la un număr ​**MOD**.
  
  
-Proprietati ​matematice necesare:+Proprietăți ​matematice necesare:
     * $(a + b)   \ \% \   MOD = ((a   \ \% \   MOD) + (b   \ \% \   ​MOD)) ​  \ \% \   MOD $      * $(a + b)   \ \% \   MOD = ((a   \ \% \   MOD) + (b   \ \% \   ​MOD)) ​  \ \% \   MOD $ 
     * $(a \ * b)   \ \% \   MOD = ((a   \ \% \   MOD) \ * (b   \ \% \   ​MOD)) ​  \ \% \   MOD $      * $(a \ * b)   \ \% \   MOD = ((a   \ \% \   MOD) \ * (b   \ \% \   ​MOD)) ​  \ \% \   MOD $ 
   ​   ​
  
-Atentie ​la inmultire! Rezultatul **temporar** poate provoca un overflow. +Atenție ​la înmulțire! Rezultatul **temporar** poate provoca un overflow. 
-Solutii:+ 
 +Soluții:
   * **C++**: $a * b$ => $1LL * a * b$   * **C++**: $a * b$ => $1LL * a * b$
   * **Java**: $a * b$ => $1L * a * b$   * **Java**: $a * b$ => $1L * a * b$
Line 549: Line 557:
 $ base  = 2 $,  $ exponent = 10$, $MOD = 5$ $ base  = 2 $,  $ exponent = 10$, $MOD = 5$
  
-Raspuns: $4$+Răspuns: $4$
  
 Explicatie: $2^{10} \ \% \ 5 = 4$ Explicatie: $2^{10} \ \% \ 5 = 4$
Line 565: Line 573:
  
 <​note>​ <​note>​
-Aceasta problema nu are schelet.+Aceasta problema nu are schelet, dar poate fi testată pe infoarena, la problema [[https://​www.infoarena.ro/​problema/​inv | Inv]].
 </​note>​ </​note>​
  
 </​spoiler>​ </​spoiler>​
  
 +<spoiler ClassicTask>​
 +Testați soluția voastră de la **Exponentiere logaritmica** pe infoarena, la problema [[https://​infoarena.ro/​problema/​classictask | ClassicTask ]] (trebuie să modificați numele fișierelor).
 +
 +Identificați problema și modificați sursa astfel încât să luați punctaj maxim.
 +</​spoiler> ​
 ==== Extra ==== ==== Extra ====
 <spoiler Statistici de ordine> <spoiler Statistici de ordine>
Line 596: Line 609:
  
 <spoiler Fractal> <spoiler Fractal>
-Puteti ​rezolva ​aceasta problema ​pe [[https://​infoarena.ro/​problema/​fractal| infoarena]].+Puteți ​rezolva ​această problemă ​pe [[https://​infoarena.ro/​problema/​fractal| infoarena]].
 </​spoiler>​ </​spoiler>​
  
- +<​spoiler ​Hanoi
-<​spoiler ​SSM+Puteți ​rezolva ​această problemă pe [[https://www.infoarena.ro/problema/hanoiinfoarena]].
-Puteti ​rezolva ​aceasta problema de [[https://ocw.cs.pub.ro/courses/pa/​laboratoare/​laborator-03#​ssm +
-aici]]. +
- +
-<​note>​ +
-Pentru problema SSM vom studia o solutie potrivita in lab03. Puteti sa incercati sa o rezolvati cu Divide et Impera pentru a exersa cele invatate astazi. +
-</​note>​+
 </​spoiler>​ </​spoiler>​
  
Line 612: Line 619:
 Dându-se N numere întregi sub forma unei secvenţe de numere strict crescătoare,​ care se continuă cu o secvenţă de întregi strict descrescătoare,​ se doreşte determinarea punctului din întregul şir înaintea căruia toate elementele sunt strict crescătoare,​ şi dupa care, toate elementele sunt strict descrescătoare. Considerăm evident faptul că acest punct nu există dacă cele N numere sunt dispuse într-un şir fie doar strict crescător, fie doar strict descrescător. Dându-se N numere întregi sub forma unei secvenţe de numere strict crescătoare,​ care se continuă cu o secvenţă de întregi strict descrescătoare,​ se doreşte determinarea punctului din întregul şir înaintea căruia toate elementele sunt strict crescătoare,​ şi dupa care, toate elementele sunt strict descrescătoare. Considerăm evident faptul că acest punct nu există dacă cele N numere sunt dispuse într-un şir fie doar strict crescător, fie doar strict descrescător.
  
 +</​spoiler>​
 +
 +<spoiler K closest points to origin>
 +Puteți rezolva această problemă pe [[https://​leetcode.com/​problems/​k-closest-points-to-origin/​ | leetcode]]
 +</​spoiler>​
 +
 +<spoiler Merge k Sorted Lists>
 +Puteți rezolva această problemă pe [[https://​leetcode.com/​problems/​merge-k-sorted-lists/​ | leetcode]]
 </​spoiler>​ </​spoiler>​
  
  
  
 +===== Referințe =====
  
 +[0] Chapter **Divide-and-Conquer**,​ "​Introduction to Algorithms",​ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein
  
  
pa/laboratoare/laborator-01.1519992940.txt.gz · Last modified: 2018/03/02 14:15 by traian.rebedea
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