Advertisement
MartinSRB

[ОС] Припрема за Т1234 - Случајни бројеви

May 9th, 2023
1,138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.93 KB | None | 0 0
  1. /**
  2.  * Napisati C++ program koji cita podatke o uniformnim distribucijama iz ulazne datoteke i potom za
  3.  * svaku distribuciju generise po 10 brojeva, racuna njihov prosek, i nalazi najmanji i najveci broj.
  4.  *
  5.  * U ulaznoj datoteci "distribucije.txt" se u svakom redu nalaze informacije o donjoj i gornjoj granici
  6.  * intervala u kojem treba generisati brojeve. Informacije o gornjoj i donjoj granici su odvojene dvotackom.
  7.  *  U pitanju su razlomljeni brojevi.
  8.  *
  9.  * U izlaznoj datoteci "brojevi.csv" treba da se nalaze u jednom redu odvojeni zarezom prvo 10
  10.  * izgenerisanih brojeva a potom i prosek, najmanji element i najveci element.
  11.  *
  12.  * Treba napraviti jednu nit koja ce samo citati ulazne podatke, jednu nit koja ce samo pisati gotove
  13.  * brojeve u datoteku i 6 niti radnika koji ce na osnovu podataka iz ulazne datoteke generisati sve
  14.  * neophodno za ispis u izlaznu datoteku.
  15. */
  16. #include <iostream>
  17. #include <mutex>
  18. #include <condition_variable>
  19. #include <fstream>
  20. #include <vector>
  21. #include <thread>
  22. #include <regex>
  23. #include <random>
  24. #include <chrono>
  25. #include <algorithm>
  26.  
  27. #define BROJ_RADNIKA 6
  28.  
  29. using namespace std;
  30. using namespace chrono;
  31.  
  32. /** Klasa koja modeluje "postansko sanduce" izmedju citaca i radnika.
  33. */
  34. template<typename T>
  35. class UlazniPodaci {
  36. private:
  37.     mutex podaci_mx;                       // propusnica za sinhronizaciju nad svim poljima klase
  38.     // TODO dodati polja ako je potrebno
  39.     condition_variable cv;
  40.     vector<T> data;
  41.     bool kraj;
  42.     int workers;
  43. public:
  44.     UlazniPodaci(): kraj(false), workers(0) {}  // na pocetku nije kraj i nema radnika
  45.  
  46.     void dodaj(T par_granica) {
  47.         // TODO
  48.         unique_lock<mutex> l(podaci_mx);
  49.         data.push_back(par_granica);
  50.         cv.notify_one();
  51.     }
  52.  
  53.     bool preuzmi(T &par_granica) {
  54.         // TODO
  55.         unique_lock<mutex> l(podaci_mx);
  56.         while(daLiCekamPodatke()){
  57.             cv.wait(l);
  58.         }
  59.         if(jeLiKraj()){
  60.             return false;
  61.         }
  62.         par_granica = data.back();
  63.         data.pop_back();
  64.         return true;
  65.     }
  66.  
  67.     // TODO dodati jos neku metodu ako je potrebno
  68.     void addWorker(){
  69.         unique_lock<mutex> l(podaci_mx);
  70.         ++workers;
  71.     }
  72.     void removeWorker(){
  73.         unique_lock<mutex> l(podaci_mx);
  74.         if((--workers) == 0){
  75.             kraj = true;
  76.             cv.notify_one();
  77.         }
  78.     }
  79. private:
  80.     /**
  81.      * Provera da li treba da cekamo podatke. Vraca istinu samo onda kada u kolekciji
  82.      * nema podataka ali istovremeno i nije objavljen kraj stvaranja podataka.
  83.     */
  84.     bool daLiCekamPodatke() {
  85.         // TODO
  86.         return data.empty() && !kraj;
  87.     }
  88.  
  89.     /**
  90.      * Provera da li smo zavrsili sa citanjem podataka. Vraca istinu samo onda kada nema vise podataka
  91.      * u kolekciji i sve niti stvaraoci podataka su se odjavili.
  92.     */
  93.     bool jeLiKraj() {
  94.         // TODO
  95.         return data.empty() && kraj;
  96.     }
  97. };
  98.  
  99.  
  100. /** Klasa koja modeluje "postansko sanduce" izmedju radnika i pisaca.
  101. */
  102. template<typename T>
  103. class IzlazniPodaci {
  104. private:
  105.     mutex podaci_mx;                       // propusnica za sinhronizaciju nad svim poljima klase
  106.     // TODO dodati polja ako je potrebno
  107.     condition_variable cv;
  108.     int br_stvaralaca_podataka;
  109.     bool kraj;
  110.     vector<T> data;
  111. public:
  112.     IzlazniPodaci(): kraj(false), br_stvaralaca_podataka(0) {}  // na pocetku nije kraj i nema radnika
  113.  
  114.     void dodaj(T brojevi) {
  115.         // TODO
  116.         unique_lock<mutex> l(podaci_mx);
  117.         data.push_back(brojevi);
  118.         //cv.notify_one();
  119.     }
  120.  
  121.     bool preuzmi(T &brojevi) {
  122.         // TODO
  123.         unique_lock<mutex> l(podaci_mx);
  124.         while(daLiCekamPodatke()){
  125.             cv.wait(l);
  126.         }
  127.         if(jeLiKraj()){
  128.             return false;
  129.         }
  130.         brojevi = data.back();
  131.         data.pop_back();
  132.         return true;
  133.     }
  134.  
  135.     // TODO dodati jos neku metodu ako je potrebno
  136.     void addWorker(){
  137.         unique_lock<mutex> l(podaci_mx);
  138.         ++br_stvaralaca_podataka;
  139.     }
  140.     void removeWorker(){
  141.         unique_lock<mutex> l(podaci_mx);
  142.         if((--br_stvaralaca_podataka) == 0){
  143.             kraj = true;
  144.             cv.notify_one();
  145.         }
  146.     }
  147.     void test(){
  148.         for(auto i = data.begin(); i != data.end(); ++i){
  149.             for(auto j = (*i).begin(); j != (*i).end(); ++j){
  150.                 cout << *j << " ";
  151.             }
  152.             cout << endl;
  153.         }
  154.     }
  155. private:
  156.     /**
  157.      * Provera da li treba da cekamo podatke. Vraca istinu samo onda kada u kolekciji
  158.      * nema podataka ali istovremeno i nije objavljen kraj stvaranja podataka.
  159.     */
  160.     bool daLiCekamPodatke() {
  161.         // TODO
  162.         return data.empty() && !kraj;
  163.     }
  164.  
  165.     /**
  166.      * Provera da li smo zavrsili sa citanjem podataka. Vraca istinu samo onda kada nema vise podataka
  167.      * u kolekciji i sve niti stvaraoci podataka su se odjavili.
  168.     */
  169.     bool jeLiKraj() {
  170.         // TODO
  171.         return data.empty() && kraj;
  172.     }
  173. };
  174.  
  175.  
  176. /**
  177.  * Logika radnika - niti koje vrse transformaciju ulaznih podataka u izlazne podatke spremne za ispis.
  178. */
  179. void radnik(UlazniPodaci<pair<double, double>> &ulaz, IzlazniPodaci<vector<double>> &izlaz) {
  180.     // TODO
  181.     izlaz.addWorker();
  182.     default_random_engine gen;
  183.     pair<double, double> tmp;
  184.     vector<double> brojevi;
  185.     gen.seed(steady_clock::now().time_since_epoch().count());
  186.     while(ulaz.preuzmi(tmp)){
  187.         uniform_real_distribution<double> rdist(tmp.first, tmp.second);
  188.         for(int i = 0; i < 10; ++i){
  189.             brojevi.push_back(rdist(gen));
  190.         }
  191.         brojevi.push_back(*min_element(brojevi.begin(), brojevi.end()));
  192.         brojevi.push_back(*max_element(brojevi.begin(), brojevi.end() - 1));
  193.         brojevi.push_back(accumulate(brojevi.begin(), brojevi.end()-2, 0.) / (brojevi.size() - 2));
  194.         izlaz.dodaj(brojevi);
  195.         brojevi.resize(0);
  196.     }
  197.     izlaz.removeWorker();
  198. }
  199.  
  200. /**
  201.  * Logika citaca_iz_datoteke - nit koja radi citanje iz ulazne datoteke i salje u ulaznu kolekciju za radnike
  202. */
  203. void citacf(string ime_ulazne_dat, UlazniPodaci<pair<double, double>> &ulaz) {
  204.     // TODO
  205.     ulaz.addWorker();
  206.     pair<double, double> tmp;
  207.     ifstream file(ime_ulazne_dat);
  208.     regex r("([0-9\\.\\-]+):([0-9\\.\\-]+)");
  209.     smatch match;
  210.     if(file.is_open()){
  211.         string line;
  212.         while(getline(file, line)){
  213.             if(regex_search(line,match,r)){
  214.                 tmp = { stod(match[1]), stod(match[2]) };
  215.                 ulaz.dodaj(tmp);
  216.             }//preskacem red ako se ne slaze kako sam ja rekao
  217.         }
  218.     }else{
  219.         cout << "Nmg da otvorim fajl." << endl;
  220.     }
  221.     file.close();
  222.     ulaz.removeWorker();
  223. }
  224.  
  225. /**
  226.  * Logika pisaca_u_datoteku - nit koja radi pisanje u izlaznu datoteku podataka dobijenih od radnika
  227. */
  228. void pisacf(IzlazniPodaci<vector<double>> &izlaz, string ime_izlazne_dat) {
  229.     // TODO
  230.     ofstream file(ime_izlazne_dat);
  231.     vector<double> brojevi;
  232.     if(file.is_open()){
  233.         while(izlaz.preuzmi(brojevi)){
  234.             bool first = true;
  235.             for(vector<double>::const_iterator i = brojevi.begin(); i != brojevi.end(); ++i){
  236.                 if(!first){
  237.                     file << "," << *i;
  238.                 }else{
  239.                     file << *i;
  240.                     first = false;
  241.                 }
  242.             }
  243.             file << endl;
  244.         }
  245.     }else{
  246.         cerr << "nmg da otvorim fajl pisacf" << endl;
  247.     }
  248.     file.close();
  249. }
  250.  
  251. int main() {
  252.     UlazniPodaci<pair<double, double>> ulaz;
  253.     IzlazniPodaci<vector<double>> izlaz;
  254.     thread t_reader(citacf, "distribucije.txt", ref(ulaz));
  255.     thread t_workers[BROJ_RADNIKA];
  256.     thread t_writer(pisacf, ref(izlaz), "brojevi.csv");
  257.     t_reader.join();
  258.     for(thread &th : t_workers){
  259.         th = thread(radnik, ref(ulaz), ref(izlaz));
  260.     }
  261.     for(thread &th : t_workers){
  262.         th.join();
  263.     }
  264.     t_writer.join();
  265.     return 0;
  266. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement