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:hw2_v2 [2023/04/09 07:10]
alexandra.udrescu01
pp:2023:hw2_v2 [2023/04/11 00:04] (current)
sorin.mateescu [2. Functii de procesare a datelor (50p)]
Line 3: Line 3:
 <note important>​ <note important>​
  
-**DEADLINE ​TODO **+**DEADLINE ​28 aprilie 2023**
  
   * Temele trebuie submise pe curs.upb.ro,​ in assignment-ul numit ''​Tema 2''​.   * Temele trebuie submise pe curs.upb.ro,​ in assignment-ul numit ''​Tema 2''​.
Line 15: Line 15:
   * **var** (**val** este ok!)   * **var** (**val** este ok!)
 </​note>​ </​note>​
-<​note>​Scheletul se poate găsi la: TODO</​note>​+<​note>​Scheletul se poate găsi la: {{:​pp:​2023:​tema2_2023_pp-skel.zip|}}</​note>​
 <​note>​ <​note>​
-Validatorul de arhive se poate găsi la: TODO+Validatorul de arhive se poate găsi la: {{:​pp:​2023:​archive_validator_hw2.zip|}}
 \\ \\
 Formatul arhivelor este: Formatul arhivelor este:
-  * TODO+  * util/​Util.scala 
 +  * Table.scala 
 +  * TestTables.scala
   * ID.txt - acest fisier va contine o singura linie, formata din ID-ul unic al fiecarui student   * 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>​_T2.zip** (daca aveti mai multe prenume sau nume, le puteti separa prin '​-'​) Numele arhivelor trebuie sa fie de forma **<​Nume>​_<​Prenume>​_<​Grupa>​_T2.zip** (daca aveti mai multe prenume sau nume, le puteti separa prin '​-'​)
Line 27: Line 29:
  
 ====Scopul temei==== ====Scopul temei====
 +
 +/*
 Scala este un limbaj de programare care a fost dezvoltat initial pentru a fi utilizat in proiectele de mare scalabilitate si in special pentru a procesa date in big data. Acesta are o serie de caracteristici care il fac foarte util pentru a lucra cu big data. Scala este un limbaj de programare care a fost dezvoltat initial pentru a fi utilizat in proiectele de mare scalabilitate si in special pentru a procesa date in big data. Acesta are o serie de caracteristici care il fac foarte util pentru a lucra cu big data.
   * Performanta:​ Scala este un limbaj de programare puternic si rapid, care poate procesa un volum mare de date intr-un timp scurt. Acest lucru il face foarte util in proiectele de big data care necesita performanta ridicata.   * Performanta:​ Scala este un limbaj de programare puternic si rapid, care poate procesa un volum mare de date intr-un timp scurt. Acest lucru il face foarte util in proiectele de big data care necesita performanta ridicata.
Line 33: Line 37:
   * Functii pure: Scala pune accentul pe functiile pure, care nu au efecte secundare si nu modifica starea sistemului. Aceste functii sunt utile in proiectele de big data, deoarece putem fi siguri ca nu vom modifica accidental datele in mod neasteptat.   * Functii pure: Scala pune accentul pe functiile pure, care nu au efecte secundare si nu modifica starea sistemului. Aceste functii sunt utile in proiectele de big data, deoarece putem fi siguri ca nu vom modifica accidental datele in mod neasteptat.
  
-Tocmai de accea, o modalitate de a aplica cunostiintele de programare functionala dobandite pana acum este aceea de a manipula date tabelare. Cerintele temei va vor ghida pentru a implementa operatii uzuale pe tabele, folosind tipuri de date definite de voi pentru a facilita implementarea.+Tocmai de accea, o modalitate de a aplica cunostiintele de programare functionala dobandite pana acum este aceea de a manipula date tabelare. ​ 
 +*/ 
 + 
 +Cerintele temei va vor ghida pentru a implementa operatii uzuale pe tabele, folosind tipuri de date definite de voi pentru a facilita implementarea.
  
 In final, veti obtine un Query Language ce ofera posibilitatea de a aplica operatii complexe si de a manipula datele din tabele intr-un mod flexibil si usor de extins cu noi functionalitati. In final, veti obtine un Query Language ce ofera posibilitatea de a aplica operatii complexe si de a manipula datele din tabele intr-un mod flexibil si usor de extins cu noi functionalitati.
  
-**TODO dezvolta in mai multe cuvinte** 
  
-==== Conventii ​==== +==== Tabele ​==== 
-Pentru reprezentarea tabelelor din Query Languagese vor folosi ​urmatoarele conventii+ 
-  * numele coloanelor ​este reprezentat sub forma de lista +Un tabel este in esenta o matrice ce contine elemente de tip ''​String''​alaturi de cate un **nume** asociat fiecarei coloane, necesar pentru a descrie cu usurinta operatii peste acestea. In aceasta tema, vom folosi ​doua reprezentari pentru o linie a unei matrici, fiecare potrivita in contexte diferite
-  * fiecare linie a tabelului e reprezentata ca o mapare intre numele colanei si valoarea ​corespunzatoare+  * ''​Line''​ - este pur si simplu o lista cu valorile liniei corespunzatoare. 
 +  * ''​Row''​ - este un Map in care asociaza numelui coloanei ​valoarea ​de pe linia respectiva. 
 <code scala> <code scala>
 // a row contains the column name and the value // a row contains the column name and the value
Line 48: Line 56:
 // a line is just a row without column names // a line is just a row without column names
 type Line = List[String] type Line = List[String]
- 
 </​code>​ </​code>​
  
-====1. ​Parsarea ​datelor==== +====1. ​Tipul de date Table si parsarea ​datelor ​(10p) ==== 
-Pentru inceput, trebuie sa ne definim o clasa prin care sa modelam ce este un tabel.+ 
 +Pentru inceput, trebuie sa definim o clasa prin care sa modelam ce este un tabel.
  
-Vom implementa clasa ''​Table'' ​ce retine numele coloanelor si informatia din tabel.+Vom implementa clasa ''​Table'' ​in acest sens:
 <code scala> <code scala>
-case class Table (column_names:​ Line, tabular: List[List[String]]) { +class Table (column_names:​ Line, tabular: List[List[String]]) { 
     ???     ???
 } }
Line 63: Line 71:
 Pentru a putea rula checkerul, este nevoie sa putem parsa input si output. Prin urmare, avem nevoie de o functie de citire si una de afisare a unui tabel. Pentru a putea rula checkerul, este nevoie sa putem parsa input si output. Prin urmare, avem nevoie de o functie de citire si una de afisare a unui tabel.
  
-**1.1.** Suprascrieti metoda ''​toString''​ a unui tabel, astfel incat sa puteti reprezenta un tabel in forma csv.+**1.1. ​(5p)** Suprascrieti metoda ''​toString''​ a unui tabel, astfel incat sa puteti reprezenta un tabel in forma csv.
 Liniile vor fi separate prin ''​\n'',​ iar coloanele vor fi delimitate prin '',''​. Liniile vor fi separate prin ''​\n'',​ iar coloanele vor fi delimitate prin '',''​.
  
-**1.2.** Definiti functia ''​apply''​ intr-un companion object al clasei ''​Table''​. Functia trebuie sa parseze un sir de caractere si sa returneze un tabel, daca acest lucru este posibil.+**1.2. ​(5p)** Definiti functia ''​apply''​ intr-un companion object al clasei ''​Table''​. Functia trebuie sa parseze un sir de caractere si sa returneze un tabel.
 <code scala> <code scala>
 def apply(s: String): Table = ??? def apply(s: String): Table = ???
 </​code>​ </​code>​
  
-====2. Functii de procesare a datelor====+====2. Functii de procesare a datelor ​(50p)====
  
-In continuare, vom implementa operatii pe tabele.+In continuare, vom implementa operatii pe tabele, ca **membri** ai clasei ''​Table''​.
  
-**2.1.** Implementati functia ''​select''​ care selecteaza valorile din tabel asociate unor coloane date ca input. Daca operatia ​nu este posibila/​permisase va marca aces lucru folosind ​''​None''​.+**2.1. ​(5p)** Implementati functia ''​select''​ care selecteaza valorile din tabel asociate unor coloane date ca input. Daca operatia ​face referire la coloane inexistenteea va intoarce ​''​None''​.
 <code scala> <code scala>
 def select(columns:​ Line): Option[Table] = ??? def select(columns:​ Line): Option[Table] = ???
 </​code>​ </​code>​
  
-**2.2.** Implementati functia ''​filter''​ care aplica un filtru pe liniile din tabel, fiind pastrate doar acele linii care verifica conditia. ​(Hint: pentru a intelege cine este Filtervezi sectiunea 3)+**2.2. ​(20p)** Implementati functia ''​filter''​ care aplica un filtru pe liniile din tabel, fiind pastrate doar acele linii care verifica conditia. ​Daca conditia de filtrare face referiri la coloane inexistenteoperatia va intoarce ''​None''​.
 <code scala> <code scala>
 def filter(cond:​ FilterCond):​ Option[Table] = ??? def filter(cond:​ FilterCond):​ Option[Table] = ???
 </​code>​ </​code>​
  
-Pentru acest exercitiu, este nevoie sa implementam si filtrele ce se aplica pe o linie din tabel. ​Astfelexista+Pentru acest exercitiu, este nevoie sa implementam si filtrele ce se aplica pe o linie din tabel. ​Definim un filtru recursivastfel
-  * filtre logice --aplica functiile logice AND si OR intre 2 filtre +<code>  
-  * filtre asociate unei coloane --decid pastrarea/eliminarea unei linii pe baza unui predicat ce primeste numele unei coloane+<filter::= <​filter>​ && <​filter>​ | <​filter>​ || <​filter>​ | (<​column_name>​ <​predicate>​) 
 +</code> 
 + 
 +Unde ''<​column_name>''​ este un nume de coloana, iar <​predicate>​ este un predicat ce poate sau nu sa fie satisfacut de valoarea de la coloana respectiva. 
 <code scala> <code scala>
 trait FilterCond { trait FilterCond {
-  def &&​(other:​ FilterCond):​ FilterCond = And(this,​other) +  ​// these are useful for the intuitive infix notation 
-  def ||(other: FilterCond):​ FilterCond = Or(this,​other)+  // e.g. the following expression is a filter condition:​ 
 +  // Field("​PL",​ x=>true) && Field("​PL",​ x=> false) 
 +  ​def &&​(other:​ FilterCond):​ FilterCond = ??? 
 +  def ||(other: FilterCond):​ FilterCond = ??? 
 +  ​
   // fails if the column name is not present in the row   // fails if the column name is not present in the row
   def eval(r: Row): Option[Boolean]   def eval(r: Row): Option[Boolean]
 +  ​
 } }
  
Line 109: Line 126:
 </​code>​ </​code>​
  
-**2.3** Implementati functia ''​newCol''​ ce adauga o noua coloana la finalul unui tabel, fiecare intrare in acea coloana asociata unei linii fiind completata cu o valoare default.+**2.3. (5p)** Implementati functia ''​newCol''​ ce adauga o noua coloana la finalul unui tabel, fiecare intrare in acea coloana asociata unei linii fiind completata cu o valoare default.
 <code scala> <code scala>
 def newCol(name:​ String, defaultVal: String): Table = ??? def newCol(name:​ String, defaultVal: String): Table = ???
 </​code>​ </​code>​
  
-**2.4.** Implementati functia ''​merge''​ care uneste 2 tabele. Identificarea liniilor ce trebuie combinate se va face folosing coloana comuna ''​key''​. Daca exista suprapuneri intre valori, se vor pastra amandoua sub forma unui singur sir de caractere (cele doua intrari vor fi separate prin ''​,''​),​ iar acolo unde nu exista corespondent in unul dintre tabele, coloanele ramase necompletate vor fi umplute cu un sir de caractere gol. Daca coloana ''​key''​ nu exista in vreunul din tabele, se va intoarce None.+**2.4. ​(20p)** Implementati functia ''​merge''​ care uneste 2 tabele. Identificarea liniilor ce trebuie combinate se va face folosing coloana comuna ''​key''​. Daca exista suprapuneri intre valorile asociate unei chei in cele doua tabele, se vor pastra amandoua ​valorile (daca sunt diferite) ​sub forma unui singur sir de caractere (cele doua intrari vor fi separate prin ''​;''​),​ iar acolo unde nu exista corespondent in unul dintre tabele, coloanele ramase necompletate vor fi umplute cu un sir de caractere gol. Daca coloana ''​key''​ nu exista in vreunul din tabele, se va intoarce ​''​None''​.
 <code scala> <code scala>
 def merge(key: String, other: Table): Option[Table] = ??? def merge(key: String, other: Table): Option[Table] = ???
 </​code>​ </​code>​
 +
 <hidden Exemplu> <hidden Exemplu>
 <​code>​ <​code>​
Line 132: Line 150:
  
 MERGE intre TABEL 1 si TABEL 2 cu cheia PL: MERGE intre TABEL 1 si TABEL 2 cu cheia PL:
-PL      Functional OO   Description +PL      Functional ​Description ​OO 
-Haskell yes        "" ​  nice +Haskell yes        ​nice ​       ""​ 
-Scala   ​yes ​       yes  cool +Scala   ​yes ​       ​cool ​       yes 
-Python ​ yes        ​yes  ​good,whoa+Python ​ yes        good;whoa   yes
 </​code>​ </​code>​
 </​hidden>​ </​hidden>​
  
-====3. Query Language ====+====3. Query Language ​(40p)====
  
 Obiectivul acestui task este acela de a: Obiectivul acestui task este acela de a:
Line 147: Line 165:
     * debug, testare     * debug, testare
  
-Veti implementa un Query Language ce reprezinta un API pentru o varietate de transformari de tabele, deja implementate anerior ca functii. Un ''​Query''​ este o secventa/ combinatie de astfel de transformari.+**3.0. (25p)** ​Veti implementa un Query Language ce reprezinta un API pentru o varietate de transformari de tabele, deja implementate anerior ca functii. Un ''​Query''​ este o secventa/ combinatie de astfel de transformari. 
 + 
 +Query-urile sunt descrise recursiv astfel: 
 +<​code>​ 
 +<​query>​ ::=  <​table> ​                              // query atomic - reprezinta tabelul initial pe care se va realiza query-ul. ​   
 +             | Select <​column_list>​ <​query> ​       //​selecteaza o lista de coloane dintr-un tabel dat, 
 +                                                   //​esueaza daca se doreste o coloana ce nu se gaseste in tabel 
 +             | NewCol <​column_name>​ <​query> ​       //creeaza o noua coloana cu nume dat intr-un tabel, completand coloana cu o valoare default 
 +                                                   //​operatia e posibila doar daca cheia se gaseste in ambele tabele 
 +             | Merge <​column_name>​ <​query>​ <​query>​ //combina 2 tabele pe baza unei chei comune 
 +                                                   //​operatia e posibila doar daca cheia se gaseste in ambele tabele 
 +             | Filter <​filter_cond>​ <​query> ​       //aplica un filtru pe liniile tabelei 
 + 
 +</​code>​
  
-Query-uri posibile: +Spre exemplu, pentru a evalua query-ul: ''​Select "​PL"​ <Q>''​, se va evalua intai query-ul ​''​<Q>'' ​apoi se va efectua operatia //Select// pe rezultatul intors ​de ''​Q''​. 
-  * ''​Value''​ +Scheletul de implementare pentru Query-uri se gaseste ​mai jos:
-    * reprezentarea de baza a unui tabel sub forma de Query +
-  * ''​Select''​ +
-    * selecteaza o lista de coloane dintr-un tabel dat +
-    * esueaza daca se doreste o coloana ce nu se gaseste in tabel +
-  * ''​NewCol''​ +
-    * creeaza o noua coloana cu nume dat intr-un tabel, completand coloana cu o valoare default +
-  * ''​Merge''​ +
-    * combina 2 tabele pe baza unei chei comune +
-    * operatia e posibila doar daca cheia se gaseste ​in ambele tabele +
-  * ''​FIlter''​ +
-    * aplica un filtru pe liniile tabelei+
  
 <code scala> <code scala>
Line 191: Line 211:
 In finalul acestei teme, vom scrie propriul nostru Query, folosind tabelele Functional, Object-Oriented si Imperative, ce contin doar 3 coloane: "​Language",​ "​Original purpose",​ "Other paradigms"​. In finalul acestei teme, vom scrie propriul nostru Query, folosind tabelele Functional, Object-Oriented si Imperative, ce contin doar 3 coloane: "​Language",​ "​Original purpose",​ "Other paradigms"​.
  
-**3.1.** Creati tabelul ''​TestTables.programmingLanguages1''​ combinand functiile ''​newCol''​ si ''​merge'':​+**3.1. ​(5p)** Creati tabelul ''​TestTables.programmingLanguages1''​ combinand functiile ''​newCol''​ si ''​merge'':​
   * creati o noua colana in fiecare tabel ce contine tipul limbajului, avand acelasi nume ca tabela si valoare default "​Yes"​   * creati o noua colana in fiecare tabel ce contine tipul limbajului, avand acelasi nume ca tabela si valoare default "​Yes"​
   * aplicati merge intre noile tabele dupa numele limbajelor de programare   * aplicati merge intre noile tabele dupa numele limbajelor de programare
  
-**3.2** Eliminati limbajele al caror scop original este "​Application"​ si sunt "​concurrent"​. Rezultatul se va numi ''​TestTables.programmingLanguages2''​.+**3.2. (5p)** Eliminati limbajele al caror scop original este "​Application"​ si sunt "​concurrent"​. Rezultatul se va numi ''​TestTables.programmingLanguages2''​.
  
-**3.3** Selectati doar coloanele "​Language",​ "​Object-Oriented" ​and "​Functional"​ din tabelul obtinut anterior. Rezultatul se va numi ''​TestTables.programmingLanguages3''​.+**3.3. (5p)** Selectati doar coloanele "​Language",​ "​Object-Oriented" ​si "​Functional"​ din tabelul obtinut anterior. Rezultatul se va numi ''​TestTables.programmingLanguages3''​.