ИЕП/К2 2022

Извор: SI Wiki
< ИЕП
Датум измене: 20. април 2024. у 23:22; аутор: KockaAdmiralac (разговор | доприноси) (Uklonjeno moje rešenje)
Пређи на навигацију Пређи на претрагу

Други колоквијум 2022. године одржан је 5. маја. На колоквијуму су били доступни Hadoop документација, презентација са предавања, виртуелна машина коришћена на предавању и два текстуална фајла као примери уноса (без очекиваног исписа или примера R и N параметара).

Поставка

Посматра се евиденција о положеним испитима. У једном реду се налазе идентификатор студента и листа испитима[sic] које је положио дати студент. Сваки рад[sic] садржи информације о положеном испиту као што су шифра предмета, шифра рока, и оцена коју је студент добио. За потребе наведене евиденције подаци се чувају у текстуалној датотеци на Hadoop систему. Подаци су дати у облику:

<Student><TAB>{<Exam>{;<Exam>}}

Где поље <Student> представља идентификатор студента, а поље <Exam> садржи шифру предмета, након кога долази знак ,, па шифра рока, након кога долази знак , и на крају оцена.

  1. У програмском језику Јава саставити Map/Reduce посао који враћа статистичке податке о испитима у испитним роковима: шифру предмета, шифру рока, број студената који су полагали дати испит, минималну оцену, максималну оцену и просечну оцену. Водити рачуна о конкурентности.
  2. У програмском језику Јава саставити ланац од два Map/Reduce посла који враћа предмет[1] који је у задатом испитном R полагало највише студената, а да ни један од тих студената у том року није добио задату оцену N. Параметри R и N се прослеђује[sic] рачунарима који раде обраду. Водити рачуна о конкурентности.

Одговор[sic] се предају у виду два[sic] јава датотека (Ocene1.java и Ocene2.java).

MapReduce

На предмету се од школске 2023/2024. године ради Apache Spark уместо Hadoop са MapReduce. Решење овог колоквијума са MapReduce може се видети на верзији странице из маја 2022.

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 датотеке за тестирање решења.

Напомене

  1. Уколико их има више, вратити било који. Није гарантовано да овај предмет постоји.