Problem Set 6: Система дотаций

Objectives

  • Понять представление чисел в памяти компьютера.
  • Создать собственные функции согласно спецификации.
  • Научиться возвращать разные значения в функциях при различных параметрах на входе.

Task 1: Немецкие фермеры

Немецкие фермеры пользуются системой дотаций согласно условиям на их ферме. Представим следующее:

Нам известна площадь территории каждой фермы (кв. метрах) и количество животных, которые живут на каждой из ферм. Мы специально не будет разделять животных по видам (хоть это и далеко от реальности). Также нам известна информация, в какой мере каждый фермер использует инструменты экологии и принципы, представленная числом большим нуля. Размер финансовых средств, которые получает фермер, считается по такому принципу:

Сперва, нам нужно знать, сколько каждое животное занимает места на ферме (это значение округляется до двух знаков после запятой). Это значение (в квадратных метрах) затем умножается на параметр, который отражает экологический подход фермера. В результате мы получим столько, сколько каждый фермер получит за одно животное, которое у него есть. Чтобы рассчитать общую субсидию одного фермера, нам нужно умножить этот результат на количество животных, которые у него есть.

Напишите программу, которая будет представлять реализацию субсидионной системы для немецких фермеров.

Первым вступительным значением будет положительное число из интервала <0,20>, которое представляет общее количество фермеров. Для каждого из фермеров введём 3 положительных числа, которые представляют: Размер фермы в кв. метрах, количество животных на каждой из ферм и коэффициент экологического подхода фермера. Каждое из данных значений не может быть меньше 0 и больше 10000.

Если хотя бы одно из вступительных значений неверное, программа завершит работу с кодом 1 и сообщением Wrong input!.

В противном случае программа должна выписать только одно значение, соответствующее общей сумме субсидий для всех фермеров, затем завершив работу с кодом 0. Выписанное значение должно быть округлено до сотых

Comment

Вывод программы должен оканчиваться символом перевода строки '\n'.

Program Examples

Если одно из вступительных значений не соблюдает предписанный интервал, программа завершит свою работу с кодом 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!

Comment

Вывод программы должен оканчиваться символом перевода строки '\n'.

Если все вступительные значения правильные, программа выпишет значение, соответствующее сумме всех субсидий фермеров (с точностью до сотых), и завершит свою работу кодом 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

Comment

Вывод программы должен оканчиваться символом перевода строки '\n'.

Assessment

За данное задание можно получить max. 2 балла.

Warning

Оценивается каждый символ!

Task 2: Obedy na TUKE

Студенты и работники Технического университета в Кошице пользуются субсидиями согласно следующих правил:

  • Студенты:
    • Субсидия в размере 1 евро, если цена составляет хотя бы 2.00 евро, но меньше 4.00 евро.
    • Субсидия в размере 2 евро, если цена составляет хотя бы 4.00 евро.
  • Работники:
    • Право на получение субсидии возникает, если цена составляет хотя бы 1.80 евро.
    • Субсидия в размере 55% цены блюда + взнос из соцфонда, т.е. 0.42 евро.
    • Если работник выбирает себе обед дороже 3.60 евро, субсидия считается по-прежнему с 3.60 евро и остаток цены не подпадает под субсидирование до тех пор, пока цена не достигнет 5.40 евро. Система автоматически узнаёт последующие дотации до суммы 7.20 евро (т.е. 2x 3.60 евро как за два обеда за раз). Начиная с суммы 9.00 евро система бы узнала следующую субсидию и т.д.
    • В результате сумма округляется до сотых.

Напишите программу, которая послужит реализацией системы субсидий обедов для TUKE.

Программа сперва считает количество людей (обедов), для которых нужно рассчитать сумму субсидий. Данное число должно быть из интервала <0,20>. В противном случае, программа должна незамедлительно завершить свою работу с кодом 1 и сообщением Wrong input!.

Для каждого обеда затем должно считаться по два числа студент/работник и цена за обед: - Первое значение является 1 (в случае студента) или 2 (в случае сотрудника). - Второе значение должно составлять минимально 0.00, т.е. быть неотрицательным. - Если хоть одно из значений неверно, программа незамедлительно завершит свою работу с кодом 1 и сообщением Wrong input!.

После вводу всех нужных значений программа должна рассчитать общую сумму субсидий за обеды и сумму, которые все заплатили за еду за вычетом субсидий. Данные два числа программа должна вывести на экран с точностью до сотых.

Program Examples

Ниже приведены примеры использования программы. Текст, выделенный жирным шрифтом представляет ввод пользователя. Строка начинающаяся символом $ представляет командную строку.

В данном примере считаются суммы субсидий для троих людей (студент, работник и работник). Все вступительные значения правильные. У второго работника две субсидии:

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

Если любое из вступительных значение не соответствует предписанному формату, программа выведет на экран сообщение Wrong input! и завершит свою работу кодом 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!

Comment

Вывод программы должен оканчиваться символом перевода строки '\n'.

Assessment

За данное задание можно получить max. 2 балла.

Warning

Оценивается каждый символ!

Task 3: Supergrant

В Седьмом королевстве объявлен конкурс на получения супергранта для изготовителей культур.

Вашей задачей сперва является написать 6 функций:

  • int is_prime(const int number) - Проверка, является ли число number простым (prime number).
  • int next_prime(const int prime) - Найти на основе найденного просто числа prime следующее простое число.
  • long int find_A_n(const int n) - На основе данного числа n найти A_n.
  • int sum_digits(const long int number) - Найти сумму цифр числа number.
  • int sum_digits_n(const int n) - На основе данного числа n найти n-ное число в последовательности циферной суммы.
  • int constant(const int a, const int b) - Найти константу K супергранта.

Супергрант присуждается исходя из 3 заданных чисел: Площадь территории (a), количество удобрений (b) и нужная сумма. Соревноваться в получении супергранта могут только те производители, площадь территорий которых находится в 1 <= a <= 5000 кв. метров и количество используемых удобрений находится в -20 <= b <= 20. Каждый претендент претендует на разную сумму, составляющая минимум 1000 евро, но не может превышать 1000000 евро.

Вначале программа должна считать 3 целых числа: Размер территорий, количество удобрений, запрошенная сумма гранта. Затем программа должна вывести на экран сумму гранта.

В случае, если хотя бы одно из значений не соблюдает предписанный формат, программа закончит свою работу с кодом 1, выписав сообщение Wrong input!.

Производителям, соблюдающим условия участия, высчитается сумма супергранта на основе константы K, представляющая процент, на который уменьшится сумма запрошенного супергранта. Например, если константа K равняется 1, тогда претенденту должно быть выплачено 99% запрошенной суммы. Конечная сумма к выплате будет извещена производителю с точностью до сотых.

Task 3.1: Является ли числом простым?

Напишите функцию int is_prime(const int number) с параметром:

  • const int number - число, которое проверятся

Функция возвращает 1, если данное число number является простым (prime number). В противном случае функция вернёт 0.

Пример использования функции:

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

Task 3.2: Найти следующее простое число

Напишите функцию int next_prime(const int prime) с параметром:

  • const int prime - число, для которого нужно найти следующее простое

Функция возвращает ближайшее простое число (prime number) на основе простого числа prime. Но если данное число number не является простым (prime number), функция возвращает -1.

Пример использования функции:

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

Task 3.3: Найти A_n

Напишите функцию long int find_A_n(const int n) с параметром:

  • const int n - Число, на основе которого нужно найти A_n

Пусть A_n является наименьшим положительным числом (больше 1), которое соблюдает условие A_n mod p_i = i. Правдиво следующее:

  • 1 <= i <= n
  • p_i это такое просто число (prime number), которое является i-тое в последовательности, например, p_1 = 2, p_2 = 3 и т.д.
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

Функция возвращает целое число типа long int, которое соблюдает данное условие. В случае, если параметр n меньше 1, функция возвращает 0.

Пример использования функции:

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

Task 3.4: Сумма цифр

Напишите функцию int sum_digits(const long int number) с параметром:

  • const long int number - число, для которого считается сумма цифр

Функция возвращает число, равное сумму цифр данного на входе числа number. В случае, если данное число number является отрицательным (меньше 0), Функция возвращает 0.

Пример использования функции:

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

Task 3.5: Сумма цифр последовательности

Напишите функцию int sum_digits_n(const int n) с параметром:

  • const int n - число, для которого высчитается сумма последовательности цифр

Функция возвращает число, равное n-ному числу в последовательности: Последовательность начинается 1 и каждое следующее число является суммой цифр всех предыдущих чисел.

Так, последовательность начинается числами: 1, 1, 2, 4, 8, 16, 23, 28, 38, 49... В случае, если данное на входе число n не является положительнм ( 0 и меньше), Функция возвращает 0.

Пример использования функции:

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

Task 3.6: Константа K

Напишите функцию int constant(const int a, const int b) с двумя параметрами:

  • const int a - площадь территории в кв. метрах
  • const int b - количество удобрений

Константа K считается исходя из следующего:

  • На основе площади территории a высчитывается a-тое число в последовательности сумм цифр (благодаря функции sum_digits_n()).
  • Если количество удобрений b не находится в интервале 1 <= b <= 9, тогда на основе числа удобрений b высчитывается число A_n (благодаря функции find_A_n()). Из посчитанного результата вычитается сумма цифр (благодаря функции sum_digits()).
  • Если количество удобрений b не подпадает под указанный интервал, тогда вместо этого числа будет использоваться число из второго параметра: площадь территории a, на основе которой высчитается a-тое число в последовательности сумм цифр(благодаря функции sum_digits_n()). На основе данного числа впоследствии высчитается сумма цифр (благодаря функции sum_digits()).
  • Из двух высчитанных чисел высчитается доля таким образом, что большее из чисел поделится меньшим. При этом десятичная часть при делении игнорируется (результат является целым числом).
  • Если доля составляет 49 и меньше, в таком случае расчёт константы K закончен.
  • Если же результат составляет 50 и больше, тогда его следует изменить:
  • Если результат является парным числом (even), он должен быть поделён на 2, после чего снова проходит проверка, больше ли число, чем 50.
  • Если же результат - непарное число (odd), высчитывается сумма его цифр и снова проходит проверка, больше ли число, чем 50.

Функция возвращает число, равное константе K.

Пример использования функции:

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

Task 3.7: Supergrant

Как уже было упомянуто выше, супергрант присуждается исходя из 3 заданных чисел: Площадь территории (a), количество удобрений (b) и нужная сумма. Соревноваться в получении супергранта могут только те производители, площадь территорий которых находится в 1 <= a <= 5000 кв. метров и количество используемых удобрений находится в -20 <= b <= 20. Каждый претендент претендует на разную сумму, составляющая минимум 1000 евро, но не может превышать 1000000 евро.

Вначале программа должна считать 3 целых числа: Размер территорий, количество удобрений, запрошенная сумма гранта. Затем программа должна вывести на экран сумму гранта.

В случае, если хотя бы одно из значений не соблюдает предписанный формат, программа закончит свою работу с кодом 1, выписав сообщение Wrong input!.

Производителям, соблюдающим условия участия, высчитается сумма супергранта на основе константы K, представляющая процент, на который уменьшится сумма запрошенного супергранта. Например, если константа K равняется 1, тогда претенденту должно быть выплачено 99% запрошенной суммы. Конечная сумма к выплате будет извещена производителю с точностью до сотых.

Program Examples

Ниже приведены примеры использования программы. Текст, выделенный жирным шрифтом представляет ввод пользователя. Строка начинающаяся символом $ представляет командную строку.

Если любое из значений на входе неверное, программа завершает свою работу сообщением Wrong input! и кодом 1:

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

Comment

Вывод программы должен оканчиваться символом перевода строки '\n'.

Если 3 вступительных значения соблюдают предписанный формат, программа выведет на экран сумму супергранта (с точностью до сотых) и завершит работу кодом 0:

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

Comment

Вывод программы должен оканчиваться символом перевода строки '\n'.

Assessment

За полностью правильное решение задания можно получить max. 4 балла. Количество баллов зависит от результатов тестов, которые пройдёт ваша реализация программы, будут проверяться:

  • Вывод вашей программы с эталонным.
  • Сама функциональность (отдельных функций).

Оценивается каждый символ!

Minimal Requirements to Succeed

  • Проекта должен быть сдан не позднее дедлайна на git репозиторий git.kpi.fei.tuke.sk (см. ниже).
  • Во время компиляции недопустимы любые ошибки! Сборка проекта будет проводиться компилятором gcc со следующими аргументами:
gcc -std=c11 -Werror -Wall -lm 
  • В конечной реализации не должно быть ни одной глобальной переменной.

Project Submission

Задание сдайте не позднее 02.12.2018. Последние тесты будут запущены в полночь.

Задание сдаётся с помощью системы контроля версий Git на сервере git.kpi.fei.tuke.sk.

Название проекта должно быть точно в виде: zap-2018.

Проект должен сохранять иерархию файлов:

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

Отдельные файлы означают:

  • README соотв. README.md - файл, в котором указана группа, которую вы посещаете на практических занятиях:
GROUP : C1
  • /ps6/farmers.c - Код программы для задания - Немецкие фермеры.
  • /ps6/lunch.c - Код программы для задания úlohy - Обеды в TUKE.
  • /ps6/supergrant.c - Код программы для задания - Supergrant.

Warning

Важно, чтобы иерархия файлов соответствовала предписанной. Если какой-то из файлов находится в другом каталоге, это будет считаться ошибкой.

Warning

Соблюдайте регистр названия файлов README соотв. README.md.

Comment

Если в каталогах будут находиться другие файлы, ошибкой это считаться не будет.

Assessment and Testing

Задание оценивается max. 8 баллами, из них max. 2 балла за первое задание, max. 2 балла за второе и max. 4 балла за третье. Количество баллов будет зависеть от результатов тестов, будут проверяться:

  • Иерархия файлов (находятся ли в репозитории все нужные файлы).
  • Функционал вашей реализации.

Сборка будет осуществляться с помощью компилятора gcc со следующими параметрами:

gcc -std=c11 -Werror -Wall -lm

Ошибкой будет считаться:

  • Использование глобальной переменной.
  • Ошибки во время компиляции (предупреждения трактуются как ошибки).
  • Если ваша реализация не пройдёт каким-то из тестов.

Тестирование проектов будет проходить каждые 3 часа, а именно: 0300, 0600, 0900, 1200, 1500, 1800, 2100 и 2400.

Проекты пройдут проверку на плагиат, поэтому руководствуйтесь правилами этического кодекса! В случае выявления плагиата, вы рискуете быть выгнанными с предмета!

Additional Resources

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