First Responder

Napisati program koji obrađuje podatke o dostupnosti vatrogasnih društava u slučaju požara. Podaci su zadati u ulaznoj datoteci u sledećem formatu:

  • mesto (jedna reč, do 30 karaktera)

  • geografska_sirina (realna vrednost)

  • geografska_duzina (realna vrednost)

Učitati podatke o vatrogasnim društvima u statički niz od 30 elemenata, koji će biti dostupni u slučaju požara. Nakon učitanih podataka, program učitava geografsku širinu i dužinu lokacije gde se dogodio požar, kao i kategoriju požara. U zavisnosti od ozbiljnosti požara, definišu se tri kategorije u odnosu na mesto dešavanja požara:

  • Žuta (Z): angažuju se sve vatrogasne stanice u krugu poluprečnika od 5km vazdušnom linijom

  • Narandžasta (N): angažuju se sve vatrogasne stanice u krugu poluprečnika od 10km vazdušnom linijom

  • Crvena (C): angažuju se sve vatrogasne stanice u krugu poluprečnika od 20km vazdušnom linijom

Rastojanje između dve tačke na Zemlji određuje se Haversinusnom formulom (data je u nastavku teksta). Ispisati sva vatrogasna društva koja će biti zahvaćena krugom. U ispis se računaju mesta i vazdušne razdaljine u kilometrima dobijeno korišćenjem Haversinusne formule. Ukoliko krug koji se formira oko lokacije požara ne obuhvata nijedno vatrogasno društvo, uzeti prvo najbliže izvan kruga.

Prilikom ispisa označiti tzv. "First responder-a", odnosno, vatrogasno društvo koje je očekivano da stigne najbrže na mesto incidenta. Dodati "(FR)" na string sa imenom mesta korišćenjem odgovarajuće funkcije za rad sa stringovima.

Korisne matematičke formule

Konverzija iz stepena u radijane

\[\varphi = stepeni * \pi / 180\]

Haversinusna formula

\[a = \sin^2(\frac{\Delta\varphi}{2}) + \cos(\varphi_{1})\cos(\varphi_{2})\sin^2(\frac{\Delta\lambda}{2})\]
\[c = 2 \cdot \arctan2(\sqrt{a}, \sqrt{1 - a})\]
\[d = R \cdot c\]

Legenda korišćenih simbola:

φ1, φ2 = geografske širine u radijanima
λ1, λ2 = geografske dužine u radijanima
Δφ = φ2 - φ1
Δλ = λ2 - λ1
R = poluprecnik Zemlje ≈ 6371km
d = vazdušna razdaljina u kilometrima

U slučaju uspešnog izvršavanja programa, izaći sa status kodom 0 (EXIT_SUCCESS). U slučaju nedovoljnog ili suvišnog broj argumenata komandne linije, izaći iz programa sa status kodom 1 (EXIT_FAILURE)

Primer ulazne datoteke vatrogasci.txt:

10
NoviSad      45.25911 19.84136
NoviSad      45.25933 19.84243
Petrovaradin 45.25454 19.86955
SrKamenica   45.22360 19.84423
Beocin       45.20785 19.71315
Futog        45.23843 19.70290
Rumenka      45.29567 19.74313
Temerin      45.40310 19.88465
Kac          45.30150 19.93775
Budisava     45.28354 19.98786

Primer poziva programa:

./a.out 45.25388 19.85194 Z < vatrogasci.txt

Primer ispisa programa na standardni izlaz:

Unesite broj vatrogasnih drustava: 
1. vatrogasno drustvo: 
2. vatrogasno drustvo: 
3. vatrogasno drustvo: 
4. vatrogasno drustvo: 
5. vatrogasno drustvo: 
6. vatrogasno drustvo: 
7. vatrogasno drustvo: 
8. vatrogasno drustvo: 
9. vatrogasno drustvo: 
10. vatrogasno drustvo: 

NoviSad 1.01km
NoviSad(FR) 0.96km
Petrovaradin 1.38km
SrKamenica 3.42km

Primer poziva programa kad nema vatrogasnog društva u okolini:

./a.out 45.344119 19.857105 Z < vatrogasci.txt

Primer ispisa programa na standardni izlaz:

Unesite broj vatrogasnih drustava: 
1. vatrogasno drustvo: 
2. vatrogasno drustvo: 
3. vatrogasno drustvo: 
4. vatrogasno drustvo: 
5. vatrogasno drustvo: 
6. vatrogasno drustvo: 
7. vatrogasno drustvo: 
8. vatrogasno drustvo: 
9. vatrogasno drustvo: 
10. vatrogasno drustvo: 

Temerin(FR) 6.90km

Primer rešenja

  1#include <stdio.h>
  2#include <string.h>
  3#include <math.h>
  4#include <stdlib.h>
  5
  6#define MAX_MESTO 31
  7
  8#define MAX_SIZE 30
  9
 10#define R 6371.0
 11
 12typedef struct vatrogasci_st
 13{
 14    char mesto[MAX_MESTO];
 15    double geografska_sirina;
 16    double geografska_duzina;
 17} VATROGASCI;
 18
 19void ucitaj_vatrogasna_drustva(VATROGASCI *v, int *pn);
 20double domet_kategorije(char kategorija_pozara);
 21double stepeni_u_radijane(double stepeni);
 22double haversinusna_razdaljina(double geogr_sirina1, double geogr_duzina1, double geogr_sirina2, double geogr_duzina2);
 23void ispisi_angazovana_vatrogasna_drustva(
 24    VATROGASCI *v, int n, double geografska_sirina_pozara, double geografska_duzina_pozara, double poluprecnik);
 25
 26int main(int argc, char **argv)
 27{
 28    VATROGASCI vatrogasci[MAX_SIZE];
 29    int n;
 30
 31    if(argc != 4)
 32    {
 33        printf("Primer poziva: %s 45.25388 19.85194 Z < vatrogasci.txt\n", argv[0]);
 34        exit(EXIT_FAILURE);
 35    }
 36
 37    ucitaj_vatrogasna_drustva(vatrogasci, &n);
 38
 39    double geografska_sirina_pozara = atof(argv[1]);
 40    double geografska_duzina_pozara = atof(argv[2]);
 41    char kategorija_pozara = argv[3][0];
 42
 43    double poluprecnik = domet_kategorije(kategorija_pozara);
 44
 45    printf("\n\n");
 46    ispisi_angazovana_vatrogasna_drustva(vatrogasci, n, geografska_sirina_pozara, geografska_duzina_pozara, poluprecnik);
 47
 48    return EXIT_SUCCESS;
 49}
 50
 51void ucitaj_vatrogasna_drustva(VATROGASCI *v, int *pn)
 52{
 53    int i;
 54
 55    do
 56    {
 57        printf("Unesite broj vatrogasnih drustava: ");
 58        scanf("%d", pn);
 59    } while (*pn <= 0 || *pn > MAX_SIZE);
 60    
 61    for(i = 0;i < *pn;i++)
 62    {
 63        printf("\n%d. vatrogasno drustvo: ", i + 1);
 64        scanf("%s %lf %lf", v[i].mesto, &v[i].geografska_sirina, &v[i].geografska_duzina);
 65    }
 66}
 67
 68double domet_kategorije(char kategorija_pozara)
 69{
 70    switch(kategorija_pozara)
 71    {
 72        case 'Z':
 73            return 5.0;
 74        case 'N':
 75            return 10.0;
 76        case 'C':
 77            return 20.0;
 78    }
 79
 80    return 0.0;
 81}
 82
 83double stepeni_u_radijane(double stepeni)
 84{
 85    return stepeni * M_PI / 180;
 86}
 87
 88double haversinusna_razdaljina(double geogr_sirina1, double geogr_duzina1, double geogr_sirina2, double geogr_duzina2)
 89{
 90    double fi1 = stepeni_u_radijane(geogr_sirina1);
 91    double fi2 = stepeni_u_radijane(geogr_sirina2);
 92
 93    double delta_fi = stepeni_u_radijane(geogr_sirina2 - geogr_sirina1);
 94    double delta_lambda = stepeni_u_radijane(geogr_duzina2 - geogr_duzina1);
 95
 96    double a = pow(sin(delta_fi / 2), 2) +
 97               cos(fi1) * cos(fi2) *
 98               pow(sin(delta_lambda / 2), 2);
 99
100    double c = 2 * atan2(sqrt(a), sqrt(1 - a));
101
102    return R * c;
103}
104
105void ispisi_angazovana_vatrogasna_drustva(
106    VATROGASCI *v, int n, double geografska_sirina_pozara, double geografska_duzina_pozara, double poluprecnik)
107{
108    int i, indeks_najblizeg = 0;
109    double vazdusne_razdaljine[MAX_SIZE], najbliza_razdaljina = haversinusna_razdaljina(
110            v[0].geografska_sirina, v[0].geografska_duzina, geografska_sirina_pozara, geografska_duzina_pozara);;
111
112    for(i = 0;i < n;i++)
113    {
114        vazdusne_razdaljine[i] = haversinusna_razdaljina(
115            v[i].geografska_sirina, v[i].geografska_duzina, geografska_sirina_pozara, geografska_duzina_pozara);
116        
117        if(vazdusne_razdaljine[i] < najbliza_razdaljina)
118        {
119            najbliza_razdaljina = vazdusne_razdaljine[i];
120            indeks_najblizeg = i;
121        }
122    }
123
124    int ima_u_poluprecniku = 0;
125
126    for(i = 0;i < n;i++)
127    {
128        if(indeks_najblizeg == i)
129        {
130            strcat(v[i].mesto, "(FR)");
131        }
132
133        if(vazdusne_razdaljine[i] <= poluprecnik)
134        {
135            printf("%s %.2lfkm\n", v[i].mesto, vazdusne_razdaljine[i]);
136            ima_u_poluprecniku = 1;
137        }
138    }
139
140    if(ima_u_poluprecniku == 0)
141    {
142        printf("%s %.2lfkm\n", v[indeks_najblizeg].mesto, vazdusne_razdaljine[indeks_najblizeg]);
143    }
144}