Problem Set 6: Dotácie

Ciele

  • Porozumieť reprezentácii čísiel v pamäti počítača.
  • Vytvoriť vlastné funkcie podľa špecifikácie.
  • Naučiť sa ukončovať funkcie pomocou rozličných návratových hodnôt pri rozličných vstupných parametroch.

Úloha 1: Nemeckí farmári

Nemeckí farmári dostávajú dotácie v závislosti od podmienok na ich farmách. Predstavme si nasledujúcu situáciu:

Poznáme veľkosť pozemku každej farmy (v metroch štvorcových) a počet zvierat, ktoré na každej farme žijú. Nerobíme rozdiely medzi jednotlivými zvieratami (aj keď toto pravidlo má ďaleko od reality). Navyše máme informáciu, do akej miery používa každý farmár ekologické nástroje a postupy, čo je vyjadrené celým číslom väčším ako nula. Počet peňazí, ktoré každý farmár dostane, je vypočítaný nasledovne:

Najskôr potrebujeme vedieť, priemerne koľko miesta zaberá každé zviera chované na farme (táto hodnota je zaokrúhlená na dve desatinné miesta). Táto hodnota (v metroch štvorcových) je následne vynásobená parametrom, ktorý vyjadruje mieru ekologického prístupu farmára. Vo výsledku teda dostaneme, koľko dostane každý farmár na každé zviera, ktoré vlastní. Aby sme vypočítali celkovú dotáciu jedného farmára, potrebujeme tento výsledok jednoducho vynásobiť počtom zvierat, ktoré chová.

Vytvorte program, ktorý bude implementáciou dotácie pre nemeckých farmárov.

Prvou vstupnou hodnotou programu bude kladné celé číslo z rozsahu <0,20>, ktoré vyjadruje počet farmárov. Pre každého farmára následne uvedieme tri kladné celé čísla, ktoré predstavujú: Veľkosť farmy v metroch štvorcových, počet zvierat chovaných na farme a mieru ekologického prístupu farmára. Žiadna z týchto troch vstupných hodnôt nesmie byť menšia ako 0 ani väčšia ako 10000.

Ak niektorá z hodnôt nie je z uvedeného rozsahu, program okamžite svoju činnosť ukončí s návratovým kódom 1 a hláškou Wrong input!.

V opačnom prípade program vypíše jednu hodnotu, ktorá vyjadruje celkovú výšku dotácií spolu pre všetkých farmárov a svoju činnosť ukončí s návratovým kódom 0. Vypísaná hodnota však musí byť zaokrúhlená na dve desatinné miesta!

Poznámka

Výstup programu končí novým riadkom '\n'.

Príklady použitia programu

Ak je niektorá z hodnôt mimo daného rozsahu, program končí s kódom 1:

$ ./farmers
21 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 500 30 3 300 100 2
Wrong input!
$ ./farmers
2 100 6 2 200 20 -1
Wrong input!

Poznámka

Výstup programu končí novým riadkom '\n'.

Ak sú zadané hodnoty správne, program vypíše výšku dotácie za všetkých farmárov (s presnosťou na dve desatinné miesta) a končí s kódom 0:

$ ./farmers
20 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 500 30 3 100 6 2 100 7 4 200 20 1 300 101 2
Total donation: 10601.94

Poznámka

Výstup programu končí novým riadkom '\n'.

Hodnotenie

Táto úloha je za max. 2 body.

Upozornenie

Pri hodnotení sa ráta každý jeden znak!

Úloha 2: Obedy na TUKE

Študenti a zamestnanci Technickej univerzity v Košiciach dostávajú na obedoch dotácie podľa nasledujúcich pravidiel:

  • Študenti:
    • Dotácia je vo výške 1 EUR, ak cena jedla je aspoň 2.00 EUR, ale menej ako 4.00 EUR.
    • Dotácia je vo výške 2 EUR, ak cena jedla je aspoň 4.00 EUR.
  • Zamestnanci:
    • Nárok na dotáciu vzniká, ak cena jedla je aspoň 1.80 EUR.
    • Dotácia je vo výške 55% ceny jedla + príspevok zo sociálneho fondu, t.j. 0.42 EUR.
    • Ak si však zamestnanec zvolí jedlo drahšie ako 3.60 EUR, dotácia sa počíta stále zo sumy 3.60 EUR a zvyšok ceny nie je dotovaný, až kým cena jedla nedosiahne sumu aspoň 5.40 EUR. Systém automaticky priznáva ďalšiu dotáciu až do hodnoty jedla 7.20 EUR (t.j. 2x 3.60 EUR ako za dva obedy naraz). Od hodnoty jedla 9.00 EUR by systém priznal tretiu dotáciu, atď.
    • Výsledná suma je zaokrúhlená na dve desatinné miesta.

Vytvorte program, ktorý bude implementáciou dotácií obedov na TUKE.

Váš program na začiatku načíta počet ľudí resp. obedov, pre ktoré má vypočítať dotácie. Toto číslo musí byť z intervalu <0,20>. V opačnom prípade program okamžite svoju činnosť ukončí s návratovým kódom 1 a hláškou Wrong input!.

Pre každú osobu (obed) sa následne načíta dvojica hodnôt študent/zamestnanec a cena za jedlo:

  • Prvá hodnota je 1 (ak je osoba študent) alebo 2 (ak je osoba zamestnanec).
  • Druhá hodnota je aspoň 0.00, t.j. nesmie byť záporná.
  • Ak je niektorá z načítaných hodnôt mimo povolený rozsah, program okamžite svoju činnosť ukončí s návratovým kódom 1 a hláškou Wrong input!.

Po načítaní všetkých hodnôt program vypočíta celkovú výšku dotácií za obed (súčet dotácií) a sumu, ktorú po odpočítaní dotácie všetci spoločne na obede zaplatili. Tieto dve hodnoty program vypíše na obrazovku s presnosťou na dve desatinné miesta.

Príklady použitia

V nasledujúcom texte sa budú nachádzať príklady použitia programu. Text zvýraznený tučne bude predstavovať vstup od používateľa. Riadok začínajúci znakom '$' bude predstavovať príkazový riadok.

V tomto prípade sa počítajú dotácie pre troch ľudí (študent, zamestnanec, zamestnanec). Všetky hodnoty sú zadané správne. Druhý zamestnanec má započítané dve dotácie:

$ ./lunch
3 1 2.55 2 2.55 2 5.50
Total: 6.69 donated, 3.91 paid.

Ak je niektorá zo vstupných hodnôt neplatná, program končí s hláškou Wrong input! a kódom 1.

$ ./lunch
22 1 1.3 1 2.4 2 1.3 2 2.4 1 3.3 1 3.4 2 3.3 2 3.4 1 4.3 1 4.4 2 4.3 2 4.4 1 1.3 1 2.4 2 1.3 2 2.4 2 3.3 2 3.4 1 1.3 1 1.4 1 0.3 1 2.4
Wrong input!
$ ./lunch
3 3 2.00 2 2.55 2 5.50
Wrong input!

Poznámka

Výstup programu končí novým riadkom '\n'.

Hodnotenie

Táto úloha je za max. 2 body.

Upozornenie

Pri hodnotení sa ráta každý jeden znak!

Úloha 3: Supergrant

V Sedmikráskove vyhlásili súťaž o zisk supergrantu pre pestovateľov sedmikrások.

Vašou úlohou bude najskôr naprogramovať 6 funkcií:

  • int is_prime(const int number) - Zistí, či je dané číslo number prvočíslo (prime number).
  • int next_prime(const int prime) - Na základe daného prvočísla prime nájde nasledujúce prvočíslo.
  • long int find_A_n(const int n) - Na základe daného čísla n nájde číslo A_n.
  • int sum_digits(const long int number) - Vypočíta ciferný súčet pre vstupné číslo number.
  • int sum_digits_n(const int n) - Na základe daného čísla n nájde n-té číslo v postupnosti ciferných súčtov.
  • int constant(const int a, const int b) - Vypočíta konštantu K supergrantu.

Supergrant sa udeľuje na základe troch vstupných hodnôt: Veľkosť pozemku (a), číslo hnojiva (b) a požadovaná suma. O supergrant môžu požiadať len tí pestovatelia, ktorých pozemok má veľkosť 1 <= a <= 5000 metrov štvorcových, a zároveň používajú hnojivo s číslom -20 <= b <= 20. Každý uchádzač sa uchádza o inú sumu, ktorá musí byť aspoň 1000 EUR, ale nesmie byť viac ako 1000000 EUR.

Program začína načítaním troch celočíselných hodnôt: Veľkosť pozemku, číslo hnojiva, požadovaná suma. Program následne vypíše na obrazovku výšku prideleného supergrantu.

V prípade, že niektorá z hodnôt nie je z povoleného rozsahu, program vypíše hlášku Wrong input! a ihneď sa ukončí s návratovou hodnotou 1.

Pre pestovateľov, ktorí spĺňajú podmienky, sa vypočíta supergrant na základe konštanty K, ktorá predstavuje percento, o ktoré sa uchádzačovi zníži požadovaná suma supergrantu. Napr. ak je konštanta K rovná 1, potom sa uchádzačovi vyplatí 99% z požadovanej sumy. Výsledná suma supergrantu bude pestovateľovi oznámená v rámci výstupu programu s presnosťou na dve desatinné miesta.

Úloha 3.1: Je číslo prvočíslo?

Naprogramujte funkciu int is_prime(const int number) s parametrom:

  • const int number - Číslo, pre ktoré sa zisťuje, či ide o prvočíslo

Funkcia vráti hodnotu 1, ak je dané číslo number prvočíslo (prime number). V opačnom prípade vráti funkcia hodnotu 0.

Príklad použitia funkcie:

printf("%d\n", is_prime(1));
// prints: 0
printf("%d\n", is_prime(7));
// prints: 1

Úloha 3.2: Nájdi nasledujúce prvočíslo

Naprogramujte funkciu int next_prime(const int prime) s parametrom:

  • const int prime - Číslo, pre ktoré sa hľadá nasledujúce prvočíslo

Funkcia vráti hodnotu najbližšieho nasledujúceho prvočísla (prime number) za vstupným prvočíslom prime. Avšak ak dané číslo number nie je prvočíslo (prime number), funkcia vráti hodnotu -1.

Príklad použitia funkcie:

printf("%d\n", next_prime(1));
// prints: -1
printf("%d\n", next_prime(7));
// prints: 11

Úloha 3.3: Nájdi A_n

Naprogramujte funkciu long int find_A_n(const int n) s parametrom:

  • const int n - Číslo, na základe ktorého sa hľadá číslo A_n

Nech A_n je najmenšie kladné celé číslo (väčšie ako 1), ktoré vyhovuje vzťahu A_n mod p_i = i. Platí:

  • 1 <= i <= n
  • p_i je také prvočíslo (prime number), ktoré je i-te v poradí, napr. p_1 = 2, p_2 = 3 atď.
A_1 = 3, lebo: A_1 mod 2 = 1
A_2 = 5, lebo: A_2 mod 2 = 1, A_2 mod 3 = 2
A_3 = 23, lebo: A_3 mod 2 = 1, A_3 mod 3 = 2, A_3 mod 5 = 3

Funkcia vráti celé číslo typu long int, ktoré vyhovuje danému vzťahu. Avšak ak je parameter n menej ako 1, funkcia vráti hodnotu 0.

Príklad použitia funkcie:

printf("%ld\n", find_A_n(0));
// prints: 0
printf("%ld\n", find_A_n(4));
// prints: 53

Úloha 3.4: Ciferný súčet

Naprogramujte funkciu int sum_digits(const long int number) s parametrom:

  • const long int number - Číslo, pre ktoré sa vypočíta ciferný súčet

Funkcia vráti hodnotu rovnú súčtu jednotlivých cifier daného čísla number. Avšak ak je vstupné číslo number záporné (menšie ako 0), funkcia vráti hodnotu 0.

Príklad použitia funkcie:

printf("%d\n", sum_digits(-1));
// prints: 0
printf("%d\n", sum_digits(12345678));
// prints: 36

Úloha 3.5: Súčet cifier v postupnosti

Naprogramujte funkciu int sum_digits_n(const int n) s parametrom:

  • const int n - Číslo, pre ktoré sa vypočíta súčet cifier v postupnosti

Funkcia vráti hodnotu rovnú n-tému číslu v postupnosti: Postupnosť začína číslom 1 a každé nasledujúce číslo je súčtom cifier všetkých predchádzajúcich čísel.

Postupnosť teda začína číslami: 1, 1, 2, 4, 8, 16, 23, 28, 38, 49... Avšak ak vstupné číslo n nie je kladné (je 0 a menej), funkcia vráti hodnotu 0.

Príklad použitia funkcie:

printf("%d\n", sum_digits_n(0));
// prints: 0
printf("%d\n", sum_digits_n(15));
// prints: 101

Úloha 3.6: Konštanta K

Naprogramujte funkciu int constant(const int a, const int b) s dvoma parametrami:

  • const int a - Veľkosť pozemku v metroch štvorcových
  • const int b - Číslo hnojiva

Konštanta K sa vypočíta podľa nasledujúcich pravidiel:

  • Na základe veľkosti pozemku a sa vypočíta a-te číslo v postupnosti ciferných súčtov (pomocou funkcie sum_digits_n()).
  • Ak číslo hnojiva b je z intervalu 1 <= b <= 9, potom sa na základe čísla hnojiva b nájde číslo A_n (pomocou funkcie find_A_n()). Z tohto výsledku sa následne vypočíta ciferný súčet (pomocou funkcie sum_digits()).
  • Ak číslo hnojiva b nie je z daného intervalu, potom sa namiesto neho použije druhá vstupná hodnota: Veľkosť pozemku a, na základe ktorej sa vypočíta a-te číslo v postupnosti ciferných súčtov (pomocou funkcie sum_digits_n()). Z tohto výsledku sa následne vypočíta ciferný súčet (pomocou funkcie sum_digits()).
  • Z týchto dvoch vypočítaných hodnôt sa následne vypočíta podiel tak, že väčšia z hodnôt sa vydelí menšou z hodnôt. Avšak desatinná časť je pri delení ignorovaná (výsledok je celočíselný).
  • Ak je vypočítaný podiel 49 a menej, potom je výpočet konštanty K ukončený.
  • Kým je vypočítaný výsledok 50 a viac, je potrebné ho ďalej upravovať:
  • Ak je výsledok párne číslo (even), vydelí sa číslom 2 a opäť sa zisťuje, či je tento výsledok menší ako 50.
  • Ak je výsledok nepárne číslo (odd), vypočíta sa jeho ciferný súčet a opäť sa zisťuje, či je tento výsledok menší ako 50.

Funkcia vráti hodnotu rovnú konštante K.

Príklad použitia funkcie:

printf("%d\n", constant(500,-15));
// prints: 26
printf("%d\n", constant(1234,4));
// prints: 14

Úloha 3.7: Supergrant

Ako sa už spomenulo vyššie, supergrant sa udeľuje na základe troch vstupných hodnôt: Veľkosť pozemku (a), číslo hnojiva (b) a požadovaná suma. O supergrant môžu požiadať len tí pestovatelia, ktorých pozemok má veľkosť 1 <= a <= 5000 metrov štvorcových, a zároveň používajú hnojivo s číslom -20 <= b <= 20. Každý uchádzač sa uchádza o inú sumu, ktorá musí byť aspoň 1000 EUR, ale nesmie byť viac ako 1000000 EUR.

Program začína načítaním troch celočíselných hodnôt: Veľkosť pozemku, číslo hnojiva, požadovaná suma. Program následne vypíše na obrazovku výšku prideleného supergrantu.

V prípade, že niektorá z hodnôt nie je z povoleného rozsahu, program vypíše hlášku Wrong input! a ihneď sa ukončí s návratovou hodnotou 1.

Pre pestovateľov, ktorí spĺňajú podmienky, sa vypočíta supergrant na základe konštanty K, ktorá predstavuje percento, o ktoré sa uchádzačovi zníži požadovaná suma supergrantu. Napr. ak je konštanta K rovná 1, potom sa uchádzačovi vyplatí 99% z požadovanej sumy. Výsledná suma supergrantu bude pestovateľovi oznámená v rámci výstupu programu (na obrazovke).

Príklady použitia

V nasledujúcom texte sa budú nachádzať príklady použitia programu. Text zvýraznený tučne bude predstavovať vstup od používateľa. Riadok začínajúci znakom '$' bude predstavovať príkazový riadok.

Ak je niektorá z hodnôt mimo povolený rozsah, program vypíše hlášku Wrong input! a končí s kódom 1:

$ ./supergrant
0 15 10000
Wrong input!
$ ./supergrant
500 22 10000
Wrong input!
$ ./supergrant
500 15 900
Wrong input!

Poznámka

Výstup programu končí novým riadkom '\n'.

Ak sú tri vstupné hodnoty v rámci povoleného rozsahu, program vypíše výšku supergrantu (s presnosťou na dve desatinné miesta) a končí s kódom 0:

$ ./supergrant
500 -20 1000000
Supergrant: 740000.00
$ ./supergrant
500 15 12345
Supergrant: 9135.30

Poznámka

Výstup programu končí novým riadkom '\n'.

Hodnotenie

Za správne vyriešenie úlohy môžete získať max. 4 body. Počet získaných bodov sa bude odrážať od výsledku testov, ktorými Vaše zadanie úspešne prejde. Overovať sa bude:

  • Výstup Vášho programu voči očakávanému výstupu.
  • Funkčnosť Vašej implementácie (jednotlivých funkcií).

Pri hodnotení sa ráta každý jeden znak!

Požiadavky pre úspešné odovzdanie zadania

  • Projekt musí byť odovzdaný včas v git repozitári na adrese git.kpi.fei.tuke.sk (viď nižšie).
  • Počas prekladu nemôže dôjsť ku žiadnej chybe! Projekt sa bude prekladať prekladačom gcc pomocou nasledovných prepínačov:
gcc -std=c11 -Werror -Wall -lm 
  • Vo výslednej implementácii sa nemôže nachádzať žiadna globálna premenná.

Odovzdávanie projektu

Zadanie odovzdajte do 02.12.2018. Posledné testovanie prebehne v tento deň o polnoci.

Zadanie sa odovzdáva prostredníctvom systému na správu verzií Git na serveri git.kpi.fei.tuke.sk.

Názov Vášho projektu musí byť v tvare: zap-2018.

Projekt musí mať nasledujúcu štruktúru priečinkov a súborov:

.
├── ps6
│   ├── farmers.c
│   ├── lunch.c
│   └── supergrant.c
└── README

Význam jednotlivých súborov je nasledovný:

  • README resp. README.md - Súbor, v ktorom bude uvedená Vaša skupina, ktorú navštevujete na cvičeniach v tvare:
GROUP : C1
  • /ps6/farmers.c - Zdrojový kód riešenia prvej úlohy - Nemeckí farmári.
  • /ps6/lunch.c - Zdrojový kód riešenia druhej úlohy - Obedy na TUKE.
  • /ps6/supergrant.c - Zdrojový kód riešenia tretej úlohy - Supergrant.

Upozornenie

Je dôležité, aby Vaše súbory zachovali uvedenú štruktúru. Ak sa niektorý zo súborov síce v repozitári nachádza, ale v inom priečinku, bude to považované za chybu a takýto projekt nebude považovaný za správny.

Upozornenie

Pri názvoch priečinkov, súborov a obsahu súboru README resp. README.md záleží na veľkosti písmen!

Poznámka

Ak sa vo Vašom projekte budú nachádzať ďalšie súbory okrem požadovaných, ich existencia nebude považovaná za chybu.

Hodnotenie a testovanie

Za zadanie môžete získať max. 8 bodov, z toho max. 2 body za prvú úlohu, max. 2 body za druhú úlohu a max. 4 body za tretiu úlohu. Počet získaných bodov sa bude odrážať od výsledku testov, ktorými Vaše zadanie úspešne prejde. Overovať sa bude:

  • Štruktúra Vášho projektu (či sa v ňom nachádzajú všetky potrebné súbory).
  • Funkčnosť Vašej implementácie.

Váš kód sa bude prekladať prekladačom gcc s nasledovnými prepínačmi:

gcc -std=c11 -Werror -Wall -lm

Za chybu sa bude považovať:

  • Ak vo Vašej implementácii použijete globálnu premennú.
  • Ak počas prekladu dôjde ku chybe (upozornenia sú priamo konvertované na chyby).
  • Ak Vaša implementácia neprejde niektorým z testov.

Testovanie Vašich riešení sa bude vykonávať automaticky každé 3 hodiny a to konkrétne o 0300, 0600, 0900, 1200, 1500, 1800, 2100 a 2400.

Vaše riešenia prejdú kontrolou originality. Preto sa pri práci na Vašom zadaní správajte podľa pravidiel etického kódexu! V prípade, že odovzdáte zadanie, ktoré nie je Vaše, môžete byť vylúčení z predmetu!

Doplňujúce zdroje

  1. What Every Computer Scientist Should Know About Floating-Point Arithmetic