ИЕП/К2 2022 — разлика између измена
ознака: враћена измена |
м (Objašnjenje) |
||
(Није приказано 10 међуизмена 2 корисника) | |||
Ред 3: | Ред 3: | ||
== Поставка == | == Поставка == | ||
Посматра се евиденција о положеним испитима. У једном реду се налазе идентификатор студента и листа | Посматра се евиденција о положеним испитима. У једном реду се налазе идентификатор студента и листа испитима<sup>[sic]</sup> које је положио дати студент. Сваки рад<sup>[sic]</sup> садржи информације о положеном испиту као што су шифра предмета, шифра рока, и оцена коју је студент добио. За потребе наведене евиденције подаци се чувају у текстуалној датотеци на ''Hadoop'' систему. Подаци су дати у облику: | ||
<Student><TAB>{<Exam>{;<Exam>}} | <Student><TAB>{<Exam>{;<Exam>}} | ||
Где поље <code><Student></code> представља идентификатор студента, а поље <code><Exam></code> садржи шифру предмета, након кога долази знак <code>,</code>, па шифра рока, након кога долази знак <code>,</code> и на крају оцена. | Где поље <code><Student></code> представља идентификатор студента, а поље <code><Exam></code> садржи шифру предмета, након кога долази знак <code>,</code>, па шифра рока, након кога долази знак <code>,</code> и на крају оцена. | ||
<div class="abc-list"> | <div class="abc-list"> | ||
# У програмском језику Јава саставити ''Map/Reduce'' посао који враћа статистичке податке о испитима у испитним роковима: шифру предмета, шифру рока, број студената који су полагали дати испит, минималну оцену, максималну оцену и просечну оцену. Водити рачуна о конкурентности. | # У програмском језику Јава саставити ''Map/Reduce'' посао који враћа статистичке податке о испитима у испитним роковима: шифру предмета, шифру рока, број студената који су полагали дати испит, минималну оцену, максималну оцену и просечну оцену. Водити рачуна о конкурентности. | ||
# У програмском језику Јава саставити ланац од два ''Map/Reduce'' посла који враћа предмет<ref>Уколико их има више, вратити било који. Није гарантовано да овај предмет постоји.</ref> који је у задатом испитном R полагало највише студената, а да ни један од тих студената у том року није добио задату оцену N. Параметри R и N се | # У програмском језику Јава саставити ланац од два ''Map/Reduce'' посла који враћа предмет<ref>Уколико их има више, вратити било који. Није гарантовано да овај предмет постоји.</ref> који је у задатом испитном R полагало највише студената, а да ни један од тих студената у том року није добио задату оцену N. Параметри R и N се прослеђује<sup>[sic]</sup> рачунарима који раде обраду. Водити рачуна о конкурентности. | ||
</div> | </div> | ||
Одговор<sup>[sic]</sup> се предају у виду два<sup>[sic]</sup> јава датотека (<code>Ocene1.java</code> и <code>Ocene2.java</code>). | |||
== ''MapReduce'' == | |||
На предмету се од школске 2023/2024. године ради ''Apache Spark'' уместо ''Hadoop'' са ''MapReduce''. Решење овог колоквијума са ''MapReduce'' може се видети на [[Special:Permalink/4291|верзији странице из маја 2022]], док су испод дата решења у ''Apache Spark''. | |||
== <code>Ocene1.java</code> == | == <code>Ocene1.java</code> == | ||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
package | package spark_iep; | ||
import java. | import java.util.LinkedList; | ||
import java.util.List; | |||
import org.apache. | import org.apache.spark.*; | ||
import org.apache. | import org.apache.spark.api.java.*; | ||
import scala.Tuple2; | |||
import | import scala.Tuple5; | ||
import | |||
public class Ocene1 { | public class Ocene1 { | ||
public static | public static void main(String[] args) { | ||
SparkConf conf = new SparkConf() | |||
.setAppName("Ocene1") | |||
.setMaster("local"); | |||
try(JavaSparkContext sc = new JavaSparkContext(conf);){ | |||
JavaRDD<String> ulazniPodaci = sc.textFile("studenti_test.txt"); | |||
//obrada ulaznih podataka | |||
List<Tuple2<String,Integer[]>> rezultat = ulazniPodaci.flatMapToPair( | |||
s->{ | |||
List<Tuple2<String, Integer[]>> lista = new LinkedList<>(); | |||
String[] podaciSvi = s.split("\t"); | |||
//za slucaj da student nema polozene ispite | |||
if(podaciSvi.length==1) return lista.iterator(); | |||
//niz podataka o ispitima za studenta | |||
String[] podaciIspiti = podaciSvi[1].split(";"); | |||
for(String p:podaciIspiti) { | |||
//pod[0] = predmet1,rok1,6 | |||
String[] pod = p.split(","); | |||
//konvertujemo ocenu u string radi dalje obrade | |||
Integer ocena = Integer.parseInt(pod[2]); | |||
//torka spremna za obradu i dodavanje u listu | |||
Tuple2<String, Integer[]> podatakZaListu = new Tuple2<>(pod[0]+"&"+pod[1], new Integer[] {ocena, ocena, ocena, 1}); | |||
lista.add(podatakZaListu); | |||
} | |||
return lista.iterator(); | |||
} | } | ||
) | |||
//prvi clan se koristi za max, drugi za min, treci je suma vrednosti, cetvrti brojac vrednosti | |||
.reduceByKey((a,b)->new Integer[] {Math.max(a[0], b[0]), Math.min(a[1], b[1]), a[2]+b[2], a[3]+b[3]}).collect(); | |||
/ | for(Tuple2<String, Integer[]> r:rezultat) { | ||
System.out.println("Predmet&Rok: "+r._1()+", max:"+r._2()[0]+", min:"+r._2()[1]+", avg:"+(r._2()[2]*1.0/r._2()[3])); | |||
} | } | ||
} | } | ||
} | } | ||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== <code>Ocene2.java</code> == | == <code>Ocene2.java</code> == | ||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
package | package spark_iep; | ||
import java. | import java.util.Arrays; | ||
import java.util.LinkedList; | |||
import java.util.List; | |||
import org.apache. | import org.apache.spark.*; | ||
import org.apache.spark.api.java.*; | |||
import scala.Tuple2; | |||
import scala.Tuple5; | |||
import org.apache. | |||
import | |||
import | |||
public class Ocene2 { | public class Ocene2 { | ||
//predmet zadat rok R, polagalo najvise studenata, a da nema ocene N | |||
public static | public static void main(String[] args) { | ||
SparkConf conf = new SparkConf() | |||
.setAppName("Ocene1") | |||
.setMaster("local"); | |||
try(JavaSparkContext sc = new JavaSparkContext(conf);){ | |||
String rok = "jun2020"; | |||
String zadataOcena = "10"; | |||
JavaRDD<String> ulazniPodaci = sc.textFile("studenti_test.txt"); | |||
//obrada ulaznih podataka | |||
//Tuple2<Integer,String[]> | |||
List<Tuple2<Integer,String[]>> rezultat = ulazniPodaci.flatMapToPair( | |||
s->{ | |||
List<Tuple2<String[], String>> lista = new LinkedList<>(); | |||
String[] podaciSvi = s.split("\t"); | |||
//za slucaj da student nema polozene ispite | |||
if(podaciSvi.length==1) return lista.iterator(); | |||
//niz podataka o ispitima za studenta | |||
String[] podaciIspiti = podaciSvi[1].split(";"); | |||
for(String p:podaciIspiti) { | |||
//pod[0] = predmet1,rok1,6 | |||
String[] pod = p.split(","); | |||
//konvertujemo ocenu u string radi dalje obrade | |||
//torka spremna za obradu i dodavanje u listu | |||
Integer ocena = Integer.parseInt(pod[2]); | |||
//([predmet,rok], ocena) | |||
Tuple2<String[], String> podatakZaListu = new Tuple2<>(new String[] {pod[0],pod[1]}, pod[2]); | |||
lista.add(podatakZaListu); | |||
} | |||
return lista.iterator(); | |||
} | } | ||
) | |||
//isfiltriraj rok | |||
.filter(s->s._1[1].equals(rok)) | |||
//reformatiraj kljuc predmet, vrednost ocena | |||
.mapToPair(s->new Tuple2<String, String>(s._1[0], s._2)) | |||
//ni jedna ocena u roku nije zadata ocena | |||
.filter(s->!(s._2.equals(zadataOcena))) | |||
//pravimoStringOcena ocena1,ocena2... | |||
.reduceByKey((a,b)->(a+";"+b)) | |||
//reformatiraj da bude ([predmet1,ocena1;ocena2...],brojOcena) | |||
.mapToPair(s->new Tuple2<Integer, String[]>(s._2.split(";").length, new String[] {s._1, s._2})) | |||
//sortiraj po broju ocena | |||
.sortByKey(false) | |||
//vrati sve, ovako zbog lakse obrade ako nema | |||
.collect() | |||
; | |||
if(rezultat.size()==0) { | |||
System.out.println("Nema jbg"); | |||
}else { | |||
System.out.println("Trazeni predmet je "+rezultat.get(0)._2[0]); | |||
} | } | ||
} | } | ||
} | } | ||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Тренутна верзија на датум 20. април 2024. у 23:22
Други колоквијум 2022. године одржан је 5. маја. На колоквијуму су били доступни Hadoop документација, презентација са предавања, виртуелна машина коришћена на предавању и два текстуална фајла као примери уноса (без очекиваног исписа или примера R и N параметара).
Поставка
Посматра се евиденција о положеним испитима. У једном реду се налазе идентификатор студента и листа испитима[sic] које је положио дати студент. Сваки рад[sic] садржи информације о положеном испиту као што су шифра предмета, шифра рока, и оцена коју је студент добио. За потребе наведене евиденције подаци се чувају у текстуалној датотеци на Hadoop систему. Подаци су дати у облику:
<Student><TAB>{<Exam>{;<Exam>}}
Где поље <Student>
представља идентификатор студента, а поље <Exam>
садржи шифру предмета, након кога долази знак ,
, па шифра рока, након кога долази знак ,
и на крају оцена.
- У програмском језику Јава саставити Map/Reduce посао који враћа статистичке податке о испитима у испитним роковима: шифру предмета, шифру рока, број студената који су полагали дати испит, минималну оцену, максималну оцену и просечну оцену. Водити рачуна о конкурентности.
- У програмском језику Јава саставити ланац од два Map/Reduce посла који враћа предмет[1] који је у задатом испитном R полагало највише студената, а да ни један од тих студената у том року није добио задату оцену N. Параметри R и N се прослеђује[sic] рачунарима који раде обраду. Водити рачуна о конкурентности.
Одговор[sic] се предају у виду два[sic] јава датотека (Ocene1.java
и Ocene2.java
).
MapReduce
На предмету се од школске 2023/2024. године ради Apache Spark уместо Hadoop са MapReduce. Решење овог колоквијума са MapReduce може се видети на верзији странице из маја 2022, док су испод дата решења у Apache Spark.
Ocene1.java
package spark_iep;
import java.util.LinkedList;
import java.util.List;
import org.apache.spark.*;
import org.apache.spark.api.java.*;
import scala.Tuple2;
import scala.Tuple5;
public class Ocene1 {
public static void main(String[] args) {
SparkConf conf = new SparkConf()
.setAppName("Ocene1")
.setMaster("local");
try(JavaSparkContext sc = new JavaSparkContext(conf);){
JavaRDD<String> ulazniPodaci = sc.textFile("studenti_test.txt");
//obrada ulaznih podataka
List<Tuple2<String,Integer[]>> rezultat = ulazniPodaci.flatMapToPair(
s->{
List<Tuple2<String, Integer[]>> lista = new LinkedList<>();
String[] podaciSvi = s.split("\t");
//za slucaj da student nema polozene ispite
if(podaciSvi.length==1) return lista.iterator();
//niz podataka o ispitima za studenta
String[] podaciIspiti = podaciSvi[1].split(";");
for(String p:podaciIspiti) {
//pod[0] = predmet1,rok1,6
String[] pod = p.split(",");
//konvertujemo ocenu u string radi dalje obrade
Integer ocena = Integer.parseInt(pod[2]);
//torka spremna za obradu i dodavanje u listu
Tuple2<String, Integer[]> podatakZaListu = new Tuple2<>(pod[0]+"&"+pod[1], new Integer[] {ocena, ocena, ocena, 1});
lista.add(podatakZaListu);
}
return lista.iterator();
}
)
//prvi clan se koristi za max, drugi za min, treci je suma vrednosti, cetvrti brojac vrednosti
.reduceByKey((a,b)->new Integer[] {Math.max(a[0], b[0]), Math.min(a[1], b[1]), a[2]+b[2], a[3]+b[3]}).collect();
for(Tuple2<String, Integer[]> r:rezultat) {
System.out.println("Predmet&Rok: "+r._1()+", max:"+r._2()[0]+", min:"+r._2()[1]+", avg:"+(r._2()[2]*1.0/r._2()[3]));
}
}
}
}
Ocene2.java
package spark_iep;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.apache.spark.*;
import org.apache.spark.api.java.*;
import scala.Tuple2;
import scala.Tuple5;
public class Ocene2 {
//predmet zadat rok R, polagalo najvise studenata, a da nema ocene N
public static void main(String[] args) {
SparkConf conf = new SparkConf()
.setAppName("Ocene1")
.setMaster("local");
try(JavaSparkContext sc = new JavaSparkContext(conf);){
String rok = "jun2020";
String zadataOcena = "10";
JavaRDD<String> ulazniPodaci = sc.textFile("studenti_test.txt");
//obrada ulaznih podataka
//Tuple2<Integer,String[]>
List<Tuple2<Integer,String[]>> rezultat = ulazniPodaci.flatMapToPair(
s->{
List<Tuple2<String[], String>> lista = new LinkedList<>();
String[] podaciSvi = s.split("\t");
//za slucaj da student nema polozene ispite
if(podaciSvi.length==1) return lista.iterator();
//niz podataka o ispitima za studenta
String[] podaciIspiti = podaciSvi[1].split(";");
for(String p:podaciIspiti) {
//pod[0] = predmet1,rok1,6
String[] pod = p.split(",");
//konvertujemo ocenu u string radi dalje obrade
//torka spremna za obradu i dodavanje u listu
Integer ocena = Integer.parseInt(pod[2]);
//([predmet,rok], ocena)
Tuple2<String[], String> podatakZaListu = new Tuple2<>(new String[] {pod[0],pod[1]}, pod[2]);
lista.add(podatakZaListu);
}
return lista.iterator();
}
)
//isfiltriraj rok
.filter(s->s._1[1].equals(rok))
//reformatiraj kljuc predmet, vrednost ocena
.mapToPair(s->new Tuple2<String, String>(s._1[0], s._2))
//ni jedna ocena u roku nije zadata ocena
.filter(s->!(s._2.equals(zadataOcena)))
//pravimoStringOcena ocena1,ocena2...
.reduceByKey((a,b)->(a+";"+b))
//reformatiraj da bude ([predmet1,ocena1;ocena2...],brojOcena)
.mapToPair(s->new Tuple2<Integer, String[]>(s._2.split(";").length, new String[] {s._1, s._2}))
//sortiraj po broju ocena
.sortByKey(false)
//vrati sve, ovako zbog lakse obrade ako nema
.collect()
;
if(rezultat.size()==0) {
System.out.println("Nema jbg");
}else {
System.out.println("Trazeni predmet je "+rezultat.get(0)._2[0]);
}
}
}
}
Провера
Следећи садржај датотеке која се прослеђује као први аргумент оба програма може се користити за тестирање:
pera predmet1,jun2020,9;predmet2,jun2020,10;predmet3,jun2020,9;predmet1,jul2020,10;predmet3,jul2020,10 mika predmet1,jun2020,6;predmet2,jun2020,6;predmet3,jun2020,7;predmet1,jul2020,6 zika predmet1,jun2020,8 jovan
(додати табулатор на крај последњег реда ручно уколико се не ископира).
На колоквијуму су биле доступне Students_V0.txt
и Students_V1.txt
датотеке за тестирање решења.
Напомене
- ↑ Уколико их има више, вратити било који. Није гарантовано да овај предмет постоји.