Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:2023:hw1 [2023/03/17 07:33]
pdmatei
pp:2023:hw1 [2023/03/19 12:06] (current)
alexandra.udrescu01
Line 25: Line 25:
   * util: Util.scala, Pixel.scala   * util: Util.scala, Pixel.scala
   * Solution.scala   * Solution.scala
 +  * ID.txt - acest fisier va contine o singura linie, formata din ID-ul unic al fiecarui student
 Numele arhivelor trebuie sa fie de forma **<​Nume>​_<​Prenume>​_<​Grupa>​_T1.zip** (daca aveti mai multe prenume sau nume, le puteti separa prin '​-'​) Numele arhivelor trebuie sa fie de forma **<​Nume>​_<​Prenume>​_<​Grupa>​_T1.zip** (daca aveti mai multe prenume sau nume, le puteti separa prin '​-'​)
  
Line 54: Line 55:
 <note tip>​Pentru a vedea ușor imaginea generată de voi, puteți folosi [[https://​0xc0de.fr/​webppm/​]] </​note>​ <note tip>​Pentru a vedea ușor imaginea generată de voi, puteți folosi [[https://​0xc0de.fr/​webppm/​]] </​note>​
  
-Pentru a reprezenta imaginea, se va folosi tipul Image definit mai jos:+**Pentru a reprezenta imaginea, se va folosi tipul Image definit mai jos:**
 <code scala> <code scala>
 type Image = List[List[Pixel]] type Image = List[List[Pixel]]
 type GrayscaleImage = List[List[Double]] type GrayscaleImage = List[List[Double]]
 </​code>​ </​code>​
-unde Pixel este o clasă in care se rețin valorile celor 3 culori (roșu, verde, albastru) sub forma de Integer. Clasa Pixel ce se găsește in folderul util din schelet.+**unde** ''​Pixel''​ **este o clasă in care se rețin valorile celor 3 culori (roșu, verde, albastru) sub forma de Integer. Clasa Pixel se găsește in folderul util din schelet.**
  
 ====1. Alăturare de imagini pe verticală (10p)==== ====1. Alăturare de imagini pe verticală (10p)====
Line 182: Line 183:
 <hidden imagine blurred> {{ :​pp:​2023:​hw1_blurred.jpg?​300 |}} </​hidden>​ <hidden imagine blurred> {{ :​pp:​2023:​hw1_blurred.jpg?​300 |}} </​hidden>​
  
-3. Se vor aplica apoi kernelurile Gx și Gy pentru a genera Mx și My+3. Se vor aplica apoi, prin convolutie, ​kernelurile Gx și Gy pentru a genera Mx și My
 <hidden Gx><​code scala> <hidden Gx><​code scala>
 val Gx : GrayscaleImage = List( val Gx : GrayscaleImage = List(
Line 228: Line 229:
 def edgeDetection(image:​ Image, threshold : Double): Image = ??? def edgeDetection(image:​ Image, threshold : Double): Image = ???
 </​code>​ </​code>​
 +
 +<note tip>​**Hint:​** la acest exercitiu este indicat sa folositi functia ''​getNeighbors''​ din fisierul Util.scala</​note>​
  
 ====5. Triunghi pascal cu resturi - colorare (40p)==== ====5. Triunghi pascal cu resturi - colorare (40p)====
  
-Se calculează ​[[https://​en.wikipedia.org/​wiki/​Pascal%27s_triangle| Triunghiul lui Pascal]]. Acesta ​este o reprezentare 2-dimensionalaa unor valori care apar in foarte multe aplicatii de combinatorica dar si algebra. Triunghiul lui Pascal cu 5 linii este ilustrat mai jos:+[[https://​en.wikipedia.org/​wiki/​Pascal%27s_triangle| Triunghiul lui Pascal]] este o reprezentare 2-dimensionala a unor valori care apar in foarte multe aplicatii de combinatorica dar si algebra. Triunghiul lui Pascal cu 5 linii este ilustrat mai jos:
 <​code>​ <​code>​
        1        1
Line 242: Line 245:
  
   * Cea mai simpla modalitate de a descrie o linie ''​l''​ din triunghiul lui Pascal este urmatoarea: primul element $math[l_0] (si ultimul) este intotdeauna 1;    * Cea mai simpla modalitate de a descrie o linie ''​l''​ din triunghiul lui Pascal este urmatoarea: primul element $math[l_0] (si ultimul) este intotdeauna 1; 
-  * Pentru restul elementelor din triunghi, se foloseste recurenta $math[i > 0], $math[l_i = lp_{i-1} + lp_{i}]. ​+  * Pentru restul elementelor din triunghi, se foloseste recurenta $math[i > 0], $math[l_i = lp_{i-1} + lp_{i}], unde $math[l] este linia curenta, si $math[lp] este linia precedenta.
   * Cu puțină atentie, observam ca o valoare de pe linia ''​n''​ si coloana ''​k''​ este $math[C_n^k] (combinari de $math[n] luate cate $math[k]), si atunci relatia de mai sus devine: $ C_n^k = C_{n-1}^k + C_{n-1}^{k-1} $. Preferam in general sa implementam calculul $math[C_n^k] folosind aceasta relatie de recurenta, pentru ca este mai eficientă din punct de vedere al complexității temporale față de formula cu factoriale.   * Cu puțină atentie, observam ca o valoare de pe linia ''​n''​ si coloana ''​k''​ este $math[C_n^k] (combinari de $math[n] luate cate $math[k]), si atunci relatia de mai sus devine: $ C_n^k = C_{n-1}^k + C_{n-1}^{k-1} $. Preferam in general sa implementam calculul $math[C_n^k] folosind aceasta relatie de recurenta, pentru ca este mai eficientă din punct de vedere al complexității temporale față de formula cu factoriale.
   * Asadar, triunghiul lui Pascal este format pe fiecare linie din $ C_n^0 C_n^1 ... C_n^n $ unde ''​n''​ este numărul liniei ( $ n \ge 0 $).    * Asadar, triunghiul lui Pascal este format pe fiecare linie din $ C_n^0 C_n^1 ... C_n^n $ unde ''​n''​ este numărul liniei ( $ n \ge 0 $). 
Line 258: Line 261:
 </​code>​ </​code>​
 </​hidden>​ </​hidden>​
-  * Prin triunghiul lui Pascal ​se pot genera diferite șabloane (patterns)a căror reprezentare grafică este influențată de modul de colorare al matricii rezultate. Vom alege să folosim ''​M''​ culori. +  * In cele ce urmeaza, nu vom construi ​triunghiul lui Pascal ​cu valori absoluteca mai sus, ci in locul fiecarei valori $math[l_i] vom construi valoarea $math[l_i \% M]. Deoarece numerele apărute in recurența mentionata anterior cresc foarte rapid, ar putea aparea un overflow la adunare, ducand la rezultate eronate. ​Asadar, pentru ​a obtine valoarea $math[l_i % M]vom folosi tot relatia ​de recurenta anterioara: $ Cmodulo_n^k = (Cmodulo_{n-1}^k + Cmodulo_{n-1}^{k-1}) \% M $. Observati ca $math[Cmodulo_n^C_n^k \% (C_{n-1}^k + C_{n-1}^{k-1}\% M = (C_{n-1}^k \% M + C_{n-1}^{k-1} \% M\% M = (Cmodulo_{n-1}^k + Cmodulo_{n-1}^{k-1}\% M] Formula recursivă ne ajută mai mult deoarece putem să aplicăm modulo la fiecare pas. 
-  * Deoarece numerele apărute in recurența mentionata anterior cresc foarte rapid, ar putea aparea un overflow la adunare, ducand la rezultate eronate. ​Din acest motiv, pentru ​un număr de culori ​alesse calculează resturile (modulo) acestor numerelor ​de pe fiecare linie la împărțirea cu M. Formula recursivă ne ajută mai mult deoarece putem să aplicăm modulo la fiecare pas. Așadar nu contează de câte ori și unde aplicăm % M. Vom folosi formula finală: $ C_n^k = (C_{n-1}^k + C_{n-1}^{k-1}) \% M $ la fiecare pas. +
-  * Sugestia de rezolvare ar fi generarea linie cu linie a triunghiului Pascal începând de la C_0^1 $ pe prima linie. Aceasta este o abordare de **programare dinamică**. +
-  * Fiecare numar ''​i''​ din triunghiul lui Pascal prezent in matricea generata va avea asociată o culoare conform functiei de mai jos( $ \le 5 $ ). Deasupra diagonalei ​(unde sunt zero-uri) va rămâne negru și nu se va aplica funcția! +
-<code scala> +
-def pickColor(i:​ Integer) : Pixel = { +
-  if (i == 0) Pixel(255, 0, 0) +
-  else if (i == 1) Pixel(0, 0, 255) +
-  else if (i == 2) Pixel(0, 255, 0) +
-  else if (i == 3) Pixel(255, 255, 255) +
-  else Pixel(0, 0, 0) +
-+
-</​code>​+
 <hidden Triunghiul lui Pascal size = 5 ; M = 4> <hidden Triunghiul lui Pascal size = 5 ; M = 4>
 <​code>​ <​code>​
Line 280: Line 271:
 </​code>​ </​code>​
 </​hidden>​ </​hidden>​
 +  * Prin triunghiul lui Pascal **cu valori modulo** se pot genera diferite șabloane (patterns), ale căror reprezentare grafică este influențată de modul de colorare al matricii rezultate. Vom folosi ''​M''​ pentru a stabili numarul de culori folosite in colorare. O culoare este, de fapt, un Pixel. **Colorarea** inseamna ca fiecarei valori din triunghiul **modulo** al lui Pascal i se asociaza un Pixel cu anumite valori (rosu, verde, albastru), valori ce urmeaza regula prezentata in functia ''​pickColor''​. Tot ce este deasupra diagonalei principale va rămâne negru și nu se va aplica funcția!
 +<code scala>
 +def pickColor(i:​ Integer) : Pixel = {
 +  if (i == 0) Pixel(255, 0, 0)
 +  else if (i == 1) Pixel(0, 0, 255)
 +  else if (i == 2) Pixel(0, 255, 0)
 +  else if (i == 3) Pixel(255, 255, 255)
 +  else Pixel(0, 0, 0)
 +}
 +</​code>​
  
 +<hidden Triunghiul lui Pascal size = 5 ; M = 4 DUPA COLORARE>​{{:​pp:​2023:​size5m4.png?​250|}}</​hidden>​
   * Se va completa pentru acest task functia:   * Se va completa pentru acest task functia:
 <code scala> <code scala>
-def moduloPascal(m: Integer, ​funct: Integer => Pixel, size: Integer): Image = ???+def moduloPascal(M: Integer, ​// nr. de culori  
 +                 ​pickColor: Integer => Pixel, ​// functia de colorare 
 +                 size: Integer ​// dimensiunea triunghiului (nr de linii)  
 +                 ): Image = ???
 </​code>​ </​code>​
 +  * Sugestia de rezolvare ar fi generarea linie cu linie a triunghiului Pascal începând de la $ C_0^0 = 1 $ pe prima linie. Aceasta este o abordare de **programare dinamică**.
 <note warning>​Nu folosiți formula combinăriilor cu factorial pentru acest exercițiu!</​note>​ <note warning>​Nu folosiți formula combinăriilor cu factorial pentru acest exercițiu!</​note>​
 <note important>​Triunghiul lui Pascal fiind infinit, va avea o marime limitata la $ size^2 $ (size > 2).</​note>​ <note important>​Triunghiul lui Pascal fiind infinit, va avea o marime limitata la $ size^2 $ (size > 2).</​note>​