├── week-01 ├── 05-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ └── sqr_all.cpp │ ├── README.md │ └── sqr_all.cpp ├── 02-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ └── blocks_weight.cpp │ ├── blocks_weight.cpp │ └── README.md ├── 01-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ └── temperature.cpp │ ├── temperature.cpp │ └── README.md ├── 06-Programming-Assignment │ ├── Solution │ │ └── element_reference.cpp │ ├── README.md │ └── element_reference.cpp ├── 03-Practice-Programming-Assignment │ ├── Solution │ │ └── find_max_repetition_count.cpp │ ├── README.md │ └── find_max_repetition_count.cpp └── 04-Programming-Assignment │ ├── Solution │ └── team_tasks.cpp │ ├── team_tasks.cpp │ └── README.md ├── week-03 ├── 04-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ └── code_decomposition.zip │ ├── project.tar.gz │ ├── Source │ │ └── main.cpp │ └── README.md ├── 01-Programming-Assignment │ ├── Source │ │ └── sum_reverse_sort.h │ ├── Solution │ │ └── sum_reverse_sort.cpp │ ├── sum_reverse_sort.cpp │ └── README.md ├── 03-Practice-Programming-Assignment │ ├── Solution │ │ └── rectangle.h │ ├── rectangle.h │ └── README.md └── 02-Programming-Assignment │ ├── Solution │ └── phone_number.cpp │ ├── Source │ └── phone_number.h │ ├── phone_number.cpp │ └── README.md ├── img └── 08-Yandex-291-1500_430-1500_430.jpg ├── week-04 ├── 07-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ ├── merge_sort_div2.cpp │ │ └── merge_sort_div3.cpp │ ├── merge_sort_div2.cpp │ ├── merge_sort_div3.cpp │ └── README.md ├── 03-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ └── split_into_words.cpp │ ├── split_into_words.cpp │ └── README.md ├── 05-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ └── print_permutations.cpp │ ├── README.md │ └── print_permutations.cpp ├── 04-Practice-Programming-Assignment │ ├── Solution │ │ └── remove_duplicates.cpp │ ├── remove_duplicates.cpp │ └── README.md ├── 02-Programming-Assignment │ ├── Solution │ │ ├── README.md │ │ └── find_greater_elements.cpp │ ├── README.md │ └── find_greater_elements.cpp ├── 01-Practice-Programming-Assignment │ ├── Solution │ │ └── print_vector_part.cpp │ ├── print_vector_part.cpp │ └── README.md ├── 10-Programming-Assignment │ ├── Solution │ │ ├── find_starts_with_string.cpp │ │ └── find_starts_with_char.cpp │ ├── find_starts_with_string.cpp │ ├── find_starts_with_char.cpp │ └── README.md ├── 08-Practice-Programming-Assignment │ ├── find_nearest_element.cpp │ ├── README.md │ └── Solution │ │ └── find_nearest_element.cpp ├── 11-Programming-Assignment │ ├── Solution │ │ ├── build_expression.cpp │ │ └── build_expression_without_redundant.cpp │ ├── build_expression.cpp │ ├── build_expression_without_redundant.cpp │ └── README.md ├── 09-Practice-Programming-Assignment │ ├── Solution │ │ └── person_names.cpp │ ├── person_names.cpp │ └── README.md └── 06-Practice-Programming-Assignment │ ├── Solution │ └── print_stats.cpp │ ├── print_stats.cpp │ └── README.md ├── README.md ├── week-05 ├── 01-Programming-Assignment │ ├── Solution │ │ └── inheritance.cpp │ ├── inheritance.cpp │ └── README.md ├── 04-Peer-graded-Assignment │ ├── README.md │ └── refactoring.cpp ├── 02-Practice-Programming-Assignment │ ├── Solution │ │ └── notifiers.cpp │ ├── notifiers.cpp │ └── README.md └── 03-Programming-Assignment │ ├── README.md │ ├── figures.cpp │ └── Solution │ └── figures.cpp └── week-02 ├── 02-Practice-Programming-Assignment ├── README.md ├── Source │ └── test_equation.cpp ├── test_equation.cpp └── Solution │ └── test_equation.cpp ├── 05-Programming-Assignment ├── README.md ├── Source │ └── test_palindrome.cpp ├── Solution │ └── test_palindrome.cpp └── test_palindrome.cpp ├── 04-Programming-Assignment ├── README.md ├── Source │ └── test_rational.cpp ├── test_rational.cpp └── Solution │ └── test_rational.cpp ├── 01-Programming-Assignment ├── Source │ └── starter.cpp ├── Solution │ └── starter.cpp ├── README.md └── starter.cpp └── 03-Practice-Programming-Assignment ├── README.md ├── Source └── test_person.cpp ├── Solution └── test_person.cpp └── test_person.cpp /week-01/05-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | Реализуем функцию Sqr для чисел, словарей, векторов и пар. -------------------------------------------------------------------------------- /week-03/04-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | Многофайловый проект приведён в архиве *code_decomposition.zip* -------------------------------------------------------------------------------- /img/08-Yandex-291-1500_430-1500_430.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/HEAD/img/08-Yandex-291-1500_430-1500_430.jpg -------------------------------------------------------------------------------- /week-04/07-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | В этой задаче достаточно аккуратно реализовать предложенный алгоритм, не ошибившись при использовании итераторов. -------------------------------------------------------------------------------- /week-03/04-Programming-Assignment/project.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/HEAD/week-03/04-Programming-Assignment/project.tar.gz -------------------------------------------------------------------------------- /week-03/04-Programming-Assignment/Solution/code_decomposition.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/HEAD/week-03/04-Programming-Assignment/Solution/code_decomposition.zip -------------------------------------------------------------------------------- /week-03/01-Programming-Assignment/Source/sum_reverse_sort.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int Sum(int x, int y); 8 | string Reverse(string s); 9 | void Sort(vector& nums); 10 | -------------------------------------------------------------------------------- /week-04/03-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | Идея решения заключается в итеративном поиске очередного пробела в строке. Как только он найден, его позиция задаёт конец очередного слова, которое можно добавить к ответу. Поиск следующего пробела будет продолжаться со следующей позиции. -------------------------------------------------------------------------------- /week-01/02-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | Главное, на что нужно было обратить внимание при решении задачи — корректный выбор целочисленных типов. Как следует из условия, максимально возможное значение массы равно 10^4 * 10^4 * 10^4 * 10^5 * 100 = 10^19, что умещается лишь в тип uint64_t. -------------------------------------------------------------------------------- /week-03/03-Practice-Programming-Assignment/Solution/rectangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Rectangle { 4 | public: 5 | Rectangle(int width, int height); 6 | 7 | int GetArea() const; 8 | int GetPerimeter() const; 9 | int GetWidth() const; 10 | int GetHeight() const; 11 | 12 | private: 13 | int width_, height_; 14 | }; 15 | -------------------------------------------------------------------------------- /week-01/01-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | При решении задачи необходимо было обратить внимание на два момента: 2 | 3 | * Сумма температур может достигать 10^14, поэтому должна храниться в типе int64_t. 4 | * Сумма температур может быть отрицательной, поэтому не должна делиться на беззнаковое число при вычислении среднего арифметического. -------------------------------------------------------------------------------- /week-04/05-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | Основная идея — использовать алгоритм *prev_permutation* для итеративного построения предыдущей перестановки по заданной. Его удобно обернуть в цикл *do while*. 2 | 3 | Кроме того, для инициализации первой перестановки используем алгоритмы *iota* (заполняющий диапазон числами от *1* до *n*) и reverse. -------------------------------------------------------------------------------- /week-04/04-Practice-Programming-Assignment/Solution/remove_duplicates.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | template 5 | void RemoveDuplicates(vector& elements) { 6 | sort(begin(elements), end(elements)); 7 | elements.erase( 8 | unique(begin(elements), end(elements)), 9 | elements.end()); 10 | } 11 | -------------------------------------------------------------------------------- /week-01/06-Programming-Assignment/Solution/element_reference.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | ValueType& GetRefStrict(map& input_map, KeyType key) { 6 | if (input_map.count(key) == 0) { 7 | throw runtime_error("no such key in dictionary"); 8 | } 9 | return input_map[key]; 10 | } 11 | -------------------------------------------------------------------------------- /week-03/01-Programming-Assignment/Solution/sum_reverse_sort.cpp: -------------------------------------------------------------------------------- 1 | #include "sum_reverse_sort.h" 2 | 3 | #include 4 | using namespace std; 5 | 6 | int Sum(int x, int y) { 7 | return x + y; 8 | } 9 | 10 | string Reverse(string s) { 11 | reverse(s.begin(), s.end()); 12 | return s; 13 | } 14 | 15 | void Sort(vector& nums) { 16 | sort(nums.begin(), nums.end()); 17 | } 18 | -------------------------------------------------------------------------------- /week-01/02-Programming-Assignment/blocks_weight.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | unsigned int n, r; 5 | std::cin >> n >> r; 6 | uint64_t w, h, d; 7 | uint64_t s = 0, m; 8 | 9 | for (int i = 0; i < n; ++i) { 10 | std::cin >> w >> h >> d; 11 | m = w * h * d * r; 12 | s += m; 13 | } 14 | std::cout << s; 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Основы разработки на C++: жёлтый пояс](https://www.coursera.org/learn/c-plus-plus-yellow) by Moscow Institute of Physics and Technology & Yandex 2 | 3 |

4 | 5 | 6 | 7 |

8 | -------------------------------------------------------------------------------- /week-04/02-Programming-Assignment/Solution/README.md: -------------------------------------------------------------------------------- 1 | Ключевой момент решения — поиск первого элемента, большего *border*. Позже мы научимся делать это оптимально, а пока достаточно использовать для этого обычный цикл *while*. 2 | 3 | Как только найден итератор на первый элемент, больший *border*, достаточно создать вектор из полуинтервала, начинающегося в этом итераторе и заканчивающегося в конце множества — это и будут все элементы, большие *border*, в возрастающем порядке. -------------------------------------------------------------------------------- /week-05/01-Programming-Assignment/Solution/inheritance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Animal { 7 | public: 8 | Animal(const string& name) 9 | : Name(name) 10 | {} 11 | 12 | const string Name; 13 | }; 14 | 15 | 16 | class Dog : public Animal { 17 | public: 18 | Dog(const string& name) 19 | : Animal(name) 20 | {} 21 | 22 | void Bark() { 23 | cout << Name << " barks: woof!" << endl; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /week-04/01-Practice-Programming-Assignment/Solution/print_vector_part.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void PrintVectorPart(const vector& numbers) { 8 | auto negative_it = find_if( 9 | numbers.begin(), numbers.end(), 10 | [](int number) { 11 | return number < 0; 12 | } 13 | ); 14 | 15 | for (auto it = negative_it; it != numbers.begin(); ) { 16 | cout << *(--it) << " "; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /week-03/01-Programming-Assignment/sum_reverse_sort.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by avtomato on 1/8/18. 3 | // 4 | 5 | #include 6 | 7 | #include 8 | 9 | 10 | int Sum(int x, int y) { 11 | return x + y; 12 | } 13 | 14 | string Reverse(string s) { 15 | string tmp = ""; 16 | for (size_t k = s.length(); k > 0; --k) { 17 | size_t i = k - 1; 18 | tmp += s[i]; 19 | } 20 | return tmp; 21 | } 22 | 23 | void Sort(vector& nums) { 24 | sort(begin(nums), end(nums)); 25 | } 26 | -------------------------------------------------------------------------------- /week-03/03-Practice-Programming-Assignment/rectangle.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by avtomato on 1/8/18. 3 | // 4 | 5 | #ifndef COURSERA_RECTANGLE_H 6 | #define COURSERA_RECTANGLE_H 7 | 8 | #endif //COURSERA_RECTANGLE_H 9 | #pragma once 10 | 11 | 12 | class Rectangle { 13 | public: 14 | explicit Rectangle(int width, int height); 15 | 16 | 17 | int GetArea() const; 18 | 19 | int GetPerimeter() const; 20 | 21 | int GetWidth() const; 22 | int GetHeight() const; 23 | 24 | private: 25 | int width_, height_; 26 | }; 27 | -------------------------------------------------------------------------------- /week-05/01-Programming-Assignment/inheritance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | 6 | class Animal { 7 | public: 8 | // ваш код 9 | Animal(const string& name = "animal") : Name(name) {} 10 | 11 | const string Name; 12 | }; 13 | 14 | 15 | class Dog : public Animal { 16 | public: 17 | // ваш код 18 | Dog(const string& name = "dog") : Animal(name) {} 19 | 20 | void Bark() { 21 | cout << Name << " barks: woof!" << endl; 22 | } 23 | }; 24 | 25 | 26 | int main() { 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /week-01/06-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Ссылка на элемент #### 2 | 3 | 4 | Реализуйте шаблонную функцию _GetRefStrict_, которая на вход принимает: _map_ и значение ключа _k_. Если элемент по ключу _k_ в коллекции отсутствует, то функция должна бросить исключение _runtime_error_, иначе вернуть ссылку на элемент в коллекции. 5 | 6 | Пример использования функции 7 | ```objectivec 8 | map m = {{0, "value"}}; 9 | string& item = GetRefStrict(m, 0); 10 | item = "newvalue"; 11 | cout << m[0] << endl; // выведет newvalue 12 | ``` -------------------------------------------------------------------------------- /week-04/05-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Перебор перестановок #### 2 | 3 | 4 | Дано целое положительное число *N*, не превышающее *9*. Выведите все перестановки чисел от *1* до *N* в обратном лексикографическом порядке (см. пример). 5 | ##### Пример ##### 6 | ###### Ввод ###### 7 | ```commandline 8 | 3 9 | ``` 10 | ###### Вывод ###### 11 | ```commandline 12 | 3 2 1 13 | 3 1 2 14 | 2 3 1 15 | 2 1 3 16 | 1 3 2 17 | 1 2 3 18 | ``` 19 | ##### Подсказка ##### 20 | Библиотека ** содержит готовые функции, позволяющие решить эту задачу. -------------------------------------------------------------------------------- /week-01/06-Programming-Assignment/element_reference.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | template 6 | Value& GetRefStrict(std::map& m, Key key) { 7 | try { 8 | return m.at(key); 9 | } catch (const std::out_of_range& oor) { 10 | throw std::runtime_error("Out of Range error"); 11 | } 12 | } 13 | 14 | 15 | int main() { 16 | std::map m = {{0, "value"}}; 17 | std::string& item = GetRefStrict(m, 0); 18 | item = "newvalue"; 19 | std::cout << m[0] << std::endl; // выведет newvalue 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /week-01/02-Programming-Assignment/Solution/blocks_weight.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int N, R; 8 | cin >> N >> R; 9 | uint64_t answer = 0; 10 | for (int i = 0; i < N; ++i) { 11 | int W, H, D; 12 | cin >> W >> H >> D; 13 | // Если не привести W к типу uint64_t перед умножением, 14 | // произведение будет иметь тип int и случится переполнение. 15 | // Альтернативное решение — хранить сами W, H, D в uint64_t 16 | answer += static_cast(W) * H * D; 17 | } 18 | answer *= R; 19 | cout << answer << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /week-04/02-Programming-Assignment/Solution/find_greater_elements.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | template 8 | vector FindGreaterElements(const set& elements, const T& border) { 9 | // Начнём итерироваться по множеству 10 | auto it = begin(elements); 11 | // Цель — найти первый элемент, больший border 12 | // Если итератор не достиг конца и указывает не туда, двигаем 13 | while (it != end(elements) && *it <= border) { 14 | ++it; 15 | } 16 | // Возвращаем вектор, созданный из элементов множества, начиная с it 17 | return {it, end(elements)}; 18 | } 19 | -------------------------------------------------------------------------------- /week-04/01-Practice-Programming-Assignment/print_vector_part.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | void PrintVectorPart(const std::vector& numbers) { 7 | auto it = std::find_if(std::begin(numbers), std::end(numbers), [](const int& num) { 8 | return num < 0; 9 | }); 10 | while (it-- != std::begin(numbers)) { 11 | std::cout << *it << " "; 12 | } 13 | std::cout << std::endl; 14 | } 15 | 16 | int main() { 17 | PrintVectorPart({6, 1, 8, -5, 4}); 18 | PrintVectorPart({-6, 1, 8, -5, 4}); // ничего не выведется 19 | PrintVectorPart({6, 1, 8, 5, 4}); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /week-01/03-Practice-Programming-Assignment/Solution/find_max_repetition_count.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | bool operator<(const Region& lhs, const Region& rhs) { 8 | return tie(lhs.std_name, lhs.parent_std_name, lhs.names, lhs.population) < 9 | tie(rhs.std_name, rhs.parent_std_name, rhs.names, rhs.population); 10 | } 11 | 12 | int FindMaxRepetitionCount(const vector& regions) { 13 | int result = 0; 14 | map repetion_count; 15 | for (const Region& region : regions) { 16 | result = max(result, ++repetion_count[region]); 17 | } 18 | return result; 19 | } 20 | -------------------------------------------------------------------------------- /week-05/01-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Наследование своими руками #### 2 | 3 | 4 | Дан следующий код: 5 | ```objectivec 6 | #include 7 | 8 | using namespace std; 9 | 10 | class Animal { 11 | public: 12 | // ваш код 13 | 14 | const string Name; 15 | }; 16 | 17 | 18 | class Dog { 19 | public: 20 | // ваш код 21 | 22 | void Bark() { 23 | cout << Name << " barks: woof!" << endl; 24 | } 25 | }; 26 | ``` 27 | Определите до конца тела классов, соблюдая следующие требования: 28 | 29 | 1. Класс *Dog* должен являться наследником класса *Animal*. 30 | 2. Конструктор класса *Dog* должен принимать параметр типа *string* и инициализировать им поле *Name* в классе *Animal*. -------------------------------------------------------------------------------- /week-01/01-Programming-Assignment/temperature.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | unsigned int n; 6 | int64_t sum = 0, average; 7 | std::cin >> n; 8 | std::vector temperature(n); 9 | 10 | for (int& t : temperature) { 11 | std::cin >> t; 12 | sum += t; 13 | } 14 | 15 | average = sum / static_cast(n); 16 | 17 | std::vector ids; 18 | for (int i = 0; i < temperature.size(); i++) { 19 | if (temperature[i] > average) { 20 | ids.push_back(i); 21 | } 22 | } 23 | 24 | std::cout << ids.size() << std::endl; 25 | for (const auto& id : ids) { 26 | std::cout << id << " "; 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /week-01/01-Programming-Assignment/Solution/temperature.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n; 8 | cin >> n; 9 | vector temperatures(n); 10 | int64_t sum = 0; 11 | for (int& temperature : temperatures) { 12 | cin >> temperature; 13 | sum += temperature; 14 | } 15 | 16 | int average = sum / n; 17 | 18 | vector above_average_indices; 19 | for (int i = 0; i < n; ++i) { 20 | if (temperatures[i] > average) { 21 | above_average_indices.push_back(i); 22 | } 23 | } 24 | 25 | cout << above_average_indices.size() << endl; 26 | for (int i : above_average_indices) { 27 | cout << i << " "; 28 | } 29 | cout << endl; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /week-04/05-Programming-Assignment/print_permutations.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main() { 7 | int n; 8 | std::cin >> n; 9 | std::vector input(n); 10 | for (int i = 0; i < n; ++i) { 11 | input[i] = i + 1; 12 | } 13 | 14 | std::vector> output; 15 | do { 16 | output.push_back({std::begin(input), std::end(input)}); 17 | } while(std::next_permutation(std::begin(input), std::end(input))); 18 | 19 | std::reverse(std::begin(output), std::end(output)); 20 | for (auto& vector : output) { 21 | for (auto& i : vector) { 22 | std::cout << i << " "; 23 | } 24 | std::cout << std::endl; 25 | } 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /week-02/02-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Тесты для функции GetDistinctRealRootCount #### 2 | 3 | 4 | Функция 5 | ```objectivec 6 | int GetDistinctRealRootCount(double a, double b, double c); 7 | ``` 8 | возвращает количество уникальных действительных корней уравнения *ax² + bx + c = 0*. Разработайте набор юнит-тестов для проверки корректности реализации этой функции. **Случай, когда все три коэффициента равны нулю, тестировать не надо**. 9 | 10 | Начать работу вы можете с шаблона, который содержит наш фреймворк юнит-тест и заготовку функции *GetDistinctRealRootCount*. 11 | 12 | [test_equation.cpp](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-02/02-Practice-Programming-Assignment/Source/test_equation.cpp) 13 | -------------------------------------------------------------------------------- /week-04/01-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Часть вектора #### 2 | 3 | 4 | Напишите функцию *PrintVectorPart*, принимающую вектор целых чисел *numbers*, выполняющую поиск первого отрицательного числа в нём и выводящую в стандартный вывод все числа, расположенные левее найденного, в обратном порядке. Если вектор не содержит отрицательных чисел, выведите все числа в обратном порядке. 5 | ```objectivec 6 | void PrintVectorPart(const vector& numbers); 7 | ``` 8 | ##### Пример кода ##### 9 | ```objectivec 10 | int main() { 11 | PrintVectorPart({6, 1, 8, -5, 4}); 12 | PrintVectorPart({-6, 1, 8, -5, 4}); // ничего не выведется 13 | PrintVectorPart({6, 1, 8, 5, 4}); 14 | return 0; 15 | } 16 | ``` 17 | ###### Вывод ###### 18 | ```commandline 19 | 8 1 6 20 | 21 | 4 5 8 1 6 22 | ``` -------------------------------------------------------------------------------- /week-04/07-Programming-Assignment/merge_sort_div2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | template 7 | void MergeSort(RandomIt range_begin, RandomIt range_end) { 8 | if (range_end - range_begin < 2) { 9 | return; 10 | } 11 | std::vector elements(range_begin, range_end); 12 | auto it = std::begin(elements) + elements.size() / 2; 13 | MergeSort(std::begin(elements), it); 14 | MergeSort(it, std::end(elements)); 15 | std::merge(std::begin(elements), it, it, std::end(elements), range_begin); 16 | } 17 | 18 | int main() { 19 | std::vector v = {6, 4, 7, 6, 4, 4, 0, 1}; 20 | MergeSort(begin(v), end(v)); 21 | for (int x : v) { 22 | std::cout << x << " "; 23 | } 24 | std::cout << std::endl; 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /week-04/02-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Часть множества #### 2 | 3 | 4 | Напишите шаблонную функцию *FindGreaterElements*, принимающую множество *elements* объектов типа *T* и ещё один объект *border* типа *T* и возвращающую вектор из всех элементов множества, бо́льших *border*, в возрастающем порядке. 5 | ```objectivec 6 | template 7 | vector FindGreaterElements(const set& elements, const T& border); 8 | ``` 9 | ##### Пример кода ##### 10 | ```objectivec 11 | int main() { 12 | for (int x : FindGreaterElements(set{1, 5, 7, 8}, 5)) { 13 | cout << x << " "; 14 | } 15 | cout << endl; 16 | 17 | string to_find = "Python"; 18 | cout << FindGreaterElements(set{"C", "C++"}, to_find).size() << endl; 19 | return 0; 20 | } 21 | ``` 22 | ###### Вывод ###### 23 | ```commandline 24 | 7 8 25 | 0 26 | ``` -------------------------------------------------------------------------------- /week-04/04-Practice-Programming-Assignment/remove_duplicates.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | template 7 | void RemoveDuplicates(std::vector& elements) { 8 | std::sort(std::begin(elements), std::end(elements)); 9 | auto it = std::unique(std::begin(elements), std::end(elements)); 10 | elements.erase(it, std::end(elements)); 11 | } 12 | 13 | int main() { 14 | std::vector v1 = {6, 4, 7, 6, 4, 4, 0, 1}; 15 | RemoveDuplicates(v1); 16 | for (int x : v1) { 17 | std::cout << x << " "; 18 | } 19 | std::cout << std::endl; 20 | 21 | std::vector v2 = {"C", "C++", "C++", "C", "C++"}; 22 | RemoveDuplicates(v2); 23 | for (const std::string& s : v2) { 24 | std::cout << s << " "; 25 | } 26 | std::cout << std::endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /week-04/10-Programming-Assignment/Solution/find_starts_with_string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | template 7 | pair FindStartsWith( 8 | RandomIt range_begin, RandomIt range_end, string prefix) { 9 | 10 | // Все строки, начинающиеся с prefix, больше или равны строке "" 11 | auto left = lower_bound(range_begin, range_end, prefix); 12 | 13 | // Составим строку, которая в рамках буквенных строк является 14 | // точной верхней гранью множества строк, начинающихся с prefix 15 | string upper_bound = prefix; 16 | ++upper_bound[upper_bound.size() - 1]; 17 | 18 | // Первое встреченное слово, не меньшее upper_bound, 19 | // обязательно является концом полуинтервала 20 | auto right = lower_bound(range_begin, range_end, upper_bound); 21 | 22 | return {left, right}; 23 | } 24 | -------------------------------------------------------------------------------- /week-05/04-Peer-graded-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание, оцениваемое сокурсниками: Грамотно рефакторим код #### 2 | 3 | 4 | В данном задании вам предстоит изменить код таким образом, чтобы он соответствовал изложенным в курсе принципам. 5 | 6 | Представьте, что этот код вам достался в наследство от коллеги и теперь вам предстоит поддерживать его и улучшать. Первое, что вы решили сделать — это провести рефакторинг. 7 | 8 | Конечние цели рефакторинга: 9 | * упростить дальнейшую поддержку кода; 10 | * уменьшить сложность кода; 11 | * упростить добавление новых абстракций в программу. 12 | 13 | **Review criteria** 14 | 15 | Задание будет оцениваться по следующим критериям: 16 | 17 | * эффективность выполнения кода; 18 | * задублированность кода; 19 | * эффективность использования приёмов рефакторинга кода, показанных в лекциях. 20 | 21 | Кроме того, присылаемый вами код должен компилироваться. -------------------------------------------------------------------------------- /week-04/02-Programming-Assignment/find_greater_elements.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | template 8 | std::vector FindGreaterElements(const std::set& elements, const T& border) { 9 | auto it = std::find_if(std::begin(elements), std::end(elements), [border](const T& elem) { 10 | return elem > border; 11 | }); 12 | std::vector tmp; 13 | for (auto i = it; i != std::end(elements); ++i) { 14 | tmp.push_back(*i); 15 | } 16 | return tmp; 17 | } 18 | 19 | int main() { 20 | for (int x : FindGreaterElements(std::set{1, 5, 7, 8}, 5)) { 21 | std::cout << x << " "; 22 | } 23 | std::cout << std::endl; 24 | 25 | std::string to_find = "Python"; 26 | std::cout << FindGreaterElements(std::set{"C", "C++"}, to_find).size() << std::endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /week-03/03-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Написать объявление класса #### 2 | 3 | 4 | Вам дано полное определение класса *Rectangle* 5 | ```objectivec 6 | class Rectangle { 7 | public: 8 | Rectangle(int width, int height) : width_(width), height_(height) 9 | { 10 | } 11 | 12 | int GetArea() const { 13 | return width_ * height_; 14 | } 15 | 16 | int GetPerimeter() const { 17 | return 2 * (width_ + height_); 18 | } 19 | 20 | int GetWidth() const { return width_; } 21 | int GetHeight() const { return height_; } 22 | 23 | private: 24 | int width_, height_; 25 | }; 26 | 27 | ``` 28 | Пришлите заголовочный файл *rectangle.h*, содержащий объявление класса *Rectangle*. Это должен быть полноценный заголовочный файл, который можно использовать в большом проекте. В частности, в нём должна быть решена проблема двойного включения. -------------------------------------------------------------------------------- /week-04/10-Programming-Assignment/Solution/find_starts_with_char.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | template 7 | pair FindStartsWith( 8 | RandomIt range_begin, RandomIt range_end, char prefix) { 9 | 10 | // Все строки, начинающиеся с '', больше или равны строке "" 11 | auto left = lower_bound(range_begin, range_end, string(1, prefix)); 12 | 13 | // Составим следующий в алфавите символ. 14 | // Не страшно, если prefix = 'z': 15 | // в этом случае мы получим следующий за 'z' символ в таблице символов 16 | char next_prefix = static_cast(prefix + 1); 17 | 18 | // Строка "" в рамках буквенных строк 19 | // является точной верхней гранью 20 | // множества строк, начнающихся с '' 21 | auto right = lower_bound(range_begin, range_end, string(1, next_prefix)); 22 | 23 | return {left, right}; 24 | } 25 | -------------------------------------------------------------------------------- /week-04/07-Programming-Assignment/Solution/merge_sort_div2.cpp: -------------------------------------------------------------------------------- 1 | template 2 | void MergeSort(RandomIt range_begin, RandomIt range_end) { 3 | // 1. Если диапазон содержит меньше 2 элементов, выходим из функции 4 | int range_length = range_end - range_begin; 5 | if (range_length < 2) { 6 | return; 7 | } 8 | 9 | // 2. Создаем вектор, содержащий все элементы текущего диапазона 10 | vector elements(range_begin, range_end); 11 | 12 | // 3. Разбиваем вектор на две равные части 13 | auto mid = elements.begin() + range_length / 2; 14 | 15 | // 4. Вызываем функцию MergeSort от каждой половины вектора 16 | MergeSort(elements.begin(), mid); 17 | MergeSort(mid, elements.end()); 18 | 19 | // 5. С помощью алгоритма merge сливаем отсортированные половины 20 | // в исходный диапазон 21 | // merge -> http://ru.cppreference.com/w/cpp/algorithm/merge 22 | merge(elements.begin(), mid, mid, elements.end(), range_begin); 23 | } 24 | -------------------------------------------------------------------------------- /week-04/03-Programming-Assignment/split_into_words.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | std::vector SplitIntoWords(const std::string& s) { 7 | std::vector tmp; 8 | auto first_char = std::begin(s); 9 | for (auto it = std::begin(s); it != std::end(s); ++it) { 10 | if (*it == *std::find(it, std::end(s), ' ')) { 11 | tmp.push_back({first_char, it}); 12 | first_char = ++it; 13 | } 14 | } 15 | tmp.push_back({first_char, std::end(s)}); 16 | return tmp; 17 | } 18 | 19 | int main() { 20 | std::string s = "C Cpp Java Python"; 21 | 22 | std::vector words = SplitIntoWords(s); 23 | std::cout << words.size() << " "; 24 | for (auto it = begin(words); it != end(words); ++it) { 25 | if (it != begin(words)) { 26 | std::cout << "/"; 27 | } 28 | std::cout << *it; 29 | } 30 | std::cout << std::endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /week-04/07-Programming-Assignment/merge_sort_div3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | template 7 | void MergeSort(RandomIt range_begin, RandomIt range_end) { 8 | if (range_end - range_begin < 3) { 9 | return; 10 | } 11 | std::vector elements(range_begin, range_end); 12 | auto it1 = std::begin(elements) + elements.size() / 3; 13 | auto it2 = it1 + elements.size() / 3; 14 | 15 | MergeSort(std::begin(elements), it1); 16 | MergeSort(it1, it2); 17 | MergeSort(it2, std::end(elements)); 18 | 19 | std::vector tmp; 20 | 21 | std::merge(std::begin(elements), it1, it1, it2, std::back_inserter(tmp)); 22 | std::merge(tmp.begin(), tmp.end(), it2, std::end(elements), range_begin); 23 | } 24 | 25 | int main() { 26 | std::vector v = {6, 4, 7, 6, 4, 4, 0, 1, 5}; 27 | MergeSort(begin(v), end(v)); 28 | for (int x : v) { 29 | std::cout << x << " "; 30 | } 31 | std::cout << std::endl; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /week-01/02-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Масса блоков #### 2 | 3 | 4 | Вычислите суммарную массу имеющих форму прямоугольного параллелепипеда бетонных блоков одинаковой плотности, но разного размера. 5 | 6 | ##### Указание ##### 7 | Считайте, что размеры блоков измеряются в сантиметрах, плотность — в граммах на кубический сантиметр, а итоговая масса — в граммах. Таким образом, массу блока можно вычислять как простое произведение плотности на объём. 8 | 9 | ##### Формат ввода ##### 10 | В первой строке вводятся два целых положительных числа: количество блоков _N_ и плотность каждого блока _R_. Каждая из следующих _N_ строк содержит три целых положительных числа _W_, _H_, _D_ — размеры очередного блока. 11 | 12 | Гарантируется, что: 13 | 14 | * количество блоков _N_ не превосходит 10^5; 15 | * плотность блоков _R_ не превосходит 100; 16 | * размеры блоков _W_, _H_, _D_ не превосходят 10^4. 17 | 18 | ##### Пример ##### 19 | 20 | ###### Ввод ####### 21 | ```commandline 22 | 2 14 23 | 1 2 3 24 | 30 40 50 25 | ``` 26 | 27 | ###### Вывод ###### 28 | ```commandline 29 | 840084 30 | ``` -------------------------------------------------------------------------------- /week-03/02-Programming-Assignment/Solution/phone_number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "phone_number.h" 5 | 6 | using namespace std; 7 | 8 | PhoneNumber::PhoneNumber(const string& international_number) { 9 | istringstream is(international_number); 10 | 11 | char sign = is.get(); 12 | getline(is, country_code_, '-'); 13 | getline(is, city_code_, '-'); 14 | getline(is, local_number_); 15 | 16 | if (sign != '+' || country_code_.empty() || city_code_.empty() || local_number_.empty()) { 17 | throw invalid_argument("Phone number must begin with '+' symbol and contain 3 parts separated by '-' symbol: " + international_number); 18 | } 19 | } 20 | 21 | string PhoneNumber::GetCountryCode() const { 22 | return country_code_; 23 | } 24 | 25 | string PhoneNumber::GetCityCode() const { 26 | return city_code_; 27 | } 28 | 29 | string PhoneNumber::GetLocalNumber() const { 30 | return local_number_; 31 | } 32 | 33 | string PhoneNumber::GetInternationalNumber() const { 34 | return ("+" + country_code_ + "-" + city_code_ + "-" + local_number_); 35 | } 36 | -------------------------------------------------------------------------------- /week-04/04-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Удаление повторов #### 2 | 3 | 4 | Напишите шаблонную функцию *RemoveDuplicates*, принимающую по ссылке вектор *elements* объектов типа *T* и удаляющую из него все дубликаты элементов. Порядок оставшихся элементов может быть любым. 5 | 6 | Гарантируется, что объекты типа *T* можно сравнивать с помощью операторов ==, !=, < и >. 7 | ```objectivec 8 | template 9 | void RemoveDuplicates(vector& elements); 10 | ``` 11 | ##### Пример кода ##### 12 | ```objectivec 13 | int main() { 14 | vector v1 = {6, 4, 7, 6, 4, 4, 0, 1}; 15 | RemoveDuplicates(v1); 16 | for (int x : v1) { 17 | cout << x << " "; 18 | } 19 | cout << endl; 20 | 21 | vector v2 = {"C", "C++", "C++", "C", "C++"}; 22 | RemoveDuplicates(v2); 23 | for (const string& s : v2) { 24 | cout << s << " "; 25 | } 26 | cout << endl; 27 | return 0; 28 | } 29 | ``` 30 | ###### Вывод ###### 31 | ```commandline 32 | 6 4 7 0 1 33 | C++ C 34 | ``` 35 | Порядок элементов может быть другим, например: 36 | ```commandline 37 | 7 4 6 1 0 38 | C C++ 39 | ``` -------------------------------------------------------------------------------- /week-03/01-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Реализовать функции, объявленные в заголовочном файле #### 2 | 3 | 4 | Вам дан заголовочный файл *sum_reverse_sort.h*, содержащий объявления трёх функций 5 | 6 | [sum_reverse_sort.h](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-03/01-Programming-Assignment/Source/sum_reverse_sort.h) 7 | 8 | ```objectivec 9 | #pragma once 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | int Sum(int x, int y); 16 | string Reverse(string s); 17 | void Sort(vector& nums); 18 | 19 | ``` 20 | Вам надо прислать *cpp*-файл, содержащий определения этих функций. 21 | 22 | ##### Как будет тестироваться ваш код ##### 23 | Автоматическая тестирующая система добавит ваш *cpp*-файл в проект, содержащий другой *cpp*-файл с юнит-тестами для всех трёх функций, а также файл *sum_reverse_sort.h*. Затем она соберёт этот проект и, если компиляция будет выполнена успешно, запустит получившийся исполняемый файл. Если он завершится успешно (т. е. юнит-тесты не найдут ошибок в вашей реализации), то ваша посылка будет засчитана. 24 | -------------------------------------------------------------------------------- /week-04/08-Practice-Programming-Assignment/find_nearest_element.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // set::const_iterator — 6 | // тип итераторов для константного множества целых чисел 7 | std::set::const_iterator FindNearestElement( 8 | const std::set& numbers, 9 | int border) { 10 | auto nearest = numbers.lower_bound(border); 11 | if (nearest != std::begin(numbers)) { 12 | if (abs(*nearest - border) >= abs(border - *std::prev(nearest))) { 13 | return std::prev(nearest); 14 | } 15 | } 16 | return nearest; 17 | } 18 | 19 | 20 | int main() { 21 | std::set numbers = {1, 4, 6}; 22 | std::cout << 23 | *FindNearestElement(numbers, 0) << " " << 24 | *FindNearestElement(numbers, 3) << " " << 25 | *FindNearestElement(numbers, 5) << " " << 26 | *FindNearestElement(numbers, 6) << " " << 27 | *FindNearestElement(numbers, 100) << std::endl; 28 | 29 | std::set empty_set; 30 | 31 | std::cout << (FindNearestElement(empty_set, 8) == end(empty_set)) << std::endl; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /week-04/03-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Разбиение на слова #### 2 | 3 | 4 | Напишите функцию *SplitIntoWords*, разбивающую строку на слова по пробелам. 5 | ```objectivec 6 | vector SplitIntoWords(const string& s); 7 | ``` 8 | Гарантируется, что: 9 | * строка непуста; 10 | * строка состоит лишь из латинских букв и пробелов; 11 | * первый и последний символы строки не являются пробелами; 12 | * строка не содержит двух пробелов подряд. 13 | 14 | ##### Подсказка ##### 15 | Рекомендуется следующий способ решения задачи: 16 | * искать очередной пробел с помощью алгоритма find; 17 | * создавать очередное слово с помощью конструктора строки по двум итераторам. 18 | 19 | ##### Пример кода ##### 20 | ```objectivec 21 | int main() { 22 | string s = "C Cpp Java Python"; 23 | 24 | vector words = SplitIntoWords(s); 25 | cout << words.size() << " "; 26 | for (auto it = begin(words); it != end(words); ++it) { 27 | if (it != begin(words)) { 28 | cout << "/"; 29 | } 30 | cout << *it; 31 | } 32 | cout << endl; 33 | 34 | return 0; 35 | } 36 | ``` 37 | ###### Вывод ###### 38 | ```commandline 39 | С/Cpp/Java/Python 40 | ``` -------------------------------------------------------------------------------- /week-04/08-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Поиск ближайшего элемента #### 2 | 3 | 4 | Напишите функцию *FindNearestElement*, для множества целых чисел *numbers* и данного числа *border* возвращающую итератор на элемент множества, ближайший к *border*. Если ближайших элементов несколько, верните итератор на наименьший из них. 5 | ```objectivec 6 | set::const_iterator FindNearestElement( 7 | const set& numbers, 8 | int border); 9 | // set::const_iterator — 10 | // тип итераторов для константного множества целых чисел 11 | ``` 12 | ##### Пример кода ##### 13 | ```objectivec 14 | int main() { 15 | set numbers = {1, 4, 6}; 16 | cout << 17 | *FindNearestElement(numbers, 0) << " " << 18 | *FindNearestElement(numbers, 3) << " " << 19 | *FindNearestElement(numbers, 5) << " " << 20 | *FindNearestElement(numbers, 6) << " " << 21 | *FindNearestElement(numbers, 100) << endl; 22 | 23 | set empty_set; 24 | 25 | cout << (FindNearestElement(empty_set, 8) == end(empty_set)) << endl; 26 | return 0; 27 | } 28 | ``` 29 | ###### Вывод ###### 30 | ```commandline 31 | 1 4 4 6 6 32 | 1 33 | ``` -------------------------------------------------------------------------------- /week-03/02-Programming-Assignment/Source/phone_number.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | using namespace std; 6 | 7 | class PhoneNumber { 8 | public: 9 | /* Принимает строку в формате +XXX-YYY-ZZZZZZ 10 | Часть от '+' до первого '-' - это код страны. 11 | Часть между первым и вторым символами '-' - код города 12 | Всё, что идёт после второго символа '-' - местный номер. 13 | Код страны, код города и местный номер не должны быть пустыми. 14 | Если строка не соответствует этому формату, нужно выбросить исключение invalid_argument. Проверять, что номер содержит только цифры, не нужно. 15 | 16 | Примеры: 17 | * +7-495-111-22-33 18 | * +7-495-1112233 19 | * +323-22-460002 20 | * +1-2-coursera-cpp 21 | * 1-2-333 - некорректный номер - не начинается на '+' 22 | * +7-1233 - некорректный номер - есть только код страны и города 23 | */ 24 | explicit PhoneNumber(const string &international_number); 25 | 26 | string GetCountryCode() const; 27 | string GetCityCode() const; 28 | string GetLocalNumber() const; 29 | string GetInternationalNumber() const; 30 | 31 | private: 32 | string country_code_; 33 | string city_code_; 34 | string local_number_; 35 | }; 36 | -------------------------------------------------------------------------------- /week-04/11-Programming-Assignment/Solution/build_expression.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // Определим структуру для удобной организации данных 9 | struct Operation { 10 | // Параметры по умолчанию нужны для конструирования вектора 11 | // ненулевого размера (*) 12 | char type = 0; 13 | int number = 0; 14 | }; 15 | 16 | int main() { 17 | int initial_number; 18 | cin >> initial_number; 19 | 20 | int number_of_operations; 21 | cin >> number_of_operations; 22 | vector operations(number_of_operations); // (*) 23 | for (int i = 0; i < number_of_operations; ++i) { 24 | cin >> operations[i].type; 25 | cin >> operations[i].number; 26 | } 27 | 28 | deque expression; 29 | expression.push_back(to_string(initial_number)); 30 | for (const auto& operation : operations) { 31 | expression.push_front("("); 32 | expression.push_back(") "); 33 | expression.push_back(string(1, operation.type)); 34 | expression.push_back(" "); 35 | expression.push_back(to_string(operation.number)); 36 | } 37 | 38 | for (const string& s : expression) { 39 | cout << s; 40 | } 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /week-04/05-Programming-Assignment/Solution/print_permutations.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | int range_length; 10 | cin >> range_length; 11 | vector permutation(range_length); 12 | 13 | // iota -> http://ru.cppreference.com/w/cpp/algorithm/iota 14 | // Заполняет диапазон последовательно возрастающими значениями 15 | iota(permutation.begin(), permutation.end(), 1); 16 | 17 | // reverse -> http://ru.cppreference.com/w/cpp/algorithm/reverse 18 | // Меняет порядок следования элементов в диапазоне на противоположный 19 | reverse(permutation.begin(), permutation.end()); 20 | 21 | // prev_permutation -> 22 | // http://ru.cppreference.com/w/cpp/algorithm/prev_permutation 23 | // Преобразует диапазон в предыдущую (лексикографически) перестановку, 24 | // если она существует, и возвращает true, 25 | // иначе (если не существует) - в последнюю (наибольшую) и возвращает false 26 | do { 27 | for (int num : permutation) { 28 | cout << num << ' '; 29 | } 30 | cout << endl; 31 | } while (prev_permutation(permutation.begin(), permutation.end())); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /week-04/09-Practice-Programming-Assignment/Solution/person_names.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Возвращает пустую строку, если имя неизвестно 5 | string FindNameByYear(const map& names, int year) { 6 | auto iter_after = names.upper_bound(year); 7 | string name; 8 | if (iter_after != names.begin()) { 9 | name = (--iter_after)->second; 10 | } 11 | return name; 12 | } 13 | 14 | class Person { 15 | public: 16 | void ChangeFirstName(int year, const string& first_name) { 17 | first_names[year] = first_name; 18 | } 19 | void ChangeLastName(int year, const string& last_name) { 20 | last_names[year] = last_name; 21 | } 22 | string GetFullName(int year) { 23 | const string first_name = FindNameByYear(first_names, year); 24 | const string last_name = FindNameByYear(last_names, year); 25 | if (first_name.empty() && last_name.empty()) { 26 | return "Incognito"; 27 | } else if (first_name.empty()) { 28 | return last_name + " with unknown first name"; 29 | } else if (last_name.empty()) { 30 | return first_name + " with unknown last name"; 31 | } else { 32 | return first_name + " " + last_name; 33 | } 34 | } 35 | private: 36 | map first_names; 37 | map last_names; 38 | }; 39 | -------------------------------------------------------------------------------- /week-04/08-Practice-Programming-Assignment/Solution/find_nearest_element.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | set::const_iterator FindNearestElement(const set& numbers, 5 | int border) { 6 | // Запрашиваем итератор на первый элемент, не меньший border; 7 | // если такого элемента нет, то мы получим numbers.end() 8 | // set::lower_bound -> 9 | // http://ru.cppreference.com/w/cpp/container/set/lower_bound 10 | const auto first_not_less = numbers.lower_bound(border); 11 | 12 | // Если множество пусто или до первого элемента не меньше border 13 | // нет элементов, то мы уже получили ответ 14 | if (first_not_less == numbers.begin()) { 15 | return first_not_less; 16 | } 17 | 18 | // Если элементов, не меньших border, нет и set не пуст, то достаточно взять 19 | // итератор на последний элемент, меньший border 20 | // prev -> http://ru.cppreference.com/w/cpp/iterator/prev 21 | const auto last_less = prev(first_not_less); 22 | if (first_not_less == numbers.end()) { 23 | return last_less; 24 | } 25 | 26 | // Разыменуем оба итератора-кандидата и выберем тот, 27 | // чей элемент ближе к искомому 28 | const bool is_left = (border - *last_less <= *first_not_less - border); 29 | return is_left ? last_less : first_not_less; 30 | } 31 | -------------------------------------------------------------------------------- /week-04/03-Programming-Assignment/Solution/split_into_words.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector SplitIntoWords(const string& str) { 8 | // Готовим вектор, в который будем сохранять слова 9 | vector result; 10 | 11 | // Эти два итератора будут ограничивать текущую не разбитую часть строки 12 | // str_begin будет двигаться вправо 13 | auto str_begin = begin(str); 14 | // str_end всегда будет указывать на конец строки (поэтому он константный) 15 | const auto str_end = end(str); 16 | 17 | // У цикла нет условия завершения, так что единственный способ закончить его — 18 | // сделать break 19 | while (true) { 20 | 21 | // Находим первый пробел в текущем «хвосте» строки 22 | auto it = find(str_begin, str_end, ' '); 23 | 24 | // Полуинтервал [str_begin, it) — очередное слово 25 | result.push_back(string(str_begin, it)); 26 | 27 | if (it == str_end) { 28 | // Если пробелов больше нет, цикл пора завершить. 29 | // Последнее слово уже добавлено 30 | break; 31 | } else { 32 | // Иначе первый символ после пробела — начало очередного слова. 33 | // Туда и подвинем str_begin 34 | str_begin = it + 1; 35 | } 36 | 37 | } 38 | 39 | return result; 40 | } 41 | -------------------------------------------------------------------------------- /week-01/01-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Средняя температура — 2 #### 2 | 3 | 4 | _Решите задачу «[Средняя температура](https://www.coursera.org/learn/c-plus-plus-white/programming/oGdDI/sriedniaia-tiempieratura)» в других ограничениях на входные данные_. 5 | 6 | Даны значения температуры, наблюдавшиеся в течение N подряд идущих дней. Найдите номера дней (в нумерации с нуля) со значением температуры выше среднего арифметического за все N дней. 7 | 8 | Гарантируется, что среднее арифметическое значений температуры является целым числом. 9 | 10 | ##### Формат ввода ##### 11 | 12 | Вводится число N, затем N целых чисел — значения температуры в 0-й, 1-й, ... (N−1)-й день. Гарантируется, что N не превышает миллиона (10^6), а значения температуры, измеряющиеся в миллионных долях градусов по Цельсию, лежат в диапазоне от −10^8 до 10^8. Проверять соблюдение этих ограничений не нужно: вы можете ориентироваться на них при выборе наиболее подходящих типов для переменных. 13 | 14 | ##### Формат вывода ##### 15 | 16 | Первое число K — количество дней, значение температуры в которых выше среднего арифметического. Затем K целых чисел — номера этих дней. 17 | 18 | ##### Пример ##### 19 | 20 | ###### Ввод ####### 21 | ```commandline 22 | 5 23 | 5 4 1 -2 7 24 | ``` 25 | 26 | ###### Вывод ###### 27 | ```commandline 28 | 3 29 | 0 1 4 30 | ``` -------------------------------------------------------------------------------- /week-01/05-Programming-Assignment/Solution/sqr_all.cpp: -------------------------------------------------------------------------------- 1 | // Объявим функции без тела, 2 | // чтобы их можно было использовать в произвольном порядке 3 | 4 | // Для простых типов 5 | template 6 | T Sqr(T value); 7 | 8 | // Для вектора 9 | template 10 | vector Sqr(const vector& value); 11 | 12 | // Для словаря 13 | template 14 | map Sqr(const map& value); 15 | 16 | // Для пары 17 | template 18 | pair Sqr(const pair& value); 19 | 20 | // Теперь реализуем их в соответствии с заданием 21 | template 22 | T Sqr(T value) { 23 | return value * value; 24 | } 25 | 26 | template 27 | vector Sqr(const vector& value) { 28 | vector result; 29 | for (const T& x : value) { 30 | // Здесь важно, что вместо x * x вызывается функция Sqr: 31 | // это позволяет возводить в квадрат составные объекты 32 | result.push_back(Sqr(x)); 33 | } 34 | 35 | return result; 36 | } 37 | 38 | template 39 | map Sqr(const map& value) { 40 | map result; 41 | for (const auto& element : value) { 42 | result[element.first] = Sqr(element.second); 43 | } 44 | return result; 45 | } 46 | 47 | template 48 | pair Sqr(const pair& value) { 49 | return {Sqr(value.first), Sqr(value.second)}; 50 | } 51 | -------------------------------------------------------------------------------- /week-02/05-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Тесты для функции IsPalindrom #### 2 | 3 | 4 | В этой задаче вам нужно разработать набор юнит-тестов для функции 5 | ```objectivec 6 | bool IsPalindrom(const string& s) 7 | ``` 8 | Эта функция проверяет, является ли строка s палиндромом. Палиндром — это слово или фраза, которые одинаково читаются слева направо и справа налево. Примеры палиндромов: **madam, level, wasitacaroracatisaw** 9 | 10 | Разработайте набор юнит-тестов, который будет принимать правильные реализации функции _IsPalindrom_ и отвергать неправильные. При этом учитывайте, что __правильная__ реализация функции: 11 | 12 | * считает пустую строку палиндромом; 13 | * считает строку из одного символа палиндромом; 14 | * осуществляет обычное сравнение символов на равенство, не игнорируя никакие символы, в том числе пробельные. 15 | 16 | При разработке тестов подумайте, какие ошибки можно допустить при реализации функции _IsPalindrom_. Примеры ошибок: 17 | 18 | * игнорируется первый или последний символ; 19 | * сравнение соответствующих символов завершается не в середине строки, а раньше; 20 | * игнорируются пробелы 21 | 22 | Начать работу вы можете с шаблона, который содержит наш фреймворк юнит-тестов и заготовку функции _IsPalindrom_. 23 | 24 | [test_palindrome.cpp](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-02/05-Programming-Assignment/Source/test_palindrome.cpp) 25 | -------------------------------------------------------------------------------- /week-03/02-Programming-Assignment/phone_number.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by avtomato on 1/8/18. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | 9 | PhoneNumber::PhoneNumber(const string &international_number) { 10 | stringstream phone_stream(international_number); 11 | string country_code, city_code, local_number; 12 | if (phone_stream) { 13 | getline(phone_stream, country_code, '-'); 14 | getline(phone_stream, city_code, '-'); 15 | getline(phone_stream, local_number, '\n'); 16 | } 17 | if (country_code[0] != '+' || country_code.size() < 2) { 18 | throw invalid_argument(""); 19 | } 20 | string tmp; 21 | for (int i = 1; i < country_code.size(); ++i) { 22 | tmp += country_code[i]; 23 | } 24 | country_code_ = tmp; 25 | if (city_code.empty()) { 26 | throw invalid_argument(""); 27 | } 28 | city_code_ = city_code; 29 | if (local_number.empty()) { 30 | throw invalid_argument(""); 31 | } 32 | local_number_ = local_number; 33 | } 34 | 35 | string PhoneNumber::GetCountryCode() const { 36 | return country_code_; 37 | } 38 | 39 | string PhoneNumber::GetCityCode() const { 40 | return city_code_; 41 | } 42 | 43 | string PhoneNumber::GetLocalNumber() const { 44 | return local_number_; 45 | } 46 | 47 | string PhoneNumber::GetInternationalNumber() const { 48 | return "+" + country_code_+ "-" + city_code_ + "-" + local_number_; 49 | } -------------------------------------------------------------------------------- /week-04/07-Programming-Assignment/Solution/merge_sort_div3.cpp: -------------------------------------------------------------------------------- 1 | template 2 | void MergeSort(RandomIt range_begin, RandomIt range_end) { 3 | // 1. Если диапазон содержит меньше 2 элементов, выходим из функции 4 | int range_length = range_end - range_begin; 5 | if (range_length < 2) { 6 | return; 7 | } 8 | 9 | // 2. Создаем вектор, содержащий все элементы текущего диапазона 10 | vector elements(range_begin, range_end); 11 | 12 | // 3. Разбиваем вектор на три равные части 13 | auto one_third = elements.begin() + range_length / 3; 14 | auto two_third = elements.begin() + range_length * 2 / 3; 15 | 16 | // 4. Вызываем функцию MergeSort от каждой трети вектора 17 | MergeSort(elements.begin(), one_third); 18 | MergeSort(one_third, two_third); 19 | MergeSort(two_third, elements.end()); 20 | 21 | // 5. С помощью алгоритма merge cливаем первые две трети во временный вектор 22 | // back_inserter -> http://ru.cppreference.com/w/cpp/iterator/back_inserter 23 | vector interim_result; 24 | merge(elements.begin(), one_third, one_third, two_third, 25 | back_inserter(interim_result)); 26 | 27 | // 6. С помощью алгоритма merge сливаем отсортированные части 28 | // в исходный диапазон 29 | // merge -> http://ru.cppreference.com/w/cpp/algorithm/merge 30 | merge(interim_result.begin(), interim_result.end(), two_third, elements.end(), 31 | range_begin); 32 | } 33 | -------------------------------------------------------------------------------- /week-05/02-Practice-Programming-Assignment/Solution/notifiers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void SendSms(const string& number, const string& message) { 7 | cout << "Send '" << message << "' to number " << number << endl; 8 | } 9 | 10 | void SendEmail(const string& email, const string& message) { 11 | cout << "Send '" << message << "' to e-mail " << email << endl; 12 | } 13 | 14 | class INotifier { 15 | public: 16 | virtual void Notify(const string& message) const = 0; 17 | }; 18 | 19 | class SmsNotifier : public INotifier { 20 | public: 21 | SmsNotifier(const string& number) 22 | : Number(number) 23 | { 24 | } 25 | virtual void Notify(const string& message) const override { 26 | SendSms(Number, message); 27 | } 28 | 29 | private: 30 | const string Number; 31 | }; 32 | 33 | class EmailNotifier : public INotifier { 34 | public: 35 | EmailNotifier(const string& email) 36 | : Email(email) 37 | { 38 | } 39 | virtual void Notify(const string& message) const override { 40 | SendEmail(Email, message); 41 | } 42 | 43 | private: 44 | const string Email; 45 | }; 46 | 47 | void Notify(const INotifier& notifier, const string& message) { 48 | notifier.Notify(message); 49 | } 50 | 51 | int main() { 52 | SmsNotifier sms{"+7-495-777-77-77"}; 53 | EmailNotifier email{"na-derevnyu@dedushke.ru"}; 54 | 55 | Notify(sms, "I have White belt in C++"); 56 | Notify(email, "And want a Yellow one"); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /week-04/10-Programming-Assignment/find_starts_with_string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | template 8 | std::pair FindStartsWith( 9 | RandomIt range_begin, RandomIt range_end, 10 | const std::string& prefix) { 11 | return std::equal_range(range_begin,range_end,prefix, [&prefix](const std::string& a,const std::string& b) { 12 | return a.compare(0, prefix.length(), b.substr(0, prefix.length())) < 0; 13 | }); 14 | }; 15 | 16 | int main() { 17 | const std::vector sorted_strings = {"moscow", "motovilikha", "murmansk"}; 18 | 19 | const auto mo_result = 20 | FindStartsWith(begin(sorted_strings), end(sorted_strings), "mo"); 21 | for (auto it = mo_result.first; it != mo_result.second; ++it) { 22 | std::cout << *it << " "; 23 | } 24 | std::cout << std::endl; 25 | 26 | const auto mt_result = 27 | FindStartsWith(begin(sorted_strings), end(sorted_strings), "mt"); 28 | std::cout << (mt_result.first - begin(sorted_strings)) << " " << 29 | (mt_result.second - begin(sorted_strings)) << std::endl; 30 | 31 | const auto na_result = 32 | FindStartsWith(begin(sorted_strings), end(sorted_strings), "na"); 33 | std::cout << (na_result.first - begin(sorted_strings)) << " " << 34 | (na_result.second - begin(sorted_strings)) << std::endl; 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /week-05/02-Practice-Programming-Assignment/notifiers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | 7 | void SendSms(const string& number, const string& message) { 8 | cout << "Send '" << message << "' to number " << number << endl; 9 | } 10 | 11 | void SendEmail(const string& email, const string& message) { 12 | cout << "Send '" << message << "' to e-mail " << email << endl; 13 | } 14 | 15 | /* 16 | Реализуйте здесь классы INotifier, SmsNotifier, EmailNotifier 17 | */ 18 | class INotifier { 19 | public: 20 | virtual void Notify(const string& message) const = 0; 21 | }; 22 | 23 | class SmsNotifier : public INotifier { 24 | public: 25 | SmsNotifier(const string& phone) : phone_(phone) {} 26 | 27 | void Notify(const string& message) const override { 28 | SendSms(phone_, message); 29 | } 30 | 31 | private: 32 | const string phone_; 33 | }; 34 | 35 | class EmailNotifier : public INotifier { 36 | public: 37 | EmailNotifier(const string& email) : email_(email) {} 38 | 39 | void Notify(const string& message) const override { 40 | SendEmail(email_, message); 41 | } 42 | 43 | private: 44 | const string email_; 45 | 46 | }; 47 | 48 | void Notify(INotifier& notifier, const string& message) { 49 | notifier.Notify(message); 50 | } 51 | 52 | int main() { 53 | SmsNotifier sms{"+7-495-777-77-77"}; 54 | EmailNotifier email{"na-derevnyu@dedushke.ru"}; 55 | 56 | Notify(sms, "I have White belt in C++"); 57 | Notify(email, "And want a Yellow one"); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /week-04/10-Programming-Assignment/find_starts_with_char.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | template 8 | std::pair FindStartsWith( 9 | RandomIt range_begin, RandomIt range_end, 10 | char prefix) { 11 | 12 | std::string target1 = {prefix}; 13 | auto first = std::lower_bound(range_begin, range_end, target1); 14 | 15 | auto next = static_cast(prefix + 1); 16 | std::string target2 = {next}; 17 | auto last = std::upper_bound(range_begin, range_end, target2); 18 | 19 | return std::make_pair(first, last); 20 | }; 21 | 22 | int main() { 23 | const std::vector sorted_strings = {"moscow", "murmansk", "vologda"}; 24 | 25 | const auto m_result = 26 | FindStartsWith(begin(sorted_strings), end(sorted_strings), 'm'); 27 | for (auto it = m_result.first; it != m_result.second; ++it) { 28 | std::cout << *it << " "; 29 | } 30 | std::cout << std::endl; 31 | 32 | const auto p_result = 33 | FindStartsWith(begin(sorted_strings), end(sorted_strings), 'p'); 34 | std::cout << (p_result.first - begin(sorted_strings)) << " " << 35 | (p_result.second - begin(sorted_strings)) << std::endl; 36 | 37 | const auto z_result = 38 | FindStartsWith(begin(sorted_strings), end(sorted_strings), 'z'); 39 | std::cout << (z_result.first - begin(sorted_strings)) << " " << 40 | (z_result.second - begin(sorted_strings)) << std::endl; 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /week-01/05-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Всё в квадрат #### 2 | 3 | 4 | Реализуйте шаблонную функцию _Sqr_, которая работает не только для чисел, но и для контейнеров. Функция должна возвращать копию исходного контейнера, модифицировав его следующим образом: 5 | 6 | * для _vector_ элементы нужно возвести в квадрат; 7 | * для _map_ в квадрат нужно возвести только значения, но не ключи; 8 | * для _pair_ в квадрат нужно возвести каждый элемент пары. 9 | ```objectivec 10 | // Пример вызова функции 11 | vector v = {1, 2, 3}; 12 | cout << "vector:"; 13 | for (int x : Sqr(v)) { 14 | cout << ' ' << x; 15 | } 16 | cout << endl; 17 | 18 | map> map_of_pairs = { 19 | {4, {2, 2}}, 20 | {7, {4, 3}} 21 | }; 22 | cout << "map of pairs:" << endl; 23 | for (const auto& x : Sqr(map_of_pairs)) { 24 | cout << x.first << ' ' << x.second.first << ' ' << x.second.second << endl; 25 | } 26 | ``` 27 | Код выше должен вывести 28 | ```commandline 29 | vector: 1 4 9 30 | map of pairs: 31 | 4 4 4 32 | 7 16 9 33 | ``` 34 | Функция должна корректно работать не только для контейнеров, состоящих из чисел, но и для составных объектов, например, векторов словарей пар чисел. 35 | 36 | Для успешной сдачи решения необходимо сделать предварительное объявление шаблонных функций перед всеми шаблонными функциями. 37 | 38 | Пример предварительного объявления шаблонной функции 39 | ```objectivec 40 | // Предварительное объявление шаблонных функций 41 | template T FuncA(T x); 42 | template void FuncB(T x); 43 | 44 | // Объявляем шаблонные функции 45 | template 46 | T FuncA(T x) { /*...*/ } 47 | 48 | template 49 | void FuncB(T x) { /*...*/ } 50 | ``` 51 | Зачем это нужно и как это работает вы узнаете далее из наших курсов. -------------------------------------------------------------------------------- /week-04/11-Programming-Assignment/Solution/build_expression_without_redundant.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | 11 | // Определим структуру для удобной организации данных 12 | struct Operation { 13 | // Параметры по умолчанию нужны для конструирования вектора 14 | // ненулевого размера, см. (*) 15 | char type = 0; 16 | int number = 0; 17 | }; 18 | 19 | 20 | // Функция для проверки выполнения требований постановки скобок 21 | bool NeedBrackets(char last, char current) { 22 | return (last == '+' || last == '-') && (current == '*' || current == '/'); 23 | } 24 | 25 | 26 | int main() { 27 | int initial_number; 28 | cin >> initial_number; 29 | 30 | int number_of_operations; 31 | cin >> number_of_operations; 32 | vector operations(number_of_operations); // (*) 33 | for (int i = 0; i < number_of_operations; ++i) { 34 | cin >> operations[i].type; 35 | cin >> operations[i].number; 36 | } 37 | 38 | deque expression; 39 | expression.push_back(to_string(initial_number)); 40 | // первое число никогда не обрамляется скобками 41 | char last_type = '*'; 42 | for (const auto& operation : operations) { 43 | // Если условия удовлетворены, обрамляем последовательность скобками 44 | if (NeedBrackets(last_type, operation.type)) { 45 | expression.push_front("("); 46 | expression.push_back(")"); 47 | } 48 | expression.push_back(" "); 49 | expression.push_back(string(1, operation.type)); 50 | expression.push_back(" "); 51 | expression.push_back(to_string(operation.number)); 52 | 53 | last_type = operation.type; 54 | } 55 | 56 | for (const string& s : expression) { 57 | cout << s; 58 | } 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /week-04/06-Practice-Programming-Assignment/Solution/print_stats.cpp: -------------------------------------------------------------------------------- 1 | void PrintStats(vector persons) { 2 | // Преобразуем порядок людей к следующему: 3 | // persons 4 | // / \ 5 | // females males 6 | // / \ / \ 7 | // empl. unempl. empl. unempl. 8 | auto females_end = partition( 9 | begin(persons), end(persons), [](const Person& p) { 10 | return p.gender == Gender::FEMALE; 11 | } 12 | ); 13 | auto employed_females_end = partition( 14 | begin(persons), females_end, [](const Person& p) { 15 | return p.is_employed; 16 | } 17 | ); 18 | auto employed_males_end = partition( 19 | females_end, end(persons), [](const Person& p) { 20 | return p.is_employed; 21 | } 22 | ); 23 | 24 | // Теперь интересующие нас группы находятся в векторе непрерывно 25 | cout << "Median age = " 26 | << ComputeMedianAge(begin(persons), end(persons)) << endl; 27 | cout << "Median age for females = " 28 | << ComputeMedianAge(begin(persons), females_end) << endl; 29 | cout << "Median age for males = " 30 | << ComputeMedianAge(females_end, end(persons)) << endl; 31 | cout << "Median age for employed females = " 32 | << ComputeMedianAge(begin(persons), employed_females_end) << endl; 33 | cout << "Median age for unemployed females = " 34 | << ComputeMedianAge(employed_females_end, females_end) << endl; 35 | cout << "Median age for employed males = " 36 | << ComputeMedianAge(females_end, employed_males_end) << endl; 37 | cout << "Median age for unemployed males = " 38 | << ComputeMedianAge(employed_males_end, end(persons)) << endl; 39 | } 40 | -------------------------------------------------------------------------------- /week-02/04-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Тесты для класса Rational #### 2 | 3 | 4 | Класс _Rational_ представляет собой рациональное число и имеет следующий интерфейс 5 | ```objectivec 6 | class Rational { 7 | public: 8 | Rational(); 9 | Rational(int numerator, int denominator); 10 | 11 | int Numerator() const; 12 | int Denominator() const; 13 | }; 14 | ``` 15 | Список требований, предъявляемых к реализации интерфейса класса _Rational_: 16 | 17 | 1. Конструктор по умолчанию должен создавать дробь с числителем 0 и знаменателем 1. 18 | 2. При конструировании объекта класса _Rational_ с параметрами p и q должно выполняться сокращение дроби p/q. 19 | 3. Если дробь p/q отрицательная, то объект _Rational(p, q)_ должен иметь отрицательный числитель и положительный знаменатель. 20 | 4. Если дробь p/q положительная, то объект _Rational(p, q)_ должен иметь положительные числитель и знаменатель (обратите внимание на случай _Rational(-2, -3)_). 21 | 5. Если числитель дроби равен нулю, то знаменатель должен быть равен 1. 22 | 23 | Разработайте набор юнит-тестов, которые будут проверять корректность реализации класса _Rational_. **Тестировать случай, когда знаменатель равен нулю, не надо**. 24 | 25 | Начать работу вы можете с шаблона, который содержит наш фреймворк юнит-тестов и заготовку класса _Rational_. 26 | 27 | [test_rational.cpp](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-02/04-Programming-Assignment/Source/test_rational.cpp) 28 | 29 | ##### Примечание ##### 30 | Перед отправкой вашего файла убедитесь, что он не содержит класса _Person_. В противном случае вы получите ошибку компиляции. Наша тестирующая система умеет игнорировать функции в файлах (поэтому, например, в задаче "Тесты для функции _IsPalindrom_" необязательно удалять функцию _IsPalindrom_), но не умеет это делать для классов. 31 | -------------------------------------------------------------------------------- /week-01/05-Programming-Assignment/sqr_all.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | template T Sqr(T x); 7 | template std::vector operator * (const std::vector& v1, const std::vector& v2); 8 | template std::pair operator * (const std::pair& p1, const std::pair& p2); 9 | template std::map operator * (const std::map& m1, const std::map& m2); 10 | 11 | 12 | template 13 | std::vector operator * (const std::vector& v1, const std::vector& v2) { 14 | std::vector result; 15 | for (int i = 0; i < v1.size(); ++i) { 16 | result.push_back(v1[i] * v2[i]); 17 | } 18 | return result; 19 | } 20 | 21 | template 22 | std::pair operator * (const std::pair& p1, const std::pair& p2) { 23 | First f = p1.first * p2.first; 24 | Second s = p1.second * p2.second; 25 | return std::make_pair(f, s); 26 | }; 27 | 28 | template 29 | std::map operator * (const std::map& m1, const std::map& m2) { 30 | std::map result; 31 | for (auto& p: m1) { 32 | auto second_value = m2.at(p.first); 33 | result[p.first] = p.second * second_value; 34 | } 35 | return result; 36 | }; 37 | 38 | template 39 | T Sqr(T x) { 40 | return x * x; 41 | } 42 | 43 | int main() { 44 | // Пример вызова функции 45 | std::vector v = {1, 2, 3}; 46 | std::cout << "vector:"; 47 | for (int x : Sqr(v)) { 48 | std::cout << ' ' << x; 49 | } 50 | std::cout << std::endl; 51 | 52 | std::map> map_of_pairs = { 53 | {4, {2, 2}}, 54 | {7, {4, 3}} 55 | }; 56 | std::cout << "map of pairs:" << std::endl; 57 | for (const auto& x : Sqr(map_of_pairs)) { 58 | std::cout << x.first << ' ' << x.second.first << ' ' << x.second.second << std::endl; 59 | } 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /week-03/02-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Реализовать класс, объявленный в заголовочном файле #### 2 | 3 | 4 | Вам дан заголовочный файл *phone_number.h*, содержащий объявление класса *PhoneNumber*. При этом в комментариях описано поведение, которое ожидается от реализации этого класса. 5 | 6 | [phone_number.h](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-03/02-Programming-Assignment/Source/phone_number.h) 7 | 8 | ```objectivec 9 | #pragma once 10 | 11 | #include 12 | 13 | using namespace std; 14 | 15 | class PhoneNumber { 16 | public: 17 | /* Принимает строку в формате +XXX-YYY-ZZZZZZ 18 | Часть от '+' до первого '-' - это код страны. 19 | Часть между первым и вторым символами '-' - код города 20 | Всё, что идёт после второго символа '-' - местный номер. 21 | Код страны, код города и местный номер не должны быть пустыми. 22 | Если строка не соответствует этому формату, нужно выбросить исключение invalid_argument. Проверять, что номер содержит только цифры, не нужно. 23 | 24 | Примеры: 25 | * +7-495-111-22-33 26 | * +7-495-1112233 27 | * +323-22-460002 28 | * +1-2-coursera-cpp 29 | * 1-2-333 - некорректный номер - не начинается на '+' 30 | * +7-1233 - некорректный номер - есть только код страны и города 31 | */ 32 | explicit PhoneNumber(const string &international_number); 33 | 34 | string GetCountryCode() const; 35 | string GetCityCode() const; 36 | string GetLocalNumber() const; 37 | string GetInternationalNumber() const; 38 | 39 | private: 40 | string country_code_; 41 | string city_code_; 42 | string local_number_; 43 | }; 44 | 45 | ``` 46 | Пришлите *cpp*-файл **с определениями методов** класса *PhoneNumber*, которые реализуют описанное поведение. 47 | 48 | ##### Как будет тестироваться ваш код ##### 49 | Автоматическая тестирующая система добавит ваш *cpp*-файл в проект, содержащий другой *cpp*-файл с юнит-тестами для класса *PhoneNumber*, а также файл *phone_number.h*. Затем она соберёт этот проект и, если компиляция будет выполнена успешно, запустит получившийся исполняемый файл. Если он завершится успешно (т. е. юнит-тесты не найдут ошибок в вашей реализации), то ваша посылка будет засчитана. 50 | -------------------------------------------------------------------------------- /week-04/11-Programming-Assignment/build_expression.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | enum class QueryType { 6 | Add, 7 | Sub, 8 | Mul, 9 | Div 10 | }; 11 | 12 | struct Query { 13 | QueryType type; 14 | std::string value; 15 | }; 16 | 17 | std::istream& operator >> (std::istream& is, Query& q) { 18 | std::string typeStr; 19 | is >> typeStr; 20 | if (typeStr == "+") { 21 | q.type = QueryType::Add; 22 | is >> q.value; 23 | } else if (typeStr == "-") { 24 | q.type = QueryType::Sub; 25 | is >> q.value; 26 | } else if (typeStr == "*") { 27 | q.type = QueryType::Mul; 28 | is >> q.value; 29 | } else if (typeStr == "/") { 30 | q.type = QueryType::Div; 31 | is >> q.value; 32 | } 33 | 34 | return is; 35 | } 36 | 37 | int main() { 38 | int x; 39 | std::cin >> x; 40 | 41 | int n; 42 | std::cin >> n; 43 | Query q; 44 | 45 | std::deque d; 46 | d.push_back(std::to_string(x)); 47 | 48 | for (int i = 0; i < n; ++i) { 49 | std::cin >> q; 50 | switch (q.type) { 51 | case QueryType::Add: 52 | d.push_front("("); 53 | d.push_back(")"); 54 | d.push_back("+"); 55 | d.push_back(q.value); 56 | break; 57 | case QueryType::Sub: 58 | d.push_front("("); 59 | d.push_back(")"); 60 | d.push_back("-"); 61 | d.push_back(q.value); 62 | break; 63 | case QueryType::Mul: 64 | d.push_front("("); 65 | d.push_back(")"); 66 | d.push_back("*"); 67 | d.push_back(q.value); 68 | break; 69 | case QueryType::Div: 70 | d.push_front("("); 71 | d.push_back(")"); 72 | d.push_back("/"); 73 | d.push_back(q.value); 74 | break; 75 | } 76 | } 77 | 78 | for (auto& item : d) { 79 | if (item == "+" || item == "-" || item == "*" || item == "/") { 80 | std::cout << " " << item << " "; 81 | } else { 82 | std::cout << item; 83 | } 84 | } 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /week-04/09-Practice-Programming-Assignment/person_names.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | // если имя неизвестно, возвращает пустую строку 7 | std::string FindNameByYear(const std::map& names, int year) { 8 | std::string name; // изначально имя неизвестно 9 | 10 | auto it = names.upper_bound(year); 11 | if (it != names.begin()) { 12 | name = std::prev(it) -> second; 13 | } 14 | 15 | return name; 16 | } 17 | 18 | class Person { 19 | public: 20 | void ChangeFirstName(int year, const std::string& first_name) { 21 | first_names[year] = first_name; 22 | } 23 | void ChangeLastName(int year, const std::string& last_name) { 24 | last_names[year] = last_name; 25 | } 26 | std::string GetFullName(int year) { 27 | // получаем имя и фамилию по состоянию на год year 28 | const std::string first_name = FindNameByYear(first_names, year); 29 | const std::string last_name = FindNameByYear(last_names, year); 30 | 31 | // если и имя, и фамилия неизвестны 32 | if (first_name.empty() && last_name.empty()) { 33 | return "Incognito"; 34 | 35 | // если неизвестно только имя 36 | } else if (first_name.empty()) { 37 | return last_name + " with unknown first name"; 38 | 39 | // если неизвестна только фамилия 40 | } else if (last_name.empty()) { 41 | return first_name + " with unknown last name"; 42 | 43 | // если известны и имя, и фамилия 44 | } else { 45 | return first_name + " " + last_name; 46 | } 47 | } 48 | 49 | private: 50 | std::map first_names; 51 | std::map last_names; 52 | }; 53 | 54 | int main() { 55 | Person person; 56 | 57 | person.ChangeFirstName(1965, "Polina"); 58 | person.ChangeLastName(1967, "Sergeeva"); 59 | for (int year : {1900, 1965, 1990}) { 60 | std::cout << person.GetFullName(year) << std::endl; 61 | } 62 | 63 | person.ChangeFirstName(1970, "Appolinaria"); 64 | for (int year : {1969, 1970}) { 65 | std::cout << person.GetFullName(year) << std::endl; 66 | } 67 | 68 | person.ChangeLastName(1968, "Volkova"); 69 | for (int year : {1969, 1970}) { 70 | std::cout << person.GetFullName(year) << std::endl; 71 | } 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /week-05/02-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Отправка уведомлений #### 2 | 3 | 4 | В этой задаче вам нужно разработать классы *SmsNotifier* и *EmailNotifier*, отправляющие уведомления в виде SMS и *e-mail* соответственно, а также абстрактный базовый класс для них. 5 | 6 | Вам даны функции *SendSms* и *SendEmail*, которые моделируют отправку SMS и *e-mail*. 7 | 8 | ```objectivec 9 | void SendSms(const string& number, const string& message); 10 | void SendEmail(const string& email, const string& message); 11 | ``` 12 | 13 | Разработайте: 14 | 15 | 1. Абстрактный базовый класс *INotifier*, у которого будет один чисто виртуальный метод *void Notify(const string& message)*. 16 | 2. Класс *SmsNotifier*, который: 17 | * является потомком класса *INotifier*; 18 | * в конструкторе принимает один параметр типа string — номер телефона; 19 | * переопределяет метод *Notify* и вызывает из него функцию *SendSms*. 20 | 3. Класс *EmailNotifier*, который; 21 | * является потомком класса *INotifier*; 22 | * в конструкторе принимает один параметр типа string — адрес электронной почты; 23 | * переопределяет метод *Notify* и вызывает из него функцию *SendEmail*. 24 | 25 | Пример кода для проверки: 26 | ```objectivec 27 | #include 28 | #include 29 | 30 | using namespace std; 31 | 32 | void SendSms(const string& number, const string& message) { 33 | cout << "Send '" << message << "' to number " << number << endl; 34 | } 35 | 36 | void SendEmail(const string& email, const string& message) { 37 | cout << "Send '" << message << "' to e-mail " << email << endl; 38 | } 39 | 40 | /* 41 | Реализуйте здесь классы INotifier, SmsNotifier, EmailNotifier 42 | */ 43 | 44 | void Notify(INotifier& notifier, const string& message) { 45 | notifier.Notify(message); 46 | } 47 | 48 | 49 | int main() { 50 | SmsNotifier sms{"+7-495-777-77-77"}; 51 | EmailNotifier email{"na-derevnyu@dedushke.ru"}; 52 | 53 | Notify(sms, "I have White belt in C++"); 54 | Notify(email, "And want a Yellow one"); 55 | return 0; 56 | } 57 | ``` 58 | Когда вы реализуете нужные классы, программа выше должна вывести: 59 | ```commandline 60 | Send 'I have White belt in C++' to number +7-495-777-77-77 61 | Send 'And want a Yellow one' to e-mail na-derevnyu@dedushke.ru 62 | ``` 63 | Уточним ещё раз, что файл, отправляемый на проверку, должен содержать реализации классов *INotifier*, *SmsNotifier*, *EmailNotifier* и не должен содержать функцию *main*. -------------------------------------------------------------------------------- /week-02/01-Programming-Assignment/Source/starter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | enum class QueryType { 10 | NewBus, 11 | BusesForStop, 12 | StopsForBus, 13 | AllBuses 14 | }; 15 | 16 | struct Query { 17 | QueryType type; 18 | string bus; 19 | string stop; 20 | vector stops; 21 | }; 22 | 23 | istream& operator >> (istream& is, Query& q) { 24 | // Реализуйте эту функцию 25 | return is; 26 | } 27 | 28 | struct BusesForStopResponse { 29 | // Наполните полями эту структуру 30 | }; 31 | 32 | ostream& operator << (ostream& os, const BusesForStopResponse& r) { 33 | // Реализуйте эту функцию 34 | return os; 35 | } 36 | 37 | struct StopsForBusResponse { 38 | // Наполните полями эту структуру 39 | }; 40 | 41 | ostream& operator << (ostream& os, const StopsForBusResponse& r) { 42 | // Реализуйте эту функцию 43 | return os; 44 | } 45 | 46 | struct AllBusesResponse { 47 | // Наполните полями эту структуру 48 | }; 49 | 50 | ostream& operator << (ostream& os, const AllBusesResponse& r) { 51 | // Реализуйте эту функцию 52 | return os; 53 | } 54 | 55 | class BusManager { 56 | public: 57 | void AddBus(const string& bus, const vector& stops) { 58 | // Реализуйте этот метод 59 | } 60 | 61 | BusesForStopResponse GetBusesForStop(const string& stop) const { 62 | // Реализуйте этот метод 63 | } 64 | 65 | StopsForBusResponse GetStopsForBus(const string& bus) const { 66 | // Реализуйте этот метод 67 | } 68 | 69 | AllBusesResponse GetAllBuses() const { 70 | // Реализуйте этот метод 71 | } 72 | }; 73 | 74 | // Не меняя тела функции main, реализуйте функции и классы выше 75 | 76 | int main() { 77 | int query_count; 78 | Query q; 79 | 80 | cin >> query_count; 81 | 82 | BusManager bm; 83 | for (int i = 0; i < query_count; ++i) { 84 | cin >> q; 85 | switch (q.type) { 86 | case QueryType::NewBus: 87 | bm.AddBus(q.bus, q.stops); 88 | break; 89 | case QueryType::BusesForStop: 90 | cout << bm.GetBusesForStop(q.stop) << endl; 91 | break; 92 | case QueryType::StopsForBus: 93 | cout << bm.GetStopsForBus(q.bus) << endl; 94 | break; 95 | case QueryType::AllBuses: 96 | cout << bm.GetAllBuses() << endl; 97 | break; 98 | } 99 | } 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /week-03/04-Programming-Assignment/Source/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | enum class QueryType { 10 | NewBus, 11 | BusesForStop, 12 | StopsForBus, 13 | AllBuses 14 | }; 15 | 16 | struct Query { 17 | QueryType type; 18 | string bus; 19 | string stop; 20 | vector stops; 21 | }; 22 | 23 | istream& operator >> (istream& is, Query& q) { 24 | // Реализуйте эту функцию 25 | return is; 26 | } 27 | 28 | struct BusesForStopResponse { 29 | // Наполните полями эту структуру 30 | }; 31 | 32 | ostream& operator << (ostream& os, const BusesForStopResponse& r) { 33 | // Реализуйте эту функцию 34 | return os; 35 | } 36 | 37 | struct StopsForBusResponse { 38 | // Наполните полями эту структуру 39 | }; 40 | 41 | ostream& operator << (ostream& os, const StopsForBusResponse& r) { 42 | // Реализуйте эту функцию 43 | return os; 44 | } 45 | 46 | struct AllBusesResponse { 47 | // Наполните полями эту структуру 48 | }; 49 | 50 | ostream& operator << (ostream& os, const AllBusesResponse& r) { 51 | // Реализуйте эту функцию 52 | return os; 53 | } 54 | 55 | class BusManager { 56 | public: 57 | void AddBus(const string& bus, const vector& stops) { 58 | // Реализуйте этот метод 59 | } 60 | 61 | BusesForStopResponse GetBusesForStop(const string& stop) const { 62 | // Реализуйте этот метод 63 | } 64 | 65 | StopsForBusResponse GetStopsForBus(const string& bus) const { 66 | // Реализуйте этот метод 67 | } 68 | 69 | AllBusesResponse GetAllBuses() const { 70 | // Реализуйте этот метод 71 | } 72 | }; 73 | 74 | // Не меняя тела функции main, реализуйте функции и классы выше 75 | 76 | int main() { 77 | int query_count; 78 | Query q; 79 | 80 | cin >> query_count; 81 | 82 | BusManager bm; 83 | for (int i = 0; i < query_count; ++i) { 84 | cin >> q; 85 | switch (q.type) { 86 | case QueryType::NewBus: 87 | bm.AddBus(q.bus, q.stops); 88 | break; 89 | case QueryType::BusesForStop: 90 | cout << bm.GetBusesForStop(q.stop) << endl; 91 | break; 92 | case QueryType::StopsForBus: 93 | cout << bm.GetStopsForBus(q.bus) << endl; 94 | break; 95 | case QueryType::AllBuses: 96 | cout << bm.GetAllBuses() << endl; 97 | break; 98 | } 99 | } 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /week-04/11-Programming-Assignment/build_expression_without_redundant.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | enum class QueryType { 6 | Add, 7 | Sub, 8 | Mul, 9 | Div 10 | }; 11 | 12 | struct Query { 13 | QueryType type; 14 | std::string value; 15 | }; 16 | 17 | std::istream& operator >> (std::istream& is, Query& q) { 18 | std::string typeStr; 19 | is >> typeStr; 20 | if (typeStr == "+") { 21 | q.type = QueryType::Add; 22 | is >> q.value; 23 | } else if (typeStr == "-") { 24 | q.type = QueryType::Sub; 25 | is >> q.value; 26 | } else if (typeStr == "*") { 27 | q.type = QueryType::Mul; 28 | is >> q.value; 29 | } else if (typeStr == "/") { 30 | q.type = QueryType::Div; 31 | is >> q.value; 32 | } 33 | 34 | return is; 35 | } 36 | 37 | int main() { 38 | int x; 39 | std::cin >> x; 40 | 41 | int n; 42 | std::cin >> n; 43 | Query q; 44 | Query p; 45 | 46 | std::deque d; 47 | d.push_back(std::to_string(x)); 48 | 49 | for (int i = 0; i < n; ++i) { 50 | std::cin >> q; 51 | switch (q.type) { 52 | case QueryType::Add: 53 | d.push_back("+"); 54 | d.push_back(q.value); 55 | p = q; 56 | break; 57 | case QueryType::Sub: 58 | d.push_back("-"); 59 | d.push_back(q.value); 60 | p = q; 61 | break; 62 | case QueryType::Mul: 63 | if (p.type == QueryType::Add || p.type == QueryType::Sub) { 64 | d.push_front("("); 65 | d.push_back(")"); 66 | } 67 | d.push_back("*"); 68 | d.push_back(q.value); 69 | p = q; 70 | break; 71 | case QueryType::Div: 72 | if (p.type == QueryType::Add || p.type == QueryType::Sub) { 73 | d.push_front("("); 74 | d.push_back(")"); 75 | } 76 | d.push_back("/"); 77 | d.push_back(q.value); 78 | p = q; 79 | break; 80 | } 81 | } 82 | 83 | for (auto& item : d) { 84 | if (item == "+" || item == "-" || item == "*" || item == "/") { 85 | std::cout << " " << item << " "; 86 | } else { 87 | std::cout << item; 88 | } 89 | } 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /week-04/11-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Построение арифметического выражения #### 2 | 3 | 4 | #### Часть 1 #### 5 | Реализуйте построение арифметического выражения согласно следующей схеме: 6 | 7 | * изначально есть выражение, состоящее из некоторого целого числа *x*; 8 | * на каждом шаге к текущему выражению применяется некоторая операция: прибавление числа, вычитание числа, умножение на число или деление на число; перед применением операции выражение всегда должно быть заключено в скобки. 9 | 10 | ##### Пример ##### 11 | Изначально есть число 8, соответствующее выражение: 12 | ```commandline 13 | 8 14 | ``` 15 | К нему применяется операция умножения на 3, получается выражение 16 | ```commandline 17 | (8) * 3 18 | ``` 19 | Затем вычитается 6: 20 | ```commandline 21 | ((8) * 3) - 6 22 | ``` 23 | Наконец, происходит деление на 1; итоговое выражение: 24 | ```commandline 25 | (((8) * 3) - 6) / 1 26 | ``` 27 | 28 | ##### Формат ввода ##### 29 | В первой строке содержится исходное целое число *x*. Во второй строке содержится целое неотрицательное число *N*— количество операций. В каждой из следующих *N* строк содержится очередная операция: 30 | * прибавление числа *a*: **+ a**; 31 | * либо вычитание числа *b*: **- b**; 32 | * либо умножение на число *c*: __* c__; 33 | * либо деление на число *d*: **/ d**. 34 | 35 | Количество операций может быть нулевым — в этом случае необходимо вывести исходное число. 36 | 37 | ##### Формат вывода ##### 38 | Выведите единственную строку — построенное арифметическое выражение. 39 | 40 | Обратите внимание на расстановку пробелов вокруг символов: 41 | * каждый символ бинарной операции (+, -, * или /) должен быть окружён ровно одним пробелом с каждой стороны: (8) * 3; 42 | * символ унарного минуса (для отрицательных чисел) не нуждается в дополнительном пробеле: -5; 43 | * скобки и числа не нуждаются в дополнительных пробелах. 44 | 45 | ##### Подсказка ##### 46 | Для преобразования числа к строке используйте функцию *to_string* из библиотеки **. 47 | 48 | ##### Пример ##### 49 | ###### Ввод ###### 50 | ```commandline 51 | 8 52 | 3 53 | * 3 54 | - 6 55 | / 1 56 | ``` 57 | ###### Вывод ###### 58 | ```commandline 59 | (((8) * 3) - 6) / 1 60 | ``` 61 | 62 | #### Часть 2. Без лишних скобок #### 63 | Модифицируйте решение предыдущей части так, чтобы предыдущее выражение обрамлялось скобками лишь при необходимости, то есть только в том случае, когда очередная операция имеет бо́льший приоритет, чем предыдущая. 64 | 65 | ##### Пример ##### 66 | ###### Ввод ###### 67 | ```commandline 68 | 8 69 | 3 70 | * 3 71 | - 6 72 | / 1 73 | ``` 74 | ###### Вывод ###### 75 | ```commandline 76 | (8 * 3 - 6) / 1 77 | ``` -------------------------------------------------------------------------------- /week-02/05-Programming-Assignment/Source/test_palindrome.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | template 12 | ostream& operator << (ostream& os, const vector& s) { 13 | os << "{"; 14 | bool first = true; 15 | for (const auto& x : s) { 16 | if (!first) { 17 | os << ", "; 18 | } 19 | first = false; 20 | os << x; 21 | } 22 | return os << "}"; 23 | } 24 | 25 | template 26 | ostream& operator << (ostream& os, const set& s) { 27 | os << "{"; 28 | bool first = true; 29 | for (const auto& x : s) { 30 | if (!first) { 31 | os << ", "; 32 | } 33 | first = false; 34 | os << x; 35 | } 36 | return os << "}"; 37 | } 38 | 39 | template 40 | ostream& operator << (ostream& os, const map& m) { 41 | os << "{"; 42 | bool first = true; 43 | for (const auto& kv : m) { 44 | if (!first) { 45 | os << ", "; 46 | } 47 | first = false; 48 | os << kv.first << ": " << kv.second; 49 | } 50 | return os << "}"; 51 | } 52 | 53 | template 54 | void AssertEqual(const T& t, const U& u, const string& hint = {}) { 55 | if (t != u) { 56 | ostringstream os; 57 | os << "Assertion failed: " << t << " != " << u; 58 | if (!hint.empty()) { 59 | os << " hint: " << hint; 60 | } 61 | throw runtime_error(os.str()); 62 | } 63 | } 64 | 65 | void Assert(bool b, const string& hint) { 66 | AssertEqual(b, true, hint); 67 | } 68 | 69 | class TestRunner { 70 | public: 71 | template 72 | void RunTest(TestFunc func, const string& test_name) { 73 | try { 74 | func(); 75 | cerr << test_name << " OK" << endl; 76 | } catch (exception& e) { 77 | ++fail_count; 78 | cerr << test_name << " fail: " << e.what() << endl; 79 | } catch (...) { 80 | ++fail_count; 81 | cerr << "Unknown exception caught" << endl; 82 | } 83 | } 84 | 85 | ~TestRunner() { 86 | if (fail_count > 0) { 87 | cerr << fail_count << " unit tests failed. Terminate" << endl; 88 | exit(1); 89 | } 90 | } 91 | 92 | private: 93 | int fail_count = 0; 94 | }; 95 | 96 | bool IsPalindrom(const string& str) { 97 | // Вы можете вставлять сюда различные реализации функции, 98 | // чтобы проверить, что ваши тесты пропускают корректный код 99 | // и ловят некорректный 100 | } 101 | 102 | int main() { 103 | TestRunner runner; 104 | // добавьте сюда свои тесты 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /week-02/02-Practice-Programming-Assignment/Source/test_equation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | template 12 | ostream& operator << (ostream& os, const vector& s) { 13 | os << "{"; 14 | bool first = true; 15 | for (const auto& x : s) { 16 | if (!first) { 17 | os << ", "; 18 | } 19 | first = false; 20 | os << x; 21 | } 22 | return os << "}"; 23 | } 24 | 25 | template 26 | ostream& operator << (ostream& os, const set& s) { 27 | os << "{"; 28 | bool first = true; 29 | for (const auto& x : s) { 30 | if (!first) { 31 | os << ", "; 32 | } 33 | first = false; 34 | os << x; 35 | } 36 | return os << "}"; 37 | } 38 | 39 | template 40 | ostream& operator << (ostream& os, const map& m) { 41 | os << "{"; 42 | bool first = true; 43 | for (const auto& kv : m) { 44 | if (!first) { 45 | os << ", "; 46 | } 47 | first = false; 48 | os << kv.first << ": " << kv.second; 49 | } 50 | return os << "}"; 51 | } 52 | 53 | template 54 | void AssertEqual(const T& t, const U& u, const string& hint = {}) { 55 | if (t != u) { 56 | ostringstream os; 57 | os << "Assertion failed: " << t << " != " << u; 58 | if (!hint.empty()) { 59 | os << " hint: " << hint; 60 | } 61 | throw runtime_error(os.str()); 62 | } 63 | } 64 | 65 | void Assert(bool b, const string& hint) { 66 | AssertEqual(b, true, hint); 67 | } 68 | 69 | class TestRunner { 70 | public: 71 | template 72 | void RunTest(TestFunc func, const string& test_name) { 73 | try { 74 | func(); 75 | cerr << test_name << " OK" << endl; 76 | } catch (exception& e) { 77 | ++fail_count; 78 | cerr << test_name << " fail: " << e.what() << endl; 79 | } catch (...) { 80 | ++fail_count; 81 | cerr << "Unknown exception caught" << endl; 82 | } 83 | } 84 | 85 | ~TestRunner() { 86 | if (fail_count > 0) { 87 | cerr << fail_count << " unit tests failed. Terminate" << endl; 88 | exit(1); 89 | } 90 | } 91 | 92 | private: 93 | int fail_count = 0; 94 | }; 95 | 96 | int GetDistinctRealRootCount(double a, double b, double c) { 97 | // Вы можете вставлять сюда различные реализации функции, 98 | // чтобы проверить, что ваши тесты пропускают корректный код 99 | // и ловят некорректный 100 | } 101 | 102 | int main() { 103 | TestRunner runner; 104 | // добавьте сюда свои тесты 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /week-04/09-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Имена и фамилии — 4 #### 2 | 3 | 4 | *Решите задачу [«Имена и фамилии — 1»](https://www.coursera.org/learn/c-plus-plus-white/programming/4FQn4/imiena-i-familii-1) более эффективно, использовав двоичный поиск в методе Person::GetFullName. Напомним условие задачи.* 5 | 6 | Реализуйте класс для человека, поддерживающий историю изменений человеком своих фамилии и имени. 7 | ```objectivec 8 | class Person { 9 | public: 10 | void ChangeFirstName(int year, const string& first_name) { 11 | // добавить факт изменения имени на first_name в год year 12 | } 13 | void ChangeLastName(int year, const string& last_name) { 14 | // добавить факт изменения фамилии на last_name в год year 15 | } 16 | string GetFullName(int year) { 17 | // получить имя и фамилию по состоянию на конец года year 18 | // с помощью двоичного поиска 19 | } 20 | private: 21 | // приватные поля 22 | }; 23 | ``` 24 | Считайте, что в каждый год может произойти не более одного изменения фамилии и не более одного изменения имени. При этом с течением времени могут открываться всё новые факты из прошлого человека, поэтому года́ в последовательных вызовах методов *ChangeLastName* и *ChangeFirstName* не обязаны возрастать. 25 | 26 | Гарантируется, что все имена и фамилии непусты. 27 | 28 | Строка, возвращаемая методом *GetFullName*, должна содержать разделённые одним пробелом имя и фамилию человека по состоянию на конец данного года. 29 | 30 | * Если к данному году не случилось ни одного изменения фамилии и имени, верните строку **"Incognito"**. 31 | * Если к данному году случилось изменение фамилии, но не было ни одного изменения имени, верните **"last_name with unknown first name"**. 32 | * Если к данному году случилось изменение имени, но не было ни одного изменения фамилии, верните **"first_name with unknown last name"**. 33 | 34 | ##### Пример ##### 35 | ###### Код ###### 36 | ```objectivec 37 | int main() { 38 | Person person; 39 | 40 | person.ChangeFirstName(1965, "Polina"); 41 | person.ChangeLastName(1967, "Sergeeva"); 42 | for (int year : {1900, 1965, 1990}) { 43 | cout << person.GetFullName(year) << endl; 44 | } 45 | 46 | person.ChangeFirstName(1970, "Appolinaria"); 47 | for (int year : {1969, 1970}) { 48 | cout << person.GetFullName(year) << endl; 49 | } 50 | 51 | person.ChangeLastName(1968, "Volkova"); 52 | for (int year : {1969, 1970}) { 53 | cout << person.GetFullName(year) << endl; 54 | } 55 | 56 | return 0; 57 | } 58 | ``` 59 | ###### Вывод ###### 60 | ```commandline 61 | Incognito 62 | Polina with unknown last name 63 | Polina Sergeeva 64 | Polina Sergeeva 65 | Appolinaria Sergeeva 66 | Polina Volkova 67 | Appolinaria Volkova 68 | ``` -------------------------------------------------------------------------------- /week-05/04-Peer-graded-Assignment/refactoring.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | 8 | class Person { 9 | public: 10 | Person(const string& name, const string& occupation) : _name(name), _occupation(occupation) {} 11 | 12 | string GetName() const { 13 | return _name; 14 | } 15 | string GetOccupation() const { 16 | return _occupation; 17 | } 18 | virtual void Walk(const string& destination) const = 0; 19 | 20 | private: 21 | const string _name; 22 | const string _occupation; 23 | }; 24 | 25 | 26 | class Student : public Person { 27 | public: 28 | 29 | Student(const string& name, const string& favouriteSong) : Person(name, "Student"), _favouriteSong(favouriteSong) {} 30 | 31 | void Learn() const { 32 | cout << "Student: " << GetName() << " learns" << endl; 33 | } 34 | 35 | void Walk(const string& destination) const override { 36 | cout << "Student: " << GetName() << " walks to: " << destination << endl; 37 | SingSong(); 38 | } 39 | 40 | void SingSong() const { 41 | cout << "Student: " << GetName() << " sings a song: " << _favouriteSong << endl; 42 | } 43 | 44 | private: 45 | const string _favouriteSong; 46 | }; 47 | 48 | 49 | class Teacher : public Person { 50 | public: 51 | 52 | Teacher(const string& name, const string& subject) : Person(name, "Teacher"), _subject(subject) {} 53 | 54 | void Teach() const { 55 | cout << "Teacher: " << GetName() << " teaches: " << _subject << endl; 56 | } 57 | 58 | void Walk(const string& destination) const override { 59 | cout << "Teacher: " << GetName() << " walks to: " << destination << endl; 60 | } 61 | 62 | private: 63 | const string _subject; 64 | }; 65 | 66 | 67 | class Policeman : public Person { 68 | public: 69 | Policeman(const string& name) : Person(name, "Policeman") {} 70 | 71 | void Check(Person& person) const { 72 | cout << "Policeman: " << GetName() << " checks " << person.GetOccupation() << ". " 73 | << person.GetOccupation() << "'s name is: " << person.GetName() << endl; 74 | } 75 | 76 | void Walk(const string& destination) const override { 77 | cout << "Policeman: " << GetName() << " walks to: " << destination << endl; 78 | } 79 | }; 80 | 81 | 82 | void VisitPlaces(Person& person, vector places) { 83 | for (const auto& p : places) { 84 | person.Walk(p); 85 | } 86 | } 87 | 88 | 89 | int main() { 90 | Teacher t("Jim", "Math"); 91 | Student s("Ann", "We will rock you"); 92 | Policeman p("Bob"); 93 | 94 | VisitPlaces(t, {"Moscow", "London"}); 95 | p.Check(s); 96 | VisitPlaces(s, {"Moscow", "London"}); 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /week-02/02-Practice-Programming-Assignment/test_equation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void AssertEqual(const T& t, const U& u, const std::string& hint = {}) { 6 | if (t != u) { 7 | std::ostringstream os; 8 | os << " AssertionError: " << t << " != " << u; 9 | if (!hint.empty()) { 10 | os << " hint: " << hint; 11 | } 12 | throw std::runtime_error(os.str()); 13 | } 14 | } 15 | 16 | class TestRunner { 17 | public: 18 | template 19 | void RunTest(TestFunc func, const std::string& test_name) { 20 | try { 21 | func(); 22 | std::cerr << " PASSED: " << test_name << std::endl; 23 | } catch (std::exception& e) { 24 | ++fail_count; 25 | std::cerr << " FAIL: " << test_name << e.what() << std::endl; 26 | } catch (...) { 27 | ++fail_count; 28 | std::cerr << "Unknown exception caught" << std::endl; 29 | } 30 | } 31 | 32 | ~TestRunner() { 33 | if (fail_count > 0) { 34 | std::cerr << "----------------------------------------------------------------------" << std::endl; 35 | std::cerr << "FAILED (failures=" << fail_count << ")" << std::endl; 36 | exit(1); 37 | } else { 38 | std::cerr << "----------------------------------------------------------------------" << std::endl; 39 | std::cerr << "OK" << std::endl; 40 | } 41 | } 42 | 43 | private: 44 | int fail_count = 0; 45 | }; 46 | 47 | int GetDistinctRealRootCount(double a, double b, double c) { 48 | // Вы можете вставлять сюда различные реализации функции, 49 | // чтобы проверить, что ваши тесты пропускают корректный код 50 | // и ловят некорректный 51 | } 52 | 53 | void TestPositiveDiscriminant() { 54 | AssertEqual(GetDistinctRealRootCount(2, 5, 2), 2); 55 | } 56 | 57 | void TestEqualZeroDiscriminant() { 58 | AssertEqual(GetDistinctRealRootCount(2, 4, 2), 1); 59 | } 60 | 61 | void TestNegativeDiscriminant() { 62 | AssertEqual(GetDistinctRealRootCount(2, 1, 2), 0); 63 | } 64 | 65 | void TestLinearEquation() { 66 | AssertEqual(GetDistinctRealRootCount(0, 4, 10), 1); 67 | } 68 | 69 | void TestNoRoot() { 70 | AssertEqual(GetDistinctRealRootCount(0, 0, 1), 0); 71 | } 72 | 73 | int main() { 74 | TestRunner runner; 75 | // добавьте сюда свои тесты 76 | runner.RunTest(TestPositiveDiscriminant, "TestPositiveDiscriminant"); 77 | runner.RunTest(TestEqualZeroDiscriminant, "TestEqualZeroDiscriminant"); 78 | runner.RunTest(TestNegativeDiscriminant, "TestNegativeDiscriminant"); 79 | runner.RunTest(TestLinearEquation, "TestLinearEquation"); 80 | runner.RunTest(TestNoRoot, "TestNoRoot"); 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /week-02/03-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Тесты для класса Person #### 2 | 3 | 4 | ##### Задача #### 5 | В первом курсе «Белый пояс по С++» у нас была задача «[Имена и фамилии — 1](https://www.coursera.org/learn/c-plus-plus-white/programming/4FQn4/imiena-i-familii-1)». В ней надо было разработать класс _Person_, поддерживающий историю изменений человеком своих фамилии и имени. В данной задаче вам надо разработать юнит-тесты на реализацию класса _Person_. При разработке тестов учитывайте ограничения, которые накладывает на класс _Person_ условие задачи «Имена и фамилии — 1». 6 | 7 | Начать работу вы можете с шаблона, который содержит наш фреймворк юнит-тестов и заготовку класса. 8 | 9 | [test_person.cpp](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-02/03-Practice-Programming-Assignment/Source/test_person.cpp) 10 | 11 | ##### Условие задачи «Имена и фамилии — 1» ##### 12 | Реализуйте класс для человека, поддерживающий историю изменений человеком своих фамилии и имени. 13 | 14 | ```objectivec 15 | class Person { 16 | public: 17 | void ChangeFirstName(int year, const string& first_name) { 18 | // добавить факт изменения имени на first_name в год year 19 | } 20 | void ChangeLastName(int year, const string& last_name) { 21 | // добавить факт изменения фамилии на last_name в год year 22 | } 23 | string GetFullName(int year) { 24 | // получить имя и фамилию по состоянию на конец года year 25 | } 26 | private: 27 | // приватные поля 28 | }; 29 | ``` 30 | Считайте, что в каждый год может произойти не более одного изменения фамилии и не более одного изменения имени. При этом с течением времени могут открываться всё новые факты из прошлого человека, поэтому года́ в последовательных вызовах методов _ChangeLastName_ и _ChangeFirstName_ не обязаны возрастать. 31 | 32 | Гарантируется, что все имена и фамилии непусты. 33 | 34 | Строка, возвращаемая методом _GetFullName_, должна содержать разделённые одним пробелом имя и фамилию человека по состоянию на конец данного года. 35 | 36 | * Если к данному году не случилось ни одного изменения фамилии и имени, верните строку **"Incognito"**. 37 | * Если к данному году случилось изменение фамилии, но не было ни одного изменения имени, верните **"last_name with unknown first name"**. 38 | * Если к данному году случилось изменение имени, но не было ни одного изменения фамилии, верните **"first_name with unknown last name"**. 39 | 40 | ##### Примечание ##### 41 | Перед отправкой вашего файла убедитесь, что он не содержит класса _Person_. В противном случае вы получите ошибку компиляции. Наша тестирующая система умеет игнорировать функции в файлах (поэтому, например, в задаче "Тесты для функции _IsPalindrom_" необязательно удалять функцию _IsPalindrom_), но не умеет это делать для классов. 42 | -------------------------------------------------------------------------------- /week-02/04-Programming-Assignment/Source/test_rational.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | template 12 | ostream& operator << (ostream& os, const vector& s) { 13 | os << "{"; 14 | bool first = true; 15 | for (const auto& x : s) { 16 | if (!first) { 17 | os << ", "; 18 | } 19 | first = false; 20 | os << x; 21 | } 22 | return os << "}"; 23 | } 24 | 25 | template 26 | ostream& operator << (ostream& os, const set& s) { 27 | os << "{"; 28 | bool first = true; 29 | for (const auto& x : s) { 30 | if (!first) { 31 | os << ", "; 32 | } 33 | first = false; 34 | os << x; 35 | } 36 | return os << "}"; 37 | } 38 | 39 | template 40 | ostream& operator << (ostream& os, const map& m) { 41 | os << "{"; 42 | bool first = true; 43 | for (const auto& kv : m) { 44 | if (!first) { 45 | os << ", "; 46 | } 47 | first = false; 48 | os << kv.first << ": " << kv.second; 49 | } 50 | return os << "}"; 51 | } 52 | 53 | template 54 | void AssertEqual(const T& t, const U& u, const string& hint = {}) { 55 | if (t != u) { 56 | ostringstream os; 57 | os << "Assertion failed: " << t << " != " << u; 58 | if (!hint.empty()) { 59 | os << " hint: " << hint; 60 | } 61 | throw runtime_error(os.str()); 62 | } 63 | } 64 | 65 | void Assert(bool b, const string& hint) { 66 | AssertEqual(b, true, hint); 67 | } 68 | 69 | class TestRunner { 70 | public: 71 | template 72 | void RunTest(TestFunc func, const string& test_name) { 73 | try { 74 | func(); 75 | cerr << test_name << " OK" << endl; 76 | } catch (exception& e) { 77 | ++fail_count; 78 | cerr << test_name << " fail: " << e.what() << endl; 79 | } catch (...) { 80 | ++fail_count; 81 | cerr << "Unknown exception caught" << endl; 82 | } 83 | } 84 | 85 | ~TestRunner() { 86 | if (fail_count > 0) { 87 | cerr << fail_count << " unit tests failed. Terminate" << endl; 88 | exit(1); 89 | } 90 | } 91 | 92 | private: 93 | int fail_count = 0; 94 | }; 95 | 96 | class Rational { 97 | public: 98 | // Вы можете вставлять сюда различные реализации, 99 | // чтобы проверить, что ваши тесты пропускают корректный код 100 | // и ловят некорректный 101 | 102 | Rational(); 103 | Rational(int numerator, int denominator) { 104 | } 105 | 106 | int Numerator() const { 107 | } 108 | 109 | int Denominator() const { 110 | } 111 | }; 112 | 113 | int main() { 114 | TestRunner runner; 115 | // добавьте сюда свои тесты 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /week-02/03-Practice-Programming-Assignment/Source/test_person.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | template 12 | ostream& operator << (ostream& os, const vector& s) { 13 | os << "{"; 14 | bool first = true; 15 | for (const auto& x : s) { 16 | if (!first) { 17 | os << ", "; 18 | } 19 | first = false; 20 | os << x; 21 | } 22 | return os << "}"; 23 | } 24 | 25 | template 26 | ostream& operator << (ostream& os, const set& s) { 27 | os << "{"; 28 | bool first = true; 29 | for (const auto& x : s) { 30 | if (!first) { 31 | os << ", "; 32 | } 33 | first = false; 34 | os << x; 35 | } 36 | return os << "}"; 37 | } 38 | 39 | template 40 | ostream& operator << (ostream& os, const map& m) { 41 | os << "{"; 42 | bool first = true; 43 | for (const auto& kv : m) { 44 | if (!first) { 45 | os << ", "; 46 | } 47 | first = false; 48 | os << kv.first << ": " << kv.second; 49 | } 50 | return os << "}"; 51 | } 52 | 53 | template 54 | void AssertEqual(const T& t, const U& u, const string& hint = {}) { 55 | if (t != u) { 56 | ostringstream os; 57 | os << "Assertion failed: " << t << " != " << u; 58 | if (!hint.empty()) { 59 | os << " hint: " << hint; 60 | } 61 | throw runtime_error(os.str()); 62 | } 63 | } 64 | 65 | void Assert(bool b, const string& hint) { 66 | AssertEqual(b, true, hint); 67 | } 68 | 69 | class TestRunner { 70 | public: 71 | template 72 | void RunTest(TestFunc func, const string& test_name) { 73 | try { 74 | func(); 75 | cerr << test_name << " OK" << endl; 76 | } catch (exception& e) { 77 | ++fail_count; 78 | cerr << test_name << " fail: " << e.what() << endl; 79 | } catch (...) { 80 | ++fail_count; 81 | cerr << "Unknown exception caught" << endl; 82 | } 83 | } 84 | 85 | ~TestRunner() { 86 | if (fail_count > 0) { 87 | cerr << fail_count << " unit tests failed. Terminate" << endl; 88 | exit(1); 89 | } 90 | } 91 | 92 | private: 93 | int fail_count = 0; 94 | }; 95 | 96 | class Person { 97 | public: 98 | // Вы можете вставлять сюда различные реализации класса, 99 | // чтобы проверить, что ваши тесты пропускают корректный код 100 | // и ловят некорректный 101 | void ChangeFirstName(int year, const string& first_name) { 102 | } 103 | void ChangeLastName(int year, const string& last_name) { 104 | } 105 | string GetFullName(int year) { 106 | } 107 | }; 108 | 109 | int main() { 110 | TestRunner runner; 111 | // добавьте сюда свои тесты 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /week-05/03-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Набор фигур #### 2 | 3 | 4 | Вам дана функция *main*, которая считывает из стандартного ввода команды по работе с набором геометрических фигур: 5 | ```objectivec 6 | int main() { 7 | vector> figures; 8 | for (string line; getline(cin, line); ) { 9 | istringstream is(line); 10 | 11 | string command; 12 | is >> command; 13 | if (command == "ADD") { 14 | figures.push_back(CreateFigure(is)); 15 | } else if (command == "PRINT") { 16 | for (const auto& current_figure : figures) { 17 | cout << fixed << setprecision(3) 18 | << current_figure->Name() << " " 19 | << current_figure->Perimeter() << " " 20 | << current_figure->Area() << endl; 21 | } 22 | } 23 | } 24 | return 0; 25 | } 26 | ``` 27 | Как видно из кода, есть два вида команд: 28 | * **ADD** — добавить фигуру в набор; 29 | * **PRINT** — для каждой фигуры в наборе распечатать название, периметр и площадь. 30 | 31 | Программа поддерживает три вида фигур: прямоугольник, треугольник и круг. Их добавление описывается так: 32 | 1. **ADD RECT *width* *height*** — добавить прямоугольник с размерами ***width*** и ***height*** (например, **ADD RECT *2* *3***). 33 | 2. **ADD TRIANGLE *a* *b* *c*** — добавить треугольник со сторонами ***a***, ***b*** и ***c*** (например, **ADD TRIANGLE *3* *4* *5***). 34 | 3. **ADD CIRCLE *r*** — добавить круг радиуса ***r*** (например, **ADD CIRCLE *5***). 35 | 36 | ##### Пример работы программы ##### 37 | ###### Ввод ###### 38 | ```commandline 39 | ADD RECT 2 3 40 | ADD TRIANGLE 3 4 5 41 | ADD RECT 10 20 42 | ADD CIRCLE 5 43 | PRINT 44 | ``` 45 | ###### Вывод ###### 46 | ```commandline 47 | RECT 10.000 6.000 48 | TRIANGLE 12.000 6.000 49 | RECT 60.000 200.000 50 | CIRCLE 31.400 78.500 51 | ``` 52 | 53 | **Не меняя функцию main**, реализуйте недостающие функции и классы: 54 | * базовый класс *Figure* с чисто виртуальными методами *Name*, *Perimeter* и *Area*; 55 | * классы *Triangle*, *Rect* и *Circle*, которые являются наследниками класса *Figure* и переопределяют его виртуальные методы; 56 | * функцию *CreateFigure*, которая в зависимости от содержимого входного потока создаёт *shared_ptr\*, *shared_ptr\* или *shared_ptr\*. 57 | 58 | Гарантируется, что все команды *ADD* корректны; размеры всех фигур — это натуральные числа не больше *1000*. В качестве значения π используйте *3,14*. 59 | 60 | ##### Как будет тестироваться ваш код ##### 61 | Автоматическая проверяющая система заменит в вашей программе функцию *main* на ту, которая приведена в условии задачи, скомпилирует получившийся файл и прогонит на наборе тестов. Кроме того, отдельно проверяется, что функция *CreateFigure* возвращает объект, созданный с помощью *make_shared\*, если во входном потоке задан прямоугольник, объект, созданный с помощью *make_shared\*, если во входном потоке задан круг, и т. д. -------------------------------------------------------------------------------- /week-03/04-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Декомпозиция программы — 2 #### 2 | 3 | 4 | В задаче [«Декомпозиция программы»](https://www.coursera.org/learn/c-plus-plus-yellow/programming/k6Xm2/diekompozitsiia-proghrammy) мы разбили монолитный код на набор функций и классов. Теперь мы сделаем ещё один шаг и разделим нашу программу на несколько файлов. В этой задаче вам нужно создать проект, состоящий из следующих файлов: 5 | 6 | 1. *query.h*, в него кладём: 7 | * enum class QueryType 8 | * struct Query 9 | * объявление istream& operator >> (istream& is, Query& q) 10 | 2. *query.cpp*, в него кладём 11 | * определение istream& operator >> (istream& is, Query& q); 12 | 3. *responses.h*: 13 | * struct BusesForStopResponse 14 | * ostream& operator << (ostream& os, const BusesForStopResponse& r) 15 | * struct StopsForBusResponse 16 | * ostream& operator << (ostream& os, const StopsForBusResponse& r) 17 | * struct AllBusesResponse 18 | * ostream& operator << (ostream& os, const AllBusesResponse& r) 19 | 4. *responses.cpp*: определения всего, что объявлено в *responses.h* 20 | 5. *bus_manager.h*: объявление класса *BusManager* 21 | 6. *bus_manager.cpp*: определения методов класса *BusManager* 22 | 7. *main.cpp*: функция *main* 23 | 24 | ##### Как отправлять проект на проверку ##### 25 | В заданиях по программированию *Coursera* позволяет отправлять на проверку только один файл, поэтому для того, чтобы сдать свой проект в тестирующую систему, вам надо запаковать все свои файлы в архив и отправить его на проверку. Поддерживаемые форматы архивов: *rar*, *zip*, *7z*, *tar*, *tar.gz*, а также многие другие (для распаковки мы используем программу [dtrx](http://manpages.ubuntu.com/manpages/trusty/en/man1/dtrx.1.html), на странице с её описанием приведён полный список поддерживаемых форматов). 26 | 27 | ##### Как будет тестироваться ваше решение ##### 28 | Ниже вам дана заготовка для файла *main.cpp*, содержащая функцию *main*. Это точно такая же заготовка, которая была дана в задаче «Декомпозиция программы». Тестирование вашего решения будет выполняться в два этапа. На первом этапе автоматическая тестирующая система распакует присланный вами архив и соберёт извлечённые файлы в исполняемый файл. При этом функция *main* в вашем проекте будет заменена на ту, которая дана в заготовке файла *main.cpp*. Затем этот исполняемый файл будет запущен на наборе тестов. Тестирование выполняется так же, как и для большинства задач на нашем курсе: тест подаётся в *stdin*, замеряется время выполнения программы, а затем анализируется *stdout*. 29 | 30 | На втором этапе будет выполняться тестирование отдельных файлов вашего проекта. Проверяется, что файл *query.h* действительно содержит перечислимый тип *QueryType*, что *BusManager::GetBusesForStop* возвращает корректно сформированный объект *BusesForStopResponse* т.д. 31 | 32 | Заготовка файла *main.cpp*: 33 | 34 | [main.cpp](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-03/04-Programming-Assignment/Source/main.cpp) 35 | -------------------------------------------------------------------------------- /week-05/03-Programming-Assignment/figures.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | 10 | class Figure { 11 | public: 12 | virtual string Name() const = 0; 13 | virtual double Perimeter() const = 0; 14 | virtual double Area() const = 0; 15 | }; 16 | 17 | class Triangle : public Figure { 18 | public: 19 | Triangle(const double& a, const double& b, const double& c) : a_(a), b_(b), c_(c) {} 20 | 21 | string Name() const override { 22 | return "TRIANGLE"; 23 | } 24 | double Perimeter() const override { 25 | return a_ + b_ + c_; 26 | } 27 | double Area() const override { 28 | double p = (a_ + b_ + c_) / 2; 29 | return sqrt(p * (p - a_) * (p - b_) * (p - c_)); 30 | } 31 | 32 | private: 33 | double a_, b_, c_; 34 | }; 35 | 36 | class Rect : public Figure { 37 | public: 38 | Rect(const double& width, const double& height) : width_(width), height_(height) {} 39 | 40 | string Name() const override { 41 | return "RECT"; 42 | } 43 | double Perimeter() const override { 44 | return (width_ + height_) * 2; 45 | } 46 | double Area() const override { 47 | return width_ * height_; 48 | } 49 | 50 | private: 51 | double width_, height_; 52 | }; 53 | 54 | class Circle : public Figure { 55 | public: 56 | Circle(const double& r) : r_(r) {} 57 | 58 | string Name() const override { 59 | return "CIRCLE"; 60 | } 61 | double Perimeter() const override { 62 | return 2 * 3.14 * r_; 63 | } 64 | double Area() const override { 65 | return 3.14 * r_ * r_; 66 | } 67 | 68 | private: 69 | double r_; 70 | }; 71 | 72 | shared_ptr
CreateFigure(istringstream& is) { 73 | string typeStr; 74 | is >> typeStr; 75 | if (typeStr == "RECT") { 76 | double width, height; 77 | is >> width >> height; 78 | return make_shared(width, height); 79 | } else if (typeStr == "TRIANGLE") { 80 | double a, b, c; 81 | is >> a >> b >> c; 82 | return make_shared(a, b, c); 83 | } else { 84 | double r; 85 | is >> r; 86 | return make_shared(r); 87 | } 88 | 89 | } 90 | 91 | int main() { 92 | vector> figures; 93 | for (string line; getline(cin, line); ) { 94 | istringstream is(line); 95 | 96 | string command; 97 | is >> command; 98 | if (command == "ADD") { 99 | figures.push_back(CreateFigure(is)); 100 | } else if (command == "PRINT") { 101 | for (const auto& current_figure : figures) { 102 | cout << fixed << setprecision(3) 103 | << current_figure->Name() << " " 104 | << current_figure->Perimeter() << " " 105 | << current_figure->Area() << endl; 106 | } 107 | } 108 | } 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /week-01/03-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: База регионов #### 2 | 3 | 4 | Имеется база регионов, представленная вектором структур _Region_: 5 | ```objectivec 6 | struct Region { 7 | string std_name; 8 | string parent_std_name; 9 | map names; 10 | int64_t population; 11 | }; 12 | 13 | ``` 14 | Здесь _Lang_ — идентификатор языка: 15 | ```objectivec 16 | enum class Lang { 17 | DE, FR, IT 18 | }; 19 | 20 | ``` 21 | Напишите функцию _FindMaxRepetitionCount_, принимающую базу регионов и определяющую, какое максимальное количество повторов она содержит. Две записи (объекты типа _Region_) считаются различными, если они отличаются хотя бы одним полем. 22 | ```objectivec 23 | int FindMaxRepetitionCount(const vector& regions); 24 | ``` 25 | Если все записи уникальны, считайте максимальное количество повторов равным 1. Если записи отсутствуют, верните 0. Гарантируется, что типа int достаточно для хранения ответа. 26 | 27 | ##### Пример кода ##### 28 | ```objectivec 29 | int main() { 30 | cout << FindMaxRepetitionCount({ 31 | { 32 | "Moscow", 33 | "Russia", 34 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 35 | 89 36 | }, { 37 | "Russia", 38 | "Eurasia", 39 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 40 | 89 41 | }, { 42 | "Moscow", 43 | "Russia", 44 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 45 | 89 46 | }, { 47 | "Moscow", 48 | "Russia", 49 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 50 | 89 51 | }, { 52 | "Russia", 53 | "Eurasia", 54 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 55 | 89 56 | }, 57 | }) << endl; 58 | 59 | cout << FindMaxRepetitionCount({ 60 | { 61 | "Moscow", 62 | "Russia", 63 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 64 | 89 65 | }, { 66 | "Russia", 67 | "Eurasia", 68 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 69 | 89 70 | }, { 71 | "Moscow", 72 | "Russia", 73 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou deux"}, {Lang::IT, "Mosca"}}, 74 | 89 75 | }, { 76 | "Moscow", 77 | "Toulouse", 78 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 79 | 89 80 | }, { 81 | "Moscow", 82 | "Russia", 83 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 84 | 31 85 | }, 86 | }) << endl; 87 | 88 | return 0; 89 | } 90 | 91 | ``` 92 | 93 | ###### Вывод ###### 94 | ```commandline 95 | 3 96 | 1 97 | ``` 98 | ##### Пояснение ##### 99 | В этой задаче вам надо прислать на проверку файл с реализацией функции _FindMaxRepetitionCount_, а также дополнительных функций, если это необходим. __Этот файл не должен содержать функцию main и типы Lang и Region__. В противном случае вы получите ошибку компиляции. -------------------------------------------------------------------------------- /week-05/03-Programming-Assignment/Solution/figures.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | class Figure { 12 | public: 13 | virtual string Name() const = 0; 14 | virtual double Perimeter() const = 0; 15 | virtual double Area() const = 0; 16 | }; 17 | 18 | class Rect : public Figure { 19 | public: 20 | Rect(int width, int height) : width_(width), height_(height) { 21 | } 22 | 23 | string Name() const override { return "RECT"; } 24 | 25 | double Perimeter() const override { 26 | return 2 * (width_ + height_); 27 | } 28 | 29 | double Area() const override { 30 | return width_ * height_; 31 | } 32 | 33 | private: 34 | int width_, height_; 35 | }; 36 | 37 | class Triangle : public Figure { 38 | public: 39 | Triangle(int side_one, int side_two, int side_three) 40 | : side_one_(side_one) 41 | , side_two_(side_two) 42 | , side_three_(side_three) 43 | { 44 | } 45 | 46 | string Name() const override { return "TRIANGLE"; } 47 | 48 | double Perimeter() const override { 49 | return side_one_ + side_two_ + side_three_; 50 | } 51 | 52 | double Area() const override { 53 | double p = Perimeter() / 2.0; 54 | return sqrt(p * (p - side_one_) * (p - side_two_) * (p - side_three_)); 55 | } 56 | 57 | private: 58 | int side_one_, side_two_, side_three_; 59 | }; 60 | 61 | class Circle : public Figure { 62 | public: 63 | Circle(double radius) : radius_(radius) 64 | { 65 | } 66 | 67 | string Name() const override { return "CIRCLE"; } 68 | 69 | double Perimeter() const override { 70 | return 2 * pi_ * radius_; 71 | } 72 | 73 | double Area() const override { 74 | return pi_ * radius_ * radius_; 75 | } 76 | 77 | private: 78 | const double pi_ = 3.14; 79 | double radius_; 80 | }; 81 | 82 | shared_ptr
CreateFigure(istream& input_stream) { 83 | string type; 84 | input_stream >> type; 85 | if (type == "RECT") { 86 | int width, height; 87 | input_stream >> width >> height; 88 | return make_shared(width, height); 89 | } else if (type == "TRIANGLE") { 90 | int side_one, side_two, side_three; 91 | input_stream >> side_one >> side_two >> side_three; 92 | return make_shared(side_one, side_two, side_three); 93 | } else { 94 | int radius; 95 | input_stream >> radius; 96 | return make_shared(radius); 97 | } 98 | } 99 | 100 | int main() { 101 | vector> figures; 102 | for (string line; getline(cin, line); ) { 103 | istringstream is(line); 104 | 105 | string command; 106 | is >> command; 107 | if (command == "ADD") { 108 | figures.push_back(CreateFigure(is)); 109 | } else if (command == "PRINT") { 110 | for (const auto& current_figure : figures) { 111 | cout << fixed << setprecision(3) 112 | << current_figure->Name() << " " 113 | << current_figure->Perimeter() << " " 114 | << current_figure->Area() << endl; 115 | } 116 | } 117 | } 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /week-04/06-Practice-Programming-Assignment/print_stats.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | enum class Gender { 7 | FEMALE, 8 | MALE 9 | }; 10 | 11 | struct Person { 12 | int age; // возраст 13 | Gender gender; // пол 14 | bool is_employed; // имеет ли работу 15 | }; 16 | 17 | // Это пример функции, его не нужно отправлять вместе с функцией PrintStats 18 | template 19 | int ComputeMedianAge(InputIt range_begin, InputIt range_end) { 20 | if (range_begin == range_end) { 21 | return 0; 22 | } 23 | std::vector range_copy(range_begin, range_end); 24 | auto middle = begin(range_copy) + range_copy.size() / 2; 25 | std::nth_element( 26 | begin(range_copy), middle, end(range_copy), 27 | [](const Person& lhs, const Person& rhs) { 28 | return lhs.age < rhs.age; 29 | } 30 | ); 31 | return middle->age; 32 | } 33 | 34 | void PrintStats(std::vector persons) { 35 | std::cout << "Median age = " << ComputeMedianAge(std::begin(persons), std::end(persons)) << std::endl; 36 | 37 | auto females = std::partition(std::begin(persons), std::end(persons), [](const Person& p) { 38 | return p.gender == Gender::FEMALE; 39 | }); 40 | int median_females = ComputeMedianAge(std::begin(persons), females); 41 | 42 | auto employed_females = std::partition(std::begin(persons), females, [](const Person& p) { 43 | return p.is_employed; 44 | }); 45 | int median_employed_females = ComputeMedianAge(std::begin(persons), employed_females); 46 | int median_unemployed_females = ComputeMedianAge(employed_females, females); 47 | 48 | 49 | auto males = std::partition(std::begin(persons), std::end(persons), [](const Person& p) { 50 | return p.gender == Gender::MALE; 51 | }); 52 | int median_males = ComputeMedianAge(std::begin(persons), males); 53 | 54 | auto employed_males = std::partition(std::begin(persons), males, [](const Person& p) { 55 | return p.is_employed; 56 | }); 57 | int median_employed_males = ComputeMedianAge(std::begin(persons), employed_males); 58 | int median_unemployed_males = ComputeMedianAge(employed_males, males); 59 | 60 | std::cout << "Median age for females = " << median_females << std::endl; 61 | std::cout << "Median age for males = " << median_males << std::endl; 62 | std::cout << "Median age for employed females = " << median_employed_females << std::endl; 63 | std::cout << "Median age for unemployed females = " << median_unemployed_females << std::endl; 64 | std::cout << "Median age for employed males = " << median_employed_males << std::endl; 65 | std::cout << "Median age for unemployed males = " << median_unemployed_males << std::endl; 66 | 67 | } 68 | 69 | int main() { 70 | std::vector persons = { 71 | {31, Gender::MALE, false}, 72 | {40, Gender::FEMALE, true}, 73 | {24, Gender::MALE, true}, 74 | {20, Gender::FEMALE, true}, 75 | {80, Gender::FEMALE, false}, 76 | {78, Gender::MALE, false}, 77 | {10, Gender::FEMALE, false}, 78 | {55, Gender::MALE, true}, 79 | }; 80 | PrintStats(persons); 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /week-04/07-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Сортировка слиянием #### 2 | 3 | 4 | Напишите шаблонную функцию *MergeSort*, принимающую два итератора шаблонного типа *RandomIt* и сортирующую заданный ими диапазон с помощью сортировки слиянием. Гарантируется, что: 5 | * итераторы типа *RandomIt* аналогичны по функциональности итераторам вектора и строки, то есть их можно сравнивать с помощью операторов <, <=, > и >=, а также вычитать и складывать с числами; 6 | * сортируемые объекты можно сравнивать с помощью оператора <. 7 | 8 | ```objectivec 9 | template 10 | void MergeSort(RandomIt range_begin, RandomIt range_end); 11 | ``` 12 | #### Часть 1. Реализация с разбиением на 2 части #### 13 | ##### Алгоритм ##### 14 | Классический алгоритм сортировки слиянием выглядит следующим образом: 15 | 16 | 1. Если диапазон содержит меньше 2 элементов, выйти из функции. 17 | 2. Создать вектор, содержащий все элементы текущего диапазона. 18 | 3. Разбить вектор на две равные части. *(В этой задаче гарантируется, что длина передаваемого диапазона является степенью двойки, так что вектор всегда можно разбить на две равные части.)* 19 | 4. Вызвать функцию *MergeSort* от каждой половины вектора. 20 | 5. С помощью алгоритма *merge* слить отсортированные половины, записав полученный отсортированный диапазон вместо исходного. 21 | 22 | Вы должны реализовать **именно этот алгоритм** и никакой другой: тестирующая система будет проверять, что вы выполняете с элементами именно эти действия. 23 | 24 | ##### Подсказка ##### 25 | Чтобы создать вектор, содержащий все элементы текущего диапазона (п. 2 алгоритма), необходимо уметь по типу итератора узнавать тип элементов, на которые он указывает. Если итератор *RandomIt* принадлежит стандартному контейнеру (вектору, строке, множеству, словарю...), нижележащий тип можно получить с помощью выражения *typename RandomIt::value_type*. Таким образом, гарантируется, что создать вектор в п. 2 можно следующим образом: 26 | ```objectivec 27 | vector elements(range_begin, range_end); 28 | ``` 29 | ##### Пример кода ##### 30 | ```objectivec 31 | int main() { 32 | vector v = {6, 4, 7, 6, 4, 4, 0, 1}; 33 | MergeSort(begin(v), end(v)); 34 | for (int x : v) { 35 | cout << x << " "; 36 | } 37 | cout << endl; 38 | return 0; 39 | } 40 | ``` 41 | ###### Вывод ###### 42 | ```commandline 43 | 0 1 4 4 4 6 6 7 44 | ``` 45 | 46 | #### Часть 2. Реализация с разбиением на 3 части #### 47 | Реализуйте сортировку слиянием, разбивая диапазон на 3 равные части, а не на 2. Гарантируется, что длина исходного диапазона является степенью 3. 48 | 49 | Соответственно, пункты 3–5 алгоритма нужно заменить следующими: 50 | 51 | * Разбить вектор на 3 равные части. 52 | * Вызвать функцию *MergeSort* от каждой части вектора. 53 | * Слить первые две трети вектора с помощью алгоритма *merge*, сохранив результат во временный вектор с помощью *back_inserter*. 54 | * Слить временный вектор из предыдущего пункта с последней третью вектора из п. 2, записав полученный отсортированный диапазон вместо исходного. 55 | 56 | ##### Пример кода ##### 57 | ```objectivec 58 | int main() { 59 | vector v = {6, 4, 7, 6, 4, 4, 0, 1, 5}; 60 | MergeSort(begin(v), end(v)); 61 | for (int x : v) { 62 | cout << x << " "; 63 | } 64 | cout << endl; 65 | return 0; 66 | } 67 | ``` 68 | ###### Вывод ###### 69 | ```commandline 70 | 0 1 4 4 4 5 6 6 7 71 | ``` -------------------------------------------------------------------------------- /week-02/05-Programming-Assignment/Solution/test_palindrome.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | template 13 | ostream& operator << (ostream& os, const vector& s) { 14 | os << "{"; 15 | bool first = true; 16 | for (const auto& x : s) { 17 | if (!first) { 18 | os << ", "; 19 | } 20 | first = false; 21 | os << x; 22 | } 23 | return os << "}"; 24 | } 25 | 26 | template 27 | ostream& operator << (ostream& os, const set& s) { 28 | os << "{"; 29 | bool first = true; 30 | for (const auto& x : s) { 31 | if (!first) { 32 | os << ", "; 33 | } 34 | first = false; 35 | os << x; 36 | } 37 | return os << "}"; 38 | } 39 | 40 | template 41 | ostream& operator << (ostream& os, const map& m) { 42 | os << "{"; 43 | bool first = true; 44 | for (const auto& kv : m) { 45 | if (!first) { 46 | os << ", "; 47 | } 48 | first = false; 49 | os << kv.first << ": " << kv.second; 50 | } 51 | return os << "}"; 52 | } 53 | 54 | template 55 | void AssertEqual(const T& t, const U& u, const string& hint = {}) { 56 | if (t != u) { 57 | ostringstream os; 58 | os << "Assertion failed: " << t << " != " << u; 59 | if (!hint.empty()) { 60 | os << " hint: " << hint; 61 | } 62 | throw runtime_error(os.str()); 63 | } 64 | } 65 | 66 | void Assert(bool b, const string& hint) { 67 | AssertEqual(b, true, hint); 68 | } 69 | 70 | class TestRunner { 71 | public: 72 | template 73 | void RunTest(TestFunc func, const string& test_name) { 74 | try { 75 | func(); 76 | cerr << test_name << " OK" << endl; 77 | } catch (exception& e) { 78 | ++fail_count; 79 | cerr << test_name << " fail: " << e.what() << endl; 80 | } catch (...) { 81 | ++fail_count; 82 | cerr << "Unknown exception caught" << endl; 83 | } 84 | } 85 | 86 | ~TestRunner() { 87 | if (fail_count > 0) { 88 | cerr << fail_count << " unit tests failed. Terminate" << endl; 89 | exit(1); 90 | } 91 | } 92 | 93 | private: 94 | int fail_count = 0; 95 | }; 96 | 97 | void TestIsPalindrom() { 98 | Assert(IsPalindrom(""), "empty string is a palindrome"); 99 | Assert(IsPalindrom("a"), "one letter string is a palindrome"); 100 | Assert(IsPalindrom("abba"), "abba is a palindrome"); 101 | Assert(IsPalindrom("abXba"), "abXba is a palindrome"); 102 | Assert(IsPalindrom("a b X b a"), "`a b X b a` is a palindrome"); 103 | Assert(IsPalindrom(" ABBA "), "` ABBA ` is a palindrome"); 104 | 105 | Assert(!IsPalindrom("XabbaY"), "XabbaY is not a palindrome"); 106 | Assert(!IsPalindrom("abXYba"), "abXYba is not a palindrome"); 107 | Assert(!IsPalindrom("Xabba"), "Xabba is not a palindrome"); 108 | Assert(!IsPalindrom("abbaX"), "abbaX is not a palindrome"); 109 | Assert( 110 | !IsPalindrom("was it a car or a cat i saw"), 111 | "`was it a car or a cat i saw` is not a palindrome because spaces do not match" 112 | ); 113 | Assert(!IsPalindrom("ABBA "), "`ABBA ` is not a palindrome"); 114 | Assert(!IsPalindrom(" ABBA"), "` ABBA` is not a palindrome"); 115 | } 116 | 117 | int main() { 118 | TestRunner runner; 119 | runner.RunTest(TestIsPalindrom, "TestIsPalindrom"); 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /week-04/06-Practice-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Тренировочное задание по программированию: Демографические показатели #### 2 | 3 | 4 | В этой задаче вам необходимо вычислить различные демографические показатели для группы людей. Человек представляется структурой *Person*: 5 | ```objectivec 6 | struct Person { 7 | int age; // возраст 8 | Gender gender; // пол 9 | bool is_employed; // имеет ли работу 10 | }; 11 | ``` 12 | Тип *Gender* определён следующим образом: 13 | ```objectivec 14 | enum class Gender { 15 | FEMALE, 16 | MALE 17 | }; 18 | ``` 19 | Вам необходимо написать функцию *PrintStats*, получающую вектор людей, вычисляющую и выводящую медианный возраст для каждой из следующих групп людей: 20 | * все люди; 21 | * все женщины; 22 | * все мужчины; 23 | * все безработные женщины; 24 | * все занятые женщины; 25 | * все безработные мужчины; 26 | * все занятые мужчины. 27 | 28 | Все 7 чисел нужно вывести в строгом соответствии с форматом (см. пример). 29 | ```objectivec 30 | void PrintStats(vector persons); 31 | ``` 32 | Принимая вектор по значению (а не по константной ссылке), вы получаете возможность модифицировать его копию произвольным образом и тем самым проще произвести вычисления. 33 | 34 | ##### Подсказка ##### 35 | Используйте алгоритм *partition*. 36 | 37 | ##### Вычисление медианного возраста ##### 38 | Для вычисления медианного возраста группы людей вы должны использовать функцию *ComputeMedianAge*: 39 | ```objectivec 40 | template 41 | int ComputeMedianAge(InputIt range_begin, InputIt range_end); 42 | ``` 43 | **Эту функцию не нужно реализовывать самостоятельно:** мы реализовали её за вас и автоматически добавим к каждому вашему решению. 44 | 45 | Функцию *ComputeMedianAge* можно вызвать и для пустого набора людей: её результат в этом случае и нужно считать медианным возрастом пустого набора людей. 46 | 47 | ##### Пример кода ##### 48 | ```objectivec 49 | // Это пример функции, его не нужно отправлять вместе с функцией PrintStats 50 | template 51 | int ComputeMedianAge(InputIt range_begin, InputIt range_end) { 52 | if (range_begin == range_end) { 53 | return 0; 54 | } 55 | vector range_copy(range_begin, range_end); 56 | auto middle = begin(range_copy) + range_copy.size() / 2; 57 | nth_element( 58 | begin(range_copy), middle, end(range_copy), 59 | [](const Person& lhs, const Person& rhs) { 60 | return lhs.age < rhs.age; 61 | } 62 | ); 63 | return middle->age; 64 | } 65 | 66 | void PrintStats(vector persons); 67 | 68 | int main() { 69 | vector persons = { 70 | {31, Gender::MALE, false}, 71 | {40, Gender::FEMALE, true}, 72 | {24, Gender::MALE, true}, 73 | {20, Gender::FEMALE, true}, 74 | {80, Gender::FEMALE, false}, 75 | {78, Gender::MALE, false}, 76 | {10, Gender::FEMALE, false}, 77 | {55, Gender::MALE, true}, 78 | }; 79 | PrintStats(persons); 80 | return 0; 81 | } 82 | ``` 83 | ###### Вывод ###### 84 | ```commandline 85 | Median age = 40 86 | Median age for females = 40 87 | Median age for males = 55 88 | Median age for employed females = 40 89 | Median age for unemployed females = 80 90 | Median age for employed males = 55 91 | Median age for unemployed males = 78 92 | ``` 93 | 94 | ##### Пояснение ##### 95 | В этой задаче вам надо прислать на проверку файл с реализацией функции *PrintStats*. **Этот файл не должен содержать определения функции ComputeMedianAge и типов Person и Gender**. В противном случае вы получите ошибку компиляции. 96 | 97 | Гарантируется, что типы *Person* и *Gender* объявлены в точности так же, как в коде выше. -------------------------------------------------------------------------------- /week-02/04-Programming-Assignment/test_rational.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void AssertEqual(const T& t, const U& u, const std::string& hint = {}) { 6 | if (t != u) { 7 | std::ostringstream os; 8 | os << " AssertionError: " << t << " != " << u; 9 | if (!hint.empty()) { 10 | os << " hint: " << hint; 11 | } 12 | throw std::runtime_error(os.str()); 13 | } 14 | } 15 | 16 | class TestRunner { 17 | public: 18 | template 19 | void RunTest(TestFunc func, const std::string& test_name) { 20 | try { 21 | func(); 22 | std::cerr << " PASSED: " << test_name << std::endl; 23 | } catch (std::exception& e) { 24 | ++fail_count; 25 | std::cerr << " FAIL: " << test_name << e.what() << std::endl; 26 | } catch (...) { 27 | ++fail_count; 28 | std::cerr << "Unknown exception caught" << std::endl; 29 | } 30 | } 31 | 32 | ~TestRunner() { 33 | if (fail_count > 0) { 34 | std::cerr << "----------------------------------------------------------------------" << std::endl; 35 | std::cerr << "FAILED (failures=" << fail_count << ")" << std::endl; 36 | exit(1); 37 | } else { 38 | std::cerr << "----------------------------------------------------------------------" << std::endl; 39 | std::cerr << "OK" << std::endl; 40 | } 41 | } 42 | 43 | private: 44 | int fail_count = 0; 45 | }; 46 | 47 | class Rational { 48 | public: 49 | // Вы можете вставлять сюда различные реализации, 50 | // чтобы проверить, что ваши тесты пропускают корректный код 51 | // и ловят некорректный 52 | 53 | Rational(); 54 | Rational(int numerator, int denominator) { 55 | } 56 | 57 | int Numerator() const { 58 | } 59 | 60 | int Denominator() const { 61 | } 62 | }; 63 | 64 | void TestRational() { 65 | const Rational r(3, 10); 66 | AssertEqual(r.Numerator(), 3); 67 | AssertEqual(r.Denominator(), 10); 68 | } 69 | 70 | void TestTruncateRational() { 71 | const Rational r(8, 12); 72 | AssertEqual(r.Numerator(), 2); 73 | AssertEqual(r.Denominator(), 3); 74 | } 75 | 76 | void TestNegativeNumenator() { 77 | const Rational r(-4, 6); 78 | AssertEqual(r.Numerator(), -2); 79 | AssertEqual(r.Denominator(), 3); 80 | } 81 | 82 | void TestNegativeDenominator() { 83 | const Rational r(4, -6); 84 | AssertEqual(r.Numerator(), -2); 85 | AssertEqual(r.Denominator(), 3); 86 | } 87 | 88 | void TestBothNegative() { 89 | const Rational r(-2, -3); 90 | AssertEqual(r.Numerator(), 2); 91 | AssertEqual(r.Denominator(), 3); 92 | } 93 | 94 | void TestZeroNumenator() { 95 | const Rational r(0, 15); 96 | AssertEqual(r.Numerator(), 0); 97 | AssertEqual(r.Denominator(), 1); 98 | } 99 | 100 | void TestDefaultConstructed() { 101 | Rational r = Rational(); 102 | AssertEqual(r.Numerator(), 0); 103 | AssertEqual(r.Denominator(), 1); 104 | } 105 | 106 | int main() { 107 | TestRunner runner; 108 | // добавьте сюда свои тесты 109 | runner.RunTest(TestRational, "TestRational"); 110 | runner.RunTest(TestTruncateRational, "TestTruncateRational"); 111 | runner.RunTest(TestNegativeNumenator, "TestNegativeNumenator"); 112 | runner.RunTest(TestNegativeDenominator, "TestNegativeDenominator"); 113 | runner.RunTest(TestBothNegative, "TestBothNegative"); 114 | runner.RunTest(TestZeroNumenator, "TestZeroNumenator"); 115 | runner.RunTest(TestDefaultConstructed, "TestDefaultConstructed"); 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /week-04/10-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Группировка строк по префиксу #### 2 | 3 | 4 | #### Часть 1. Группировка по символу #### 5 | Напишите функцию *FindStartsWith*: 6 | 7 | * принимающую отсортированный набор строк в виде итераторов *range_begin*, *range_end* и один символ *prefix*; 8 | * возвращающую диапазон строк, начинающихся с символа *prefix*, в виде пары итераторов. 9 | ```objectivec 10 | template 11 | pair FindStartsWith( 12 | RandomIt range_begin, RandomIt range_end, 13 | char prefix); 14 | ``` 15 | Если итоговый диапазон пуст, его границы должны указывать на то место в контейнере, куда можно без нарушения порядка сортировки вставить любую строку, начинающуюся с символа *prefix* (подобно алгоритму *equal_range*). Гарантируется, что строки состоят лишь из строчных латинских букв и символ *prefix* также является строчной латинской буквой. 16 | 17 | Поиск должен осуществляться за логарифмическую сложность — например, с помощью двоичного поиска. 18 | 19 | ##### Пример кода ##### 20 | ```objectivec 21 | int main() { 22 | const vector sorted_strings = {"moscow", "murmansk", "vologda"}; 23 | 24 | const auto m_result = 25 | FindStartsWith(begin(sorted_strings), end(sorted_strings), 'm'); 26 | for (auto it = m_result.first; it != m_result.second; ++it) { 27 | cout << *it << " "; 28 | } 29 | cout << endl; 30 | 31 | const auto p_result = 32 | FindStartsWith(begin(sorted_strings), end(sorted_strings), 'p'); 33 | cout << (p_result.first - begin(sorted_strings)) << " " << 34 | (p_result.second - begin(sorted_strings)) << endl; 35 | 36 | const auto z_result = 37 | FindStartsWith(begin(sorted_strings), end(sorted_strings), 'z'); 38 | cout << (z_result.first - begin(sorted_strings)) << " " << 39 | (z_result.second - begin(sorted_strings)) << endl; 40 | 41 | return 0; 42 | } 43 | ``` 44 | ###### Вывод ###### 45 | ```commandline 46 | moscow murmansk 47 | 2 2 48 | 3 3 49 | ``` 50 | 51 | ##### Подсказка ##### 52 | К символам (*char*) можно прибавлять или вычитать числа, получая таким образом следующие или предыдущие буквы в алфавитном порядке. Например, для строки *s* выражение *--s[0]* заменит её первую букву на предыдущую. 53 | 54 | Обратите внимание, что выражение *'a' + 1* имеет тип *int* и поэтому может понадобиться привести его к типу *char* с помощью *static_cast*. 55 | 56 | #### Часть 2. Группировка по префиксу #### 57 | Напишите более универсальный вариант функции *FindStartsWith*, принимающий в качестве префикса произвольную строку, состоящую из строчных латинских букв. 58 | ```objectivec 59 | template 60 | pair FindStartsWith( 61 | RandomIt range_begin, RandomIt range_end, 62 | const string& prefix); 63 | 64 | ``` 65 | 66 | ##### Пример кода ##### 67 | ```objectivec 68 | int main() { 69 | const vector sorted_strings = {"moscow", "motovilikha", "murmansk"}; 70 | 71 | const auto mo_result = 72 | FindStartsWith(begin(sorted_strings), end(sorted_strings), "mo"); 73 | for (auto it = mo_result.first; it != mo_result.second; ++it) { 74 | cout << *it << " "; 75 | } 76 | cout << endl; 77 | 78 | const auto mt_result = 79 | FindStartsWith(begin(sorted_strings), end(sorted_strings), "mt"); 80 | cout << (mt_result.first - begin(sorted_strings)) << " " << 81 | (mt_result.second - begin(sorted_strings)) << endl; 82 | 83 | const auto na_result = 84 | FindStartsWith(begin(sorted_strings), end(sorted_strings), "na"); 85 | cout << (na_result.first - begin(sorted_strings)) << " " << 86 | (na_result.second - begin(sorted_strings)) << endl; 87 | 88 | return 0; 89 | } 90 | ``` 91 | ###### Вывод ###### 92 | ```commandline 93 | moscow motovilikha 94 | 2 2 95 | 3 3 96 | ``` -------------------------------------------------------------------------------- /week-02/03-Practice-Programming-Assignment/Solution/test_person.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | template 14 | ostream &operator<<(ostream &os, const vector &s) { 15 | os << "{"; 16 | bool first = true; 17 | for (const auto &x : s) { 18 | if (!first) { 19 | os << ", "; 20 | } 21 | first = false; 22 | os << x; 23 | } 24 | return os << "}"; 25 | } 26 | 27 | template 28 | ostream &operator<<(ostream &os, const set &s) { 29 | os << "{"; 30 | bool first = true; 31 | for (const auto &x : s) { 32 | if (!first) { 33 | os << ", "; 34 | } 35 | first = false; 36 | os << x; 37 | } 38 | return os << "}"; 39 | } 40 | 41 | template 42 | ostream &operator<<(ostream &os, const map &m) { 43 | os << "{"; 44 | bool first = true; 45 | for (const auto &kv : m) { 46 | if (!first) { 47 | os << ", "; 48 | } 49 | first = false; 50 | os << kv.first << ": " << kv.second; 51 | } 52 | return os << "}"; 53 | } 54 | 55 | template 56 | void AssertEqual(const T &t, const U &u, const string &hint = {}) { 57 | if (t != u) { 58 | ostringstream os; 59 | os << "Assertion failed: " << t << " != " << u; 60 | if (!hint.empty()) { 61 | os << " hint: " << hint; 62 | } 63 | throw runtime_error(os.str()); 64 | } 65 | } 66 | 67 | void Assert(bool b, const string &hint) { AssertEqual(b, true, hint); } 68 | 69 | class TestRunner { 70 | public: 71 | template 72 | void RunTest(TestFunc func, const string &test_name) { 73 | try { 74 | func(); 75 | cerr << test_name << " OK" << endl; 76 | } catch (exception &e) { 77 | ++fail_count; 78 | cerr << test_name << " fail: " << e.what() << endl; 79 | } catch (...) { 80 | ++fail_count; 81 | cerr << "Unknown exception caught" << endl; 82 | } 83 | } 84 | 85 | ~TestRunner() { 86 | if (fail_count > 0) { 87 | cerr << fail_count << " unit tests failed. Terminate" << endl; 88 | exit(1); 89 | } 90 | } 91 | 92 | private: 93 | int fail_count = 0; 94 | }; 95 | 96 | void TestPredefinedLastNameFirst() { 97 | Person person; 98 | 99 | person.ChangeLastName(1965, "Sergeeva"); 100 | person.ChangeFirstName(1967, "Polina"); 101 | 102 | AssertEqual(person.GetFullName(1964), "Incognito"); 103 | AssertEqual(person.GetFullName(1966), "Sergeeva with unknown first name"); 104 | AssertEqual(person.GetFullName(1968), "Polina Sergeeva"); 105 | } 106 | 107 | void TestPredefined() { 108 | Person person; 109 | 110 | person.ChangeFirstName(1965, "Polina"); 111 | person.ChangeLastName(1967, "Sergeeva"); 112 | 113 | AssertEqual(person.GetFullName(1964), "Incognito"); 114 | AssertEqual(person.GetFullName(1966), "Polina with unknown last name"); 115 | AssertEqual(person.GetFullName(1968), "Polina Sergeeva"); 116 | 117 | person.ChangeFirstName(1969, "Appolinaria"); 118 | AssertEqual(person.GetFullName(1968), "Polina Sergeeva"); 119 | AssertEqual(person.GetFullName(1969), "Appolinaria Sergeeva"); 120 | AssertEqual(person.GetFullName(1970), "Appolinaria Sergeeva"); 121 | 122 | person.ChangeLastName(1968, "Volkova"); 123 | AssertEqual(person.GetFullName(1967), "Polina Sergeeva"); 124 | AssertEqual(person.GetFullName(1968), "Polina Volkova"); 125 | AssertEqual(person.GetFullName(1969), "Appolinaria Volkova"); 126 | 127 | } 128 | 129 | int main() { 130 | TestRunner runner; 131 | runner.RunTest(TestPredefined, "TestPredefined"); 132 | runner.RunTest(TestPredefinedLastNameFirst, "TestPredefinedLastNameFirst"); 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /week-01/04-Programming-Assignment/Solution/team_tasks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | // Выделим в отдельную функцию получение следующего по приоритету типа задачи 10 | // Функция налагает требование на входной параметр: он не должен быть равен DONE 11 | // При этом task_status явно не сравнивается с DONE, что позволяет 12 | // сделать эту функцию максимально эффективной 13 | TaskStatus Next(TaskStatus task_status) { 14 | return static_cast(static_cast(task_status) + 1); 15 | } 16 | 17 | // Объявляем тип-синоним для map, 18 | // позволяющего хранить количество задач каждого статуса 19 | using TasksInfo = map; 20 | 21 | class TeamTasks { 22 | public: 23 | // Получить статистику по статусам задач конкретного разработчика 24 | const TasksInfo& GetPersonTasksInfo(const string& person) const; 25 | 26 | // Добавить новую задачу (в статусе NEW) для конкретного разработчика 27 | void AddNewTask(const string& person); 28 | 29 | // Обновить статусы по данному количеству задач конкретного разработчика 30 | tuple PerformPersonTasks( 31 | const string& person, int task_count); 32 | 33 | private: 34 | map person_tasks_; 35 | }; 36 | 37 | const TasksInfo& TeamTasks::GetPersonTasksInfo(const string& person) const { 38 | return person_tasks_.at(person); 39 | } 40 | 41 | void TeamTasks::AddNewTask(const string& person) { 42 | ++person_tasks_[person][TaskStatus::NEW]; 43 | } 44 | 45 | // Функция для удаления нулей из словаря 46 | void RemoveZeros(TasksInfo& tasks_info) { 47 | // Соберём те статусы, которые нужно убрать из словаря 48 | vector statuses_to_remove; 49 | for (const auto& task_item : tasks_info) { 50 | if (task_item.second == 0) { 51 | statuses_to_remove.push_back(task_item.first); 52 | } 53 | } 54 | for (const TaskStatus status : statuses_to_remove) { 55 | tasks_info.erase(status); 56 | } 57 | } 58 | 59 | 60 | tuple TeamTasks::PerformPersonTasks( 61 | const string& person, int task_count) { 62 | TasksInfo updated_tasks, untouched_tasks; 63 | 64 | // Здесь и далее мы будем пользоваться тем фактом, что в std::map оператор [] 65 | // в случае отсутствия ключа инициализирует значение по умолчанию, 66 | // если это возможно. 67 | // std::map::operator[] -> 68 | // http://ru.cppreference.com/w/cpp/container/map/operator_at 69 | TasksInfo& tasks = person_tasks_[person]; 70 | 71 | // Посчитаем, сколько задач каждого из статусов нужно обновить, 72 | // пользуясь тем фактом, что по умолчанию enum class инциализирует значения 73 | // от нуля по возрастанию. 74 | // enum class -> http://ru.cppreference.com/w/cpp/language/enum 75 | for (TaskStatus status = TaskStatus::NEW; 76 | status != TaskStatus::DONE; 77 | status = Next(status)) { 78 | // Считаем обновлённые 79 | updated_tasks[Next(status)] = min(task_count, tasks[status]); 80 | // Считаем, сколько осталось обновить 81 | task_count -= updated_tasks[Next(status)]; 82 | } 83 | 84 | // Обновляем статус текущих задач в соответствии с информацией об обновлённых 85 | // и находим количество нетронутых 86 | for (TaskStatus status = TaskStatus::NEW; 87 | status != TaskStatus::DONE; 88 | status = Next(status)) { 89 | untouched_tasks[status] = tasks[status] - updated_tasks[Next(status)]; 90 | tasks[status] += updated_tasks[status] - updated_tasks[Next(status)]; 91 | } 92 | // По условию DONE задачи не нужно вовзвращать в не обновлённых задачах 93 | tasks[TaskStatus::DONE] += updated_tasks[TaskStatus::DONE]; 94 | 95 | // По условию в словарях не должно быть нулей 96 | RemoveZeros(updated_tasks); 97 | RemoveZeros(untouched_tasks); 98 | 99 | return {updated_tasks, untouched_tasks}; 100 | } 101 | -------------------------------------------------------------------------------- /week-02/01-Programming-Assignment/Solution/starter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | enum class QueryType { 9 | NewBus, 10 | BusesForStop, 11 | StopsForBus, 12 | AllBuses 13 | }; 14 | 15 | struct Query { 16 | QueryType type; 17 | string bus; 18 | string stop; 19 | vector stops; 20 | }; 21 | 22 | istream& operator >> (istream& is, Query& q) { 23 | string typeStr; 24 | is >> typeStr; 25 | if (typeStr == "NEW_BUS") { 26 | q.type = QueryType::NewBus; 27 | is >> q.bus; 28 | int stop_count = 0; 29 | is >> stop_count; 30 | q.stops.resize(stop_count); 31 | for (auto& stop : q.stops) { 32 | is >> stop; 33 | } 34 | } else if (typeStr == "BUSES_FOR_STOP") { 35 | q.type = QueryType::BusesForStop; 36 | is >> q.stop; 37 | } else if (typeStr == "STOPS_FOR_BUS") { 38 | q.type = QueryType::StopsForBus; 39 | is >> q.bus; 40 | } else if (typeStr == "ALL_BUSES") { 41 | q.type = QueryType::AllBuses; 42 | } 43 | 44 | return is; 45 | } 46 | 47 | struct BusesForStopResponse { 48 | vector buses; 49 | }; 50 | 51 | ostream& operator << (ostream& os, const BusesForStopResponse& r) { 52 | if (r.buses.empty()) { 53 | os << "No stop" << endl; 54 | } else { 55 | for (const auto& bus : r.buses) { 56 | os << bus << " "; 57 | } 58 | os << endl; 59 | } 60 | return os; 61 | } 62 | 63 | struct StopsForBusResponse { 64 | string bus; 65 | vector>> stops_for_buses; 66 | }; 67 | 68 | ostream& operator << (ostream& os, const StopsForBusResponse& r) { 69 | if (r.stops_for_buses.empty()) { 70 | os << "No bus" << endl; 71 | } else { 72 | for (const auto& stop_and_buses : r.stops_for_buses) { 73 | os << "Stop " << stop_and_buses.first << ":"; 74 | if (stop_and_buses.second.size() == 1) { 75 | os << " no interchange" << endl; 76 | } else { 77 | for (const auto& bus : stop_and_buses.second) { 78 | if (bus != r.bus) { 79 | os << " " << bus; 80 | } 81 | } 82 | os << endl; 83 | } 84 | } 85 | } 86 | return os; 87 | } 88 | 89 | struct AllBusesResponse { 90 | map> buses_to_stops; 91 | }; 92 | 93 | ostream& operator << (ostream& os, const AllBusesResponse& r) { 94 | if (r.buses_to_stops.empty()) { 95 | os << "No buses" << endl; 96 | } else { 97 | for (const auto& bus_and_stops : r.buses_to_stops) { 98 | os << "Bus " << bus_and_stops.first << ":"; 99 | for (const auto& stop : bus_and_stops.second) { 100 | os << " " << stop; 101 | } 102 | os << endl; 103 | } 104 | } 105 | return os; 106 | } 107 | 108 | class BusManager { 109 | public: 110 | void AddBus(const string& bus, const vector& stops) { 111 | buses_to_stops.insert(make_pair(bus, stops)); 112 | for (const auto& stop : stops) { 113 | stops_to_buses[stop].push_back(bus); 114 | } 115 | } 116 | 117 | BusesForStopResponse GetBusesForStop(const string& stop) const { 118 | if (stops_to_buses.count(stop) == 0) { 119 | return BusesForStopResponse{vector()}; 120 | } else { 121 | return BusesForStopResponse{stops_to_buses.at(stop)}; 122 | } 123 | } 124 | 125 | StopsForBusResponse GetStopsForBus(const string& bus) const { 126 | vector>> result; 127 | 128 | if (buses_to_stops.count(bus) > 0) { 129 | for (const auto& stop : buses_to_stops.at(bus)) { 130 | result.push_back(make_pair(stop, stops_to_buses.at(stop))); 131 | } 132 | } 133 | return StopsForBusResponse{bus, result}; 134 | } 135 | 136 | AllBusesResponse GetAllBuses() const { 137 | return AllBusesResponse{buses_to_stops}; 138 | } 139 | 140 | private: 141 | map> buses_to_stops; 142 | map> stops_to_buses; 143 | }; 144 | -------------------------------------------------------------------------------- /week-02/04-Programming-Assignment/Solution/test_rational.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | template 13 | ostream& operator << (ostream& os, const vector& s) { 14 | os << "{"; 15 | bool first = true; 16 | for (const auto& x : s) { 17 | if (!first) { 18 | os << ", "; 19 | } 20 | first = false; 21 | os << x; 22 | } 23 | return os << "}"; 24 | } 25 | 26 | template 27 | ostream& operator << (ostream& os, const set& s) { 28 | os << "{"; 29 | bool first = true; 30 | for (const auto& x : s) { 31 | if (!first) { 32 | os << ", "; 33 | } 34 | first = false; 35 | os << x; 36 | } 37 | return os << "}"; 38 | } 39 | 40 | template 41 | ostream& operator << (ostream& os, const map& m) { 42 | os << "{"; 43 | bool first = true; 44 | for (const auto& kv : m) { 45 | if (!first) { 46 | os << ", "; 47 | } 48 | first = false; 49 | os << kv.first << ": " << kv.second; 50 | } 51 | return os << "}"; 52 | } 53 | 54 | template 55 | void AssertEqual(const T& t, const U& u, const string& hint = {}) { 56 | if (t != u) { 57 | ostringstream os; 58 | os << "Assertion failed: " << t << " != " << u; 59 | if (!hint.empty()) { 60 | os << " hint: " << hint; 61 | } 62 | throw runtime_error(os.str()); 63 | } 64 | } 65 | 66 | void Assert(bool b, const string& hint) { 67 | AssertEqual(b, true, hint); 68 | } 69 | 70 | class TestRunner { 71 | public: 72 | template 73 | void RunTest(TestFunc func, const string& test_name) { 74 | try { 75 | func(); 76 | cerr << test_name << " OK" << endl; 77 | } catch (exception& e) { 78 | ++fail_count; 79 | cerr << test_name << " fail: " << e.what() << endl; 80 | } catch (...) { 81 | ++fail_count; 82 | cerr << "Unknown exception caught" << endl; 83 | } 84 | } 85 | 86 | ~TestRunner() { 87 | if (fail_count > 0) { 88 | cerr << fail_count << " unit tests failed. Terminate" << endl; 89 | exit(1); 90 | } 91 | } 92 | 93 | private: 94 | int fail_count = 0; 95 | }; 96 | 97 | void TestPredefined() { 98 | AssertEqual(Rational(1, 1).Numerator(), 1, "Canonical form of 1/1 is 1/1"); 99 | AssertEqual(Rational(1, 1).Denominator(), 1, "Canonical form of 1/1 is 1/1"); 100 | AssertEqual(Rational(3, 5).Numerator(), 3, "Canonical form of 3/5 is 3/5"); 101 | AssertEqual(Rational(3, 5).Denominator(), 5, "Canonical form of 3/5 is 3/5"); 102 | AssertEqual(Rational(2147483647, 2147483647).Numerator(), 1, "Canonical form of 2147483647/2147483647 is 1/1"); 103 | AssertEqual(Rational(2147483647, 2147483647).Denominator(), 1, "Canonical form of 2147483647/2147483647 is 1/1"); 104 | AssertEqual(Rational(-5, 4).Numerator(), -5, "Canonical form of -5/4 is -5/4"); 105 | AssertEqual(Rational(-5, 4).Denominator(), 4, "Canonical form of -5/4 is -5/4"); 106 | AssertEqual(Rational(5, -4).Numerator(), -5, "Canonical form of 5/-4 is -5/4"); 107 | AssertEqual(Rational(5, -4).Denominator(), 4, "Canonical form of 5/-4 is -5/4"); 108 | AssertEqual(Rational(-6, -2).Numerator(), 3, "Canonical form of -6/-2 is 3/1"); 109 | AssertEqual(Rational(-6, -2).Denominator(), 1, "Canonical form of -6/-2 is 3/1"); 110 | AssertEqual(Rational(21, 56).Numerator(), 3, "Canonical form of 21/56 is 3/8"); 111 | AssertEqual(Rational(21, 56).Denominator(), 8, "Canonical form of 21/56 is 3/8"); 112 | AssertEqual(Rational(0, 100).Numerator(), 0, "Canonical form of 0/100 is 0/1"); 113 | AssertEqual(Rational(0, 100).Denominator(), 1, "Canonical form of 0/100 is 0/1"); 114 | AssertEqual(Rational().Numerator(), 0, "Canonical form of default constructed is 0/1"); 115 | AssertEqual(Rational().Denominator(), 1, "Canonical form of default constructed is 0/1"); 116 | } 117 | 118 | int main() { 119 | TestRunner runner; 120 | runner.RunTest(TestPredefined, "TestPredefined"); 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /week-02/03-Practice-Programming-Assignment/test_person.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | template 6 | void AssertEqual(const T& t, const U& u, const std::string& hint = {}) { 7 | if (t != u) { 8 | std::ostringstream os; 9 | os << " AssertionError: " << t << " != " << u; 10 | if (!hint.empty()) { 11 | os << " hint: " << hint; 12 | } 13 | throw std::runtime_error(os.str()); 14 | } 15 | } 16 | 17 | class TestRunner { 18 | public: 19 | template 20 | void RunTest(TestFunc func, const std::string& test_name) { 21 | try { 22 | func(); 23 | std::cerr << " PASSED: " << test_name << std::endl; 24 | } catch (std::exception& e) { 25 | ++fail_count; 26 | std::cerr << " FAIL: " << test_name << e.what() << std::endl; 27 | } catch (...) { 28 | ++fail_count; 29 | std::cerr << "Unknown exception caught" << std::endl; 30 | } 31 | } 32 | 33 | ~TestRunner() { 34 | if (fail_count > 0) { 35 | std::cerr << "----------------------------------------------------------------------" << std::endl; 36 | std::cerr << "FAILED (failures=" << fail_count << ")" << std::endl; 37 | exit(1); 38 | } else { 39 | std::cerr << "----------------------------------------------------------------------" << std::endl; 40 | std::cerr << "OK" << std::endl; 41 | } 42 | } 43 | 44 | private: 45 | int fail_count = 0; 46 | }; 47 | 48 | class Person { 49 | public: 50 | // Вы можете вставлять сюда различные реализации класса, 51 | // чтобы проверить, что ваши тесты пропускают корректный код 52 | // и ловят некорректный 53 | void ChangeFirstName(int year, const string& first_name) { 54 | } 55 | void ChangeLastName(int year, const string& last_name) { 56 | } 57 | string GetFullName(int year) { 58 | } 59 | }; 60 | 61 | void TestIncognito() { 62 | Person person; 63 | person.ChangeFirstName(1965, "Polina"); 64 | person.ChangeLastName(1967, "Sergeeva"); 65 | AssertEqual(person.GetFullName(1900), "Incognito"); 66 | } 67 | 68 | void TestUnknownLastName() { 69 | Person person; 70 | person.ChangeFirstName(1965, "Polina"); 71 | person.ChangeLastName(1967, "Sergeeva"); 72 | AssertEqual(person.GetFullName(1965), "Polina with unknown last name"); 73 | } 74 | 75 | void TestBothName() { 76 | Person person; 77 | person.ChangeFirstName(1965, "Polina"); 78 | person.ChangeLastName(1967, "Sergeeva"); 79 | AssertEqual(person.GetFullName(1990), "Polina Sergeeva"); 80 | } 81 | 82 | void TestSaveFirstName() { 83 | Person person; 84 | person.ChangeFirstName(1965, "Polina"); 85 | person.ChangeLastName(1967, "Sergeeva"); 86 | person.ChangeFirstName(1970, "Appolinaria"); 87 | AssertEqual(person.GetFullName(1969), "Polina Sergeeva"); 88 | } 89 | 90 | void TestChangeFirstName() { 91 | Person person; 92 | person.ChangeFirstName(1965, "Polina"); 93 | person.ChangeLastName(1967, "Sergeeva"); 94 | person.ChangeFirstName(1970, "Appolinaria"); 95 | AssertEqual(person.GetFullName(1970), "Appolinaria Sergeeva"); 96 | } 97 | 98 | void TestChangeLastName() { 99 | Person person; 100 | person.ChangeFirstName(1965, "Polina"); 101 | person.ChangeLastName(1967, "Sergeeva"); 102 | person.ChangeFirstName(1970, "Appolinaria"); 103 | person.ChangeLastName(1968, "Volkova"); 104 | AssertEqual(person.GetFullName(1969), "Polina Volkova"); 105 | } 106 | 107 | void TestChangeBothName() { 108 | Person person; 109 | person.ChangeFirstName(1965, "Polina"); 110 | person.ChangeLastName(1967, "Sergeeva"); 111 | person.ChangeFirstName(1970, "Appolinaria"); 112 | person.ChangeLastName(1968, "Volkova"); 113 | AssertEqual(person.GetFullName(1970), "Appolinaria Volkova"); 114 | } 115 | 116 | void TestUnknownFirstName() { 117 | Person person; 118 | person.ChangeLastName(1967, "Sergeeva"); 119 | person.ChangeFirstName(1995, "Polina"); 120 | AssertEqual(person.GetFullName(1970), "Sergeeva with unknown first name"); 121 | } 122 | 123 | 124 | int main() { 125 | TestRunner runner; 126 | // добавьте сюда свои тесты 127 | runner.RunTest(TestIncognito, "TestIncognito"); 128 | runner.RunTest(TestUnknownLastName, "TestUnknownLastName"); 129 | runner.RunTest(TestUnknownFirstName, "TestUnknownFirstName"); 130 | runner.RunTest(TestBothName, "TestBothName"); 131 | runner.RunTest(TestSaveFirstName, "TestSaveFirstName"); 132 | runner.RunTest(TestChangeFirstName, "TestChangeFirstName"); 133 | runner.RunTest(TestChangeLastName, "TestChangeLastName"); 134 | runner.RunTest(TestChangeBothName, "TestChangeBothName"); 135 | return 0; 136 | } 137 | 138 | -------------------------------------------------------------------------------- /week-02/02-Practice-Programming-Assignment/Solution/test_equation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | template 14 | ostream &operator<<(ostream &os, const vector &s) { 15 | os << "{"; 16 | bool first = true; 17 | for (const auto &x : s) { 18 | if (!first) { 19 | os << ", "; 20 | } 21 | first = false; 22 | os << x; 23 | } 24 | return os << "}"; 25 | } 26 | 27 | template 28 | ostream &operator<<(ostream &os, const set &s) { 29 | os << "{"; 30 | bool first = true; 31 | for (const auto &x : s) { 32 | if (!first) { 33 | os << ", "; 34 | } 35 | first = false; 36 | os << x; 37 | } 38 | return os << "}"; 39 | } 40 | 41 | template 42 | ostream &operator<<(ostream &os, const map &m) { 43 | os << "{"; 44 | bool first = true; 45 | for (const auto &kv : m) { 46 | if (!first) { 47 | os << ", "; 48 | } 49 | first = false; 50 | os << kv.first << ": " << kv.second; 51 | } 52 | return os << "}"; 53 | } 54 | 55 | template 56 | void AssertEqual(const T &t, const U &u, const string &hint = {}) { 57 | if (t != u) { 58 | ostringstream os; 59 | os << "Assertion failed: " << t << " != " << u; 60 | if (!hint.empty()) { 61 | os << " hint: " << hint; 62 | } 63 | throw runtime_error(os.str()); 64 | } 65 | } 66 | 67 | void Assert(bool b, const string &hint) { AssertEqual(b, true, hint); } 68 | 69 | class TestRunner { 70 | public: 71 | template 72 | void RunTest(TestFunc func, const string &test_name) { 73 | try { 74 | func(); 75 | cerr << test_name << " OK" << endl; 76 | } catch (exception &e) { 77 | ++fail_count; 78 | cerr << test_name << " fail: " << e.what() << endl; 79 | } catch (...) { 80 | ++fail_count; 81 | cerr << "Unknown exception caught" << endl; 82 | } 83 | } 84 | 85 | ~TestRunner() { 86 | if (fail_count > 0) { 87 | cerr << fail_count << " unit tests failed. Terminate" << endl; 88 | exit(1); 89 | } 90 | } 91 | 92 | private: 93 | int fail_count = 0; 94 | }; 95 | 96 | void TestRootCount() { 97 | mt19937 gen; 98 | uniform_real_distribution<> unif(-10, 10); 99 | 100 | for (auto i = 0; i < 100; ++i) { 101 | const auto a = unif(gen); 102 | const auto b = unif(gen); 103 | const auto c = unif(gen); 104 | 105 | const auto count = GetDistinctRealRootCount(a, b, c); 106 | 107 | Assert(count >= 0 && count <= 2, 108 | "Quadratic equation has only 0, 1 or 2 real roots."); 109 | } 110 | } 111 | 112 | void TestOneRoot() { 113 | mt19937 gen; 114 | uniform_real_distribution<> unif(-10, 10); 115 | 116 | for (auto i = 0; i < 100; ++i) { 117 | const auto x_1 = unif(gen); 118 | 119 | const auto p = x_1 + x_1; 120 | const auto q = x_1 * x_1; 121 | 122 | const auto count = GetDistinctRealRootCount(1, p, q); 123 | stringstream description; 124 | description << showpos << "x^2" << p << "x" << q 125 | << " = 0 has 1 real root."; 126 | 127 | AssertEqual(count, 1, description.str()); 128 | } 129 | } 130 | 131 | void TestNoRoots() { 132 | AssertEqual(GetDistinctRealRootCount(1, 0, 1), 0, 133 | "x^2+1 = 0 has 0 real roots."); 134 | AssertEqual(GetDistinctRealRootCount(1, 3, 4), 0, 135 | "x^2+3x+4 = 0 has 0 real roots."); 136 | AssertEqual(GetDistinctRealRootCount(1, -2, 10), 0, 137 | "x^2-2x+10 = 0 has 0 real roots."); 138 | } 139 | 140 | void TestLinearEquation() { 141 | AssertEqual(GetDistinctRealRootCount(0, 2, 1), 1, 142 | "2x+1 = 0 has 1 real roots."); 143 | AssertEqual(GetDistinctRealRootCount(0, -1, 0), 1, 144 | "-x = 0 has 0 real roots."); 145 | AssertEqual(GetDistinctRealRootCount(0, 120, -10), 1, 146 | "120x - 10 = 0 has 0 real roots."); 147 | } 148 | 149 | void TestConstant() { 150 | AssertEqual(GetDistinctRealRootCount(0, 0, 1), 0, 151 | "c = 0, where c = 1 has 1 real roots."); 152 | AssertEqual(GetDistinctRealRootCount(0, 0, -10), 0, 153 | "c = 0, where c = -10 has 0 real roots."); 154 | AssertEqual(GetDistinctRealRootCount(0, 0, 189238910), 0, 155 | "c = 0, where c = 189238910 has 0 real roots."); 156 | } 157 | 158 | int main() { 159 | TestRunner runner; 160 | runner.RunTest(TestRootCount, "TestRootCount"); 161 | runner.RunTest(TestOneRoot, "TestOneRoot"); 162 | runner.RunTest(TestNoRoots, "TestNoRoots"); 163 | runner.RunTest(TestLinearEquation, "TestLinearEquation"); 164 | runner.RunTest(TestConstant, "TestConstant"); 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /week-02/01-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Декомпозиция программы #### 2 | 3 | 4 | ##### Введение ##### 5 | В курсе «Белый пояс по С++» у нас была задача «[Автобусные остановки — 1](https://www.coursera.org/learn/c-plus-plus-white/programming/Gi9dw/avtobusnyie-ostanovki-1)». В этой задаче вам будет дано её правильное решение, целиком содержащееся внутри функции _main_. Вам надо будет выполнить декомпозицию этого решения на заранее заданные блоки так, чтобы получившаяся программа так же корректно решала задачу. Условие задачи «Автобусные остановки — 1» приведено ниже. 6 | 7 | ##### Исходные файлы ##### 8 | Авторское решение этой задачи содержится в файле 9 | 10 | [correct.cpp]() 11 | 12 | Кроме того, вам дан файл 13 | 14 | [starter.cpp](https://github.com/avtomato/Basics-of-C-plus-plus-development-yellow-belt/blob/master/week-02/01-Programming-Assignment/Source/starter.cpp) 15 | 16 | который содержит заготовки классов и функций. __Не меняя функцию main__, вам надо реализовать эти классы и функции так, чтобы получившаяся программа решала задачу «Автобусные остановки — 1». 17 | 18 | ##### Как будет тестироваться ваша программа ##### 19 | Автоматическая проверяющая система заменит в вашей программе функцию _main_ на ту, которая дана вам в файле _starter.cpp_, скомпилирует получившийся файл и прогонит на тестах для задачи «Автобусные остановки — 1». 20 | 21 | ##### Условие задачи «Автобусные остановки — 1» ##### 22 | Реализуйте систему хранения автобусных маршрутов. Вам нужно обрабатывать следующие запросы: 23 | 24 | * **NEW_BUS *bus stop_count stop1 stop2 ...*** — добавить маршрут автобуса с названием ***bus*** и ***stop_count*** остановками с названиями ***stop1, stop2, ...*** 25 | * **BUSES_FOR_STOP *stop*** — вывести названия всех маршрутов автобуса, проходящих через остановку ***stop***. 26 | * **STOPS_FOR_BUS *bus*** — вывести названия всех остановок маршрута ***bus*** со списком автобусов, на которые можно пересесть на каждой из остановок. 27 | * **ALL_BUSES** — вывести список всех маршрутов с остановками. 28 | 29 | ##### Формат ввода ##### 30 | В первой строке ввода содержится количество запросов *Q*, затем в *Q* строках следуют описания запросов. 31 | 32 | Гарантируется, что все названия маршрутов и остановок состоят лишь из латинских букв, цифр и знаков подчёркивания. 33 | 34 | Для каждого запроса **NEW_BUS *bus stop_count stop1 stop2 ...*** гарантируется, что маршрут ***bus*** отсутствует, количество остановок больше 0, а после числа ***stop_count*** следует именно такое количество названий остановок, причём все названия в каждом списке различны. 35 | 36 | ##### Формат вывода ##### 37 | Для каждого запроса, кроме **NEW_BUS**, выведите соответствующий ответ на него: 38 | 39 | * На запрос **BUSES_FOR_STOP *stop*** выведите через пробел список автобусов, проезжающих через эту остановку, в том порядке, в котором они создавались командами **NEW_BUS**. Если остановка ***stop*** не существует, выведите **No stop**. 40 | * На запрос **STOPS_FOR_BUS *bus*** выведите описания остановок маршрута ***bus*** в отдельных строках в том порядке, в котором они были заданы в соответствующей команде **NEW_BUS**. Описание каждой остановки ***stop*** должно иметь вид **Stop *stop: bus1 bus2 ...***, где ***bus1 bus2 ...*** — список автобусов, проезжающих через остановку ***stop***, в порядке, в котором они создавались командами **NEW_BUS**, за исключением исходного маршрута ***bus***. Если через остановку ***stop*** не проезжает ни один автобус, кроме ***bus***, вместо списка автобусов для неё выведите **no interchange**. Если маршрут ***bus*** не существует, выведите **No bus**. 41 | * На запрос **ALL_BUSES** выведите описания всех автобусов в алфавитном порядке. Описание каждого маршрута ***bus*** должно иметь вид **Bus *bus: stop1 stop2 ...***, где ***stop1 stop2 ...*** — список остановок автобуса ***bus*** в порядке, в котором они были заданы в соответствующей команде **NEW_BUS**. Если автобусы отсутствуют, выведите **No buses**. 42 | 43 | ##### Предупреждение ##### 44 | Условие задачи выше содержит много важных деталей. Если вы не уверены в том, что не упустили ни одной, перечитайте условие ещё раз. 45 | 46 | ##### Пример ##### 47 | ###### Ввод ###### 48 | ```commandline 49 | 10 50 | ALL_BUSES 51 | BUSES_FOR_STOP Marushkino 52 | STOPS_FOR_BUS 32K 53 | NEW_BUS 32 3 Tolstopaltsevo Marushkino Vnukovo 54 | NEW_BUS 32K 6 Tolstopaltsevo Marushkino Vnukovo Peredelkino Solntsevo Skolkovo 55 | BUSES_FOR_STOP Vnukovo 56 | NEW_BUS 950 6 Kokoshkino Marushkino Vnukovo Peredelkino Solntsevo Troparyovo 57 | NEW_BUS 272 4 Vnukovo Moskovsky Rumyantsevo Troparyovo 58 | STOPS_FOR_BUS 272 59 | ALL_BUSES 60 | ``` 61 | ###### Вывод ###### 62 | ```commandline 63 | No buses 64 | No stop 65 | No bus 66 | 32 32K 67 | Stop Vnukovo: 32 32K 950 68 | Stop Moskovsky: no interchange 69 | Stop Rumyantsevo: no interchange 70 | Stop Troparyovo: 950 71 | Bus 272: Vnukovo Moskovsky Rumyantsevo Troparyovo 72 | Bus 32: Tolstopaltsevo Marushkino Vnukovo 73 | Bus 32K: Tolstopaltsevo Marushkino Vnukovo Peredelkino Solntsevo Skolkovo 74 | Bus 950: Kokoshkino Marushkino Vnukovo Peredelkino Solntsevo Troparyovo 75 | ``` 76 | -------------------------------------------------------------------------------- /week-01/03-Practice-Programming-Assignment/find_max_repetition_count.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | enum class Lang { 7 | DE, FR, IT 8 | }; 9 | 10 | struct Region { 11 | std::string std_name; 12 | std::string parent_std_name; 13 | std::map names; 14 | int64_t population; 15 | }; 16 | 17 | bool operator<(const Region& lhs, const Region& rhs) { 18 | return std::tie(lhs.std_name, lhs.parent_std_name, lhs.names, lhs.population) < 19 | std::tie(rhs.std_name, rhs.parent_std_name, rhs.names, rhs.population); 20 | } 21 | 22 | int FindMaxRepetitionCount(const std::vector& regions) { 23 | if (regions.empty()) { 24 | return 0; 25 | } 26 | std::map m; 27 | for (const auto& r : regions) { 28 | ++m[r]; 29 | } 30 | int max_repeat = 0; 31 | for (const auto& i : m) { 32 | if (i.second > max_repeat) { 33 | max_repeat = i.second; 34 | } 35 | } 36 | return max_repeat; 37 | } 38 | 39 | int main() { 40 | std::cout << FindMaxRepetitionCount({ 41 | { 42 | "Moscow", 43 | "Russia", 44 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 45 | 89 46 | }, { 47 | "Russia", 48 | "Eurasia", 49 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 50 | 89 51 | }, { 52 | "Moscow", 53 | "Russia", 54 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 55 | 89 56 | }, { 57 | "Moscow", 58 | "Russia", 59 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 60 | 89 61 | }, { 62 | "Russia", 63 | "Eurasia", 64 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 65 | 89 66 | }, 67 | })<< std::endl; 68 | 69 | std::cout << FindMaxRepetitionCount({ 70 | { 71 | "Moscow", 72 | "Russia", 73 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 74 | 89 75 | }, { 76 | "Russia", 77 | "Eurasia", 78 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 79 | 89 80 | }, { 81 | "Moscow", 82 | "Russia", 83 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou deux"}, {Lang::IT, "Mosca"}}, 84 | 89 85 | }, { 86 | "Moscow", 87 | "Toulouse", 88 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 89 | 89 90 | }, { 91 | "Moscow", 92 | "Russia", 93 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 94 | 31 95 | }, 96 | }) << std::endl; 97 | 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /week-02/05-Programming-Assignment/test_palindrome.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void AssertEqual(const T& t, const U& u, const std::string& hint = {}) { 6 | if (t != u) { 7 | std::ostringstream os; 8 | os << " AssertionError: " << t << " != " << u; 9 | if (!hint.empty()) { 10 | os << " hint: " << hint; 11 | } 12 | throw std::runtime_error(os.str()); 13 | } 14 | } 15 | 16 | class TestRunner { 17 | public: 18 | template 19 | void RunTest(TestFunc func, const std::string& test_name) { 20 | try { 21 | func(); 22 | std::cerr << " PASSED: " << test_name << std::endl; 23 | } catch (std::exception& e) { 24 | ++fail_count; 25 | std::cerr << " FAIL: " << test_name << e.what() << std::endl; 26 | } catch (...) { 27 | ++fail_count; 28 | std::cerr << "Unknown exception caught" << std::endl; 29 | } 30 | } 31 | 32 | ~TestRunner() { 33 | if (fail_count > 0) { 34 | std::cerr << "----------------------------------------------------------------------" << std::endl; 35 | std::cerr << "FAILED (failures=" << fail_count << ")" << std::endl; 36 | exit(1); 37 | } else { 38 | std::cerr << "----------------------------------------------------------------------" << std::endl; 39 | std::cerr << "OK" << std::endl; 40 | } 41 | } 42 | 43 | private: 44 | int fail_count = 0; 45 | }; 46 | 47 | bool IsPalindrom(const std::string& str) { 48 | // Вы можете вставлять сюда различные реализации функции, 49 | // чтобы проверить, что ваши тесты пропускают корректный код 50 | // и ловят некорректный 51 | } 52 | 53 | void TestOddLengthStringTrue1() { 54 | AssertEqual(IsPalindrom("madam"), true); 55 | } 56 | 57 | void TestOddLengthStringTrue2() { 58 | AssertEqual(IsPalindrom("level"), true); 59 | } 60 | 61 | void TestOddLengthStringTrue3() { 62 | AssertEqual(IsPalindrom("wasitacaroracatisaw"), true); 63 | } 64 | 65 | void TestOddLengthStringFalse1() { 66 | AssertEqual(IsPalindrom("gentleman"), false); 67 | } 68 | // 11 69 | void TestOddLengthStringFalse2() { 70 | AssertEqual(IsPalindrom("abcca"), false); 71 | } 72 | // 12 73 | void TestOddLengthStringFalse3() { 74 | AssertEqual(IsPalindrom("abcbc"), false); 75 | } 76 | 77 | void TestEvenLengthStringTrue() { 78 | AssertEqual(IsPalindrom("abba"), true); 79 | } 80 | // 4 81 | void TestEvenLengthStringFalse() { 82 | AssertEqual(IsPalindrom("ab"), false); 83 | } 84 | 85 | void TestLongString1() { 86 | AssertEqual(IsPalindrom("abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcba"), true); 87 | } 88 | 89 | void TestLongString2() { 90 | AssertEqual(IsPalindrom("abcdefghijklnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcba"), false); 91 | } 92 | 93 | void TestUpperCase() { 94 | AssertEqual(IsPalindrom("aA"), false); 95 | } 96 | 97 | void TestPassFirstSymbol() { 98 | AssertEqual(IsPalindrom("asitacaroracatisaw"), false); 99 | } 100 | 101 | void TestPassLastSymbol() { 102 | AssertEqual(IsPalindrom("wasitacaroracatisa"), false); 103 | } 104 | 105 | void TestPassTwoFirstSymbol() { 106 | AssertEqual(IsPalindrom("sitacaroracatisaw"), false); 107 | } 108 | 109 | void TestPassTwoLastSymbol() { 110 | AssertEqual(IsPalindrom("wasitacaroracatis"), false); 111 | } 112 | 113 | void TestEmptyString() { 114 | AssertEqual(IsPalindrom(""), true); 115 | } 116 | // 2 117 | void TestOneSymbolString() { 118 | AssertEqual(IsPalindrom("a"), true); 119 | } 120 | 121 | void TestSpaceSymbols() { 122 | AssertEqual(IsPalindrom("kay ak"), false); 123 | } 124 | 125 | void TestTabSymbols() { 126 | AssertEqual(IsPalindrom("kay\tak"), false); 127 | } 128 | 129 | void TestIndent() { 130 | AssertEqual(IsPalindrom(" kayak"), false); 131 | } 132 | 133 | void TestWhitespaceSymbols() { 134 | AssertEqual(IsPalindrom("\t\n \n\t"), true); 135 | } 136 | 137 | int main() { 138 | TestRunner runner; 139 | // добавьте сюда свои тесты 140 | runner.RunTest(TestOddLengthStringTrue1, "TestOddLengthStringTrue1"); 141 | runner.RunTest(TestOddLengthStringTrue2, "TestOddLengthStringTrue2"); 142 | runner.RunTest(TestOddLengthStringTrue3, "TestOddLengthStringTrue3"); 143 | runner.RunTest(TestOddLengthStringFalse1, "TestOddLengthStringFalse1"); 144 | runner.RunTest(TestOddLengthStringFalse2, "TestOddLengthStringFalse2"); 145 | runner.RunTest(TestOddLengthStringFalse3, "TestOddLengthStringFalse3"); 146 | runner.RunTest(TestEvenLengthStringTrue, "TestEvenLengthStringTrue"); 147 | runner.RunTest(TestEvenLengthStringFalse, "TestEvenLengthStringFalse"); 148 | runner.RunTest(TestLongString1, "TestLongString1"); 149 | runner.RunTest(TestLongString2, "TestLongString2"); 150 | runner.RunTest(TestUpperCase, "TestUpperCase"); 151 | runner.RunTest(TestPassFirstSymbol, "TestPassFirstSymbol"); 152 | runner.RunTest(TestPassLastSymbol, "TestPassLastSymbol"); 153 | runner.RunTest(TestPassTwoFirstSymbol, "TestPassTwoFirstSymbol"); 154 | runner.RunTest(TestPassTwoLastSymbol, "TestPassTwoLastSymbol"); 155 | runner.RunTest(TestEmptyString, "TestEmptyString"); 156 | runner.RunTest(TestOneSymbolString, "TestOneSymbolString"); 157 | runner.RunTest(TestSpaceSymbols, "TestSpaceSymbols"); 158 | runner.RunTest(TestTabSymbols, "TestTabSymbols"); 159 | runner.RunTest(TestIndent, "TestIndent"); 160 | runner.RunTest(TestWhitespaceSymbols, "TestWhitespaceSymbols"); 161 | return 0; 162 | } 163 | 164 | -------------------------------------------------------------------------------- /week-01/04-Programming-Assignment/team_tasks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Перечислимый тип для статуса задачи 5 | enum class TaskStatus { 6 | NEW, // новая 7 | IN_PROGRESS, // в разработке 8 | TESTING, // на тестировании 9 | DONE // завершена 10 | }; 11 | 12 | // Объявляем тип-синоним для map, 13 | // позволяющего хранить количество задач каждого статуса 14 | using TasksInfo = std::map; 15 | 16 | class TeamTasks { 17 | public: 18 | // Получить статистику по статусам задач конкретного разработчика 19 | const TasksInfo& GetPersonTasksInfo(const std::string& person) const { 20 | return PersonTasks.at(person); 21 | } 22 | 23 | // Добавить новую задачу (в статусе NEW) для конкретного разработчитка 24 | void AddNewTask(const std::string& person) { 25 | auto& tasks_info = PersonTasks[person]; 26 | ++tasks_info[TaskStatus::NEW]; 27 | } 28 | 29 | // Обновить статусы по данному количеству задач конкретного разработчика, 30 | // подробности см. ниже 31 | std::tuple PerformPersonTasks( 32 | const std::string& person, int task_count) { 33 | TasksInfo upgrade; 34 | TasksInfo updated; 35 | TasksInfo untouched; 36 | auto& tasks_info = PersonTasks[person]; 37 | for (auto& item : tasks_info) { 38 | if (item.first == TaskStatus::NEW) { 39 | if (item.second > 0) { 40 | int new_status_count = item.second; 41 | while (new_status_count > 0 && task_count > 0) { 42 | ++updated[TaskStatus::IN_PROGRESS]; 43 | ++upgrade[TaskStatus::IN_PROGRESS]; 44 | --new_status_count; 45 | --task_count; 46 | } 47 | if (new_status_count > 0) { 48 | untouched[TaskStatus::NEW] += new_status_count; 49 | upgrade[TaskStatus::NEW] += new_status_count; 50 | } 51 | } 52 | } 53 | if (item.first == TaskStatus::IN_PROGRESS) { 54 | if (item.second > 0) { 55 | int in_progress_status_count = item.second; 56 | while (in_progress_status_count > 0 && task_count > 0) { 57 | ++updated[TaskStatus::TESTING]; 58 | ++upgrade[TaskStatus::TESTING]; 59 | --in_progress_status_count; 60 | --task_count; 61 | } 62 | if (in_progress_status_count > 0) { 63 | untouched[TaskStatus::IN_PROGRESS] += in_progress_status_count; 64 | upgrade[TaskStatus::IN_PROGRESS] += in_progress_status_count; 65 | } 66 | } 67 | } 68 | if (item.first == TaskStatus::TESTING) { 69 | if (item.second > 0) { 70 | int testing_status_count = item.second; 71 | while (testing_status_count > 0 && task_count > 0) { 72 | ++updated[TaskStatus::DONE]; 73 | ++upgrade[TaskStatus::DONE]; 74 | --testing_status_count; 75 | --task_count; 76 | } 77 | if (testing_status_count > 0) { 78 | untouched[TaskStatus::TESTING] += testing_status_count; 79 | upgrade[TaskStatus::TESTING] += testing_status_count; 80 | } 81 | } 82 | } 83 | if (item.first == TaskStatus::DONE) { 84 | if (item.second > 0) { 85 | upgrade[TaskStatus::DONE] += item.second; 86 | } 87 | } 88 | } 89 | PersonTasks[person] = upgrade; 90 | return std::make_tuple(updated, untouched); 91 | }; 92 | 93 | private: 94 | std::map PersonTasks; 95 | }; 96 | 97 | // Принимаем словарь по значению, чтобы иметь возможность 98 | // обращаться к отсутствующим ключам с помощью [] и получать 0, 99 | // не меняя при этом исходный словарь 100 | void PrintTasksInfo(TasksInfo tasks_info) { 101 | std::cout << tasks_info[TaskStatus::NEW] << " new tasks" << 102 | ", " << tasks_info[TaskStatus::IN_PROGRESS] << " tasks in progress" << 103 | ", " << tasks_info[TaskStatus::TESTING] << " tasks are being tested" << 104 | " and " << tasks_info[TaskStatus::DONE] << " tasks are done" << std::endl; 105 | } 106 | 107 | 108 | int main() { 109 | TeamTasks tasks; 110 | tasks.AddNewTask("Ilia"); 111 | for (int i = 0; i < 3; ++i) { 112 | tasks.AddNewTask("Ivan"); 113 | } 114 | std::cout << "Ilia's tasks: "; 115 | PrintTasksInfo(tasks.GetPersonTasksInfo("Ilia")); 116 | std::cout << "Ivan's tasks: "; 117 | PrintTasksInfo(tasks.GetPersonTasksInfo("Ivan")); 118 | 119 | TasksInfo updated_tasks, untouched_tasks; 120 | 121 | tie(updated_tasks, untouched_tasks) = 122 | tasks.PerformPersonTasks("Ivan", 2); 123 | std::cout << "Updated Ivan's tasks: "; 124 | PrintTasksInfo(updated_tasks); 125 | std::cout << "Untouched Ivan's tasks: "; 126 | PrintTasksInfo(untouched_tasks); 127 | 128 | tie(updated_tasks, untouched_tasks) = 129 | tasks.PerformPersonTasks("Ivan", 2); 130 | std::cout << "Updated Ivan's tasks: "; 131 | PrintTasksInfo(updated_tasks); 132 | std::cout << "Untouched Ivan's tasks: "; 133 | PrintTasksInfo(untouched_tasks); 134 | 135 | return 0; 136 | } 137 | -------------------------------------------------------------------------------- /week-01/04-Programming-Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Трекер задач #### 2 | 3 | 4 | Реализуйте класс _TeamTasks_, позволяющий хранить статистику по статусам задач команды разработчиков: 5 | ```objectivec 6 | // Перечислимый тип для статуса задачи 7 | enum class TaskStatus { 8 | NEW, // новая 9 | IN_PROGRESS, // в разработке 10 | TESTING, // на тестировании 11 | DONE // завершена 12 | }; 13 | 14 | // Объявляем тип-синоним для map, 15 | // позволяющего хранить количество задач каждого статуса 16 | using TasksInfo = map; 17 | 18 | class TeamTasks { 19 | public: 20 | // Получить статистику по статусам задач конкретного разработчика 21 | const TasksInfo& GetPersonTasksInfo(const string& person) const; 22 | 23 | // Добавить новую задачу (в статусе NEW) для конкретного разработчитка 24 | void AddNewTask(const string& person); 25 | 26 | // Обновить статусы по данному количеству задач конкретного разработчика, 27 | // подробности см. ниже 28 | tuple PerformPersonTasks( 29 | const string& person, int task_count); 30 | }; 31 | 32 | ``` 33 | Метод _PerformPersonTasks_ должен реализовывать следующий алгоритм: 34 | 35 | 1. Рассмотрим все не выполненные задачи разработчика person. 36 | 2. Упорядочим их по статусам: сначала все задачи в статусе NEW, затем все задачи в статусе IN_PROGRESS и, наконец, задачи в статусе TESTING. 37 | 3. Рассмотрим первые task_count задач и переведём каждую из них в следующий статус в соответствии с естественным порядком: NEW → IN_PROGRESS → TESTING → DONE. 38 | 4. Вернём кортеж из двух элементов: информацию о статусах обновившихся задач (включая те, которые оказались в статусе DONE) и информацию о статусах остальных не выполненных задач. 39 | 40 | Гарантируется, что *task_count* является положительным числом. Если *task_count* превышает текущее количество невыполненных задач разработчика, достаточно считать, что *task_count* равен количеству невыполненных задач: дважды обновлять статус какой-либо задачи в этом случае не нужно. 41 | 42 | Кроме того, гарантируется, что метод _GetPersonTasksInfo_ не будет вызван для разработчика, не имеющего задач. 43 | 44 | ##### Пример работы метода PerformPersonTasks ##### 45 | Предположим, что у конкретного разработчика имеется 10 задач со следующими статусами: 46 | 47 | * NEW — 3 48 | * IN_PROGRESS — 2 49 | * TESTING — 4 50 | * DONE — 1 51 | 52 | Поступает команда _PerformPersonTasks_ с параметром *task_count = 4*, что означает обновление статуса для 3 задач c *NEW* до *IN_PROGRESS* и для 1 задачи с *IN_PROGRESS* до *TESTING*. Таким образом, новые статусы задач будут следующими: 53 | 54 | * IN_PROGRESS — 3 обновлённых, 1 старая 55 | * TESTING — 1 обновлённая, 4 старых 56 | * DONE — 1 старая 57 | 58 | В этом случае необходимо вернуть кортеж из 2 словарей: 59 | 60 | * Обновлённые задачи: IN_PROGRESS — 3, TESTING — 1. 61 | * Не обновлённые задачи, исключая выполненные: IN_PROGRESS — 1, TESTING — 4. 62 | 63 | __Словари не должны содержать лишних элементов__, то есть статусов, которым соответствует ноль задач. 64 | 65 | ##### Примечание ##### 66 | Обновление словаря одновременно с итерированием по нему может привести к непредсказуемым последствиям. При возникновении такой необходимости рекомендуется сначала в отдельном временном словаре собрать информацию об обновлениях, а затем применить их к основному словарю. 67 | 68 | ##### Пример кода ##### 69 | ```objectivec 70 | // Принимаем словарь по значению, чтобы иметь возможность 71 | // обращаться к отсутствующим ключам с помощью [] и получать 0, 72 | // не меняя при этом исходный словарь 73 | void PrintTasksInfo(TasksInfo tasks_info) { 74 | cout << tasks_info[TaskStatus::NEW] << " new tasks" << 75 | ", " << tasks_info[TaskStatus::IN_PROGRESS] << " tasks in progress" << 76 | ", " << tasks_info[TaskStatus::TESTING] << " tasks are being tested" << 77 | ", " << tasks_info[TaskStatus::DONE] << " tasks are done" << endl; 78 | } 79 | 80 | int main() { 81 | TeamTasks tasks; 82 | tasks.AddNewTask("Ilia"); 83 | for (int i = 0; i < 3; ++i) { 84 | tasks.AddNewTask("Ivan"); 85 | } 86 | cout << "Ilia's tasks: "; 87 | PrintTasksInfo(tasks.GetPersonTasksInfo("Ilia")); 88 | cout << "Ivan's tasks: "; 89 | PrintTasksInfo(tasks.GetPersonTasksInfo("Ivan")); 90 | 91 | TasksInfo updated_tasks, untouched_tasks; 92 | 93 | tie(updated_tasks, untouched_tasks) = 94 | tasks.PerformPersonTasks("Ivan", 2); 95 | cout << "Updated Ivan's tasks: "; 96 | PrintTasksInfo(updated_tasks); 97 | cout << "Untouched Ivan's tasks: "; 98 | PrintTasksInfo(untouched_tasks); 99 | 100 | tie(updated_tasks, untouched_tasks) = 101 | tasks.PerformPersonTasks("Ivan", 2); 102 | cout << "Updated Ivan's tasks: "; 103 | PrintTasksInfo(updated_tasks); 104 | cout << "Untouched Ivan's tasks: "; 105 | PrintTasksInfo(untouched_tasks); 106 | 107 | return 0; 108 | } 109 | 110 | ``` 111 | 112 | ###### Вывод ###### 113 | ```commandline 114 | Ilia's tasks: 1 new tasks, 0 tasks in progress, 0 tasks are being tested, 0 tasks are done 115 | Ivan's tasks: 3 new tasks, 0 tasks in progress, 0 tasks are being tested, 0 tasks are done 116 | Updated Ivan's tasks: 0 new tasks, 2 tasks in progress, 0 tasks are being tested, 0 tasks are done 117 | Untouched Ivan's tasks: 1 new tasks, 0 tasks in progress, 0 tasks are being tested, 0 tasks are done 118 | Updated Ivan's tasks: 0 new tasks, 1 tasks in progress, 1 tasks are being tested, 0 tasks are done 119 | Untouched Ivan's tasks: 0 new tasks, 1 tasks in progress, 0 tasks are being tested, 0 tasks are done 120 | ``` 121 | ##### Пояснение ##### 122 | В этой задаче вам надо прислать на проверку файл с реализацией класса _TeamTasks_. __Этот файл не должен содержать определения типов TaskStatus и TasksInfo__. В противном случае вы получите ошибку компиляции. 123 | 124 | Гарантируется, что типы _TaskStatus_ и _TasksInfo_ объявлены в точности так же, как в коде выше. -------------------------------------------------------------------------------- /week-02/01-Programming-Assignment/starter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | 10 | enum class QueryType { 11 | NewBus, 12 | BusesForStop, 13 | StopsForBus, 14 | AllBuses 15 | }; 16 | 17 | struct Query { 18 | QueryType type; 19 | string bus; 20 | string stop; 21 | vector stops; 22 | }; 23 | 24 | istream& operator >> (istream& is, Query& q) { 25 | // Реализуйте эту функцию 26 | size_t stop_count; 27 | string type, bus, stop; 28 | is >> type; 29 | if (type == "NEW_BUS") { 30 | is >> bus >> stop_count; 31 | vector stops(stop_count); 32 | for (string& stop_name : stops) { 33 | is >> stop_name; 34 | } 35 | q.type = QueryType::NewBus; 36 | q.bus = bus; 37 | q.stops = stops; 38 | } else if (type == "BUSES_FOR_STOP") { 39 | is >> stop; 40 | q.type = QueryType::BusesForStop; 41 | q.stop = stop; 42 | } else if (type == "STOPS_FOR_BUS") { 43 | is >> bus; 44 | q.type = QueryType ::StopsForBus; 45 | q.bus = bus; 46 | } else if (type == "ALL_BUSES") { 47 | q.type = QueryType::AllBuses; 48 | } 49 | 50 | return is; 51 | } 52 | 53 | struct BusesForStopResponse { 54 | // Наполните полями эту структуру 55 | string stop; 56 | vector buses; 57 | }; 58 | 59 | ostream& operator << (ostream& os, const BusesForStopResponse& r) { 60 | // Реализуйте эту функцию 61 | bool first = true; 62 | if (r.buses.empty()) { 63 | os << "No stop"; 64 | } else { 65 | for (const string& bus : r.buses) { 66 | if (!first) { 67 | os << " "; 68 | } 69 | first = false; 70 | os << bus; 71 | } 72 | } 73 | return os; 74 | } 75 | 76 | struct StopsForBusResponse { 77 | // Наполните полями эту структуру 78 | string bus; 79 | vector stops; 80 | map buses_for_stop; 81 | }; 82 | 83 | ostream& operator << (ostream& os, const StopsForBusResponse& r) { 84 | // Реализуйте эту функцию 85 | bool first = true; 86 | bool second = true; 87 | if (r.stops.empty()) { 88 | os << "No bus"; 89 | } else { 90 | for (const string& stop : r.stops) { 91 | second = true; 92 | if (!first) { 93 | os << endl; 94 | } 95 | first = false; 96 | os << "Stop " << stop << ": "; 97 | if (r.buses_for_stop.at(stop).buses.size() == 1) { 98 | os << "no interchange"; 99 | } else { 100 | for (const string& outher_bus : r.buses_for_stop.at(stop).buses) { 101 | if (!second) { 102 | os << " "; 103 | } 104 | second = false; 105 | if (r.bus != outher_bus) { 106 | os << outher_bus; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | return os; 113 | } 114 | 115 | struct AllBusesResponse { 116 | // Наполните полями эту структуру 117 | map> buses; 118 | }; 119 | 120 | ostream& operator << (ostream& os, const AllBusesResponse& r) { 121 | // Реализуйте эту функцию 122 | bool first = true; 123 | bool second = true; 124 | if (r.buses.empty()) { 125 | os << "No buses"; 126 | } else { 127 | for (const auto& bus_item : r.buses) { 128 | second = true; 129 | if (!first) { 130 | os << endl; 131 | } 132 | first = false; 133 | os << "Bus " << bus_item.first << ": "; 134 | for (const string& stop : bus_item.second) { 135 | if (!second) { 136 | os << " "; 137 | } 138 | second = false; 139 | os << stop; 140 | } 141 | } 142 | } 143 | return os; 144 | } 145 | 146 | class BusManager { 147 | public: 148 | void AddBus(const string& bus, const vector& stops) { 149 | // Реализуйте этот метод 150 | buses_to_stops[bus] = stops; 151 | for (const string& stop : stops) { 152 | stops_to_buses[stop].push_back(bus); 153 | } 154 | } 155 | 156 | BusesForStopResponse GetBusesForStop(const string& stop) const { 157 | // Реализуйте этот метод 158 | vector buses; 159 | if (stops_to_buses.count(stop) > 0) { 160 | buses = stops_to_buses.at(stop); 161 | } else { 162 | buses = {}; 163 | } 164 | return BusesForStopResponse {stop, buses}; 165 | } 166 | 167 | StopsForBusResponse GetStopsForBus(const string& bus) const { 168 | // Реализуйте этот метод 169 | vector stops; 170 | if (buses_to_stops.count(bus) > 0) { 171 | stops = buses_to_stops.at(bus); 172 | } else { 173 | stops = {}; 174 | } 175 | map buses; 176 | for (const string& stop : stops) { 177 | buses[stop] = GetBusesForStop(stop); 178 | } 179 | return StopsForBusResponse {bus, stops, buses}; 180 | } 181 | 182 | AllBusesResponse GetAllBuses() const { 183 | // Реализуйте этот метод 184 | map> buses; 185 | if (!buses_to_stops.empty()) { 186 | buses = buses_to_stops; 187 | } else { 188 | buses = {}; 189 | } 190 | return AllBusesResponse {buses}; 191 | } 192 | 193 | private: 194 | map> buses_to_stops; 195 | map> stops_to_buses; 196 | }; 197 | 198 | // Не меняя тела функции main, реализуйте функции и классы выше 199 | 200 | int main() { 201 | int query_count; 202 | Query q; 203 | 204 | cin >> query_count; 205 | 206 | BusManager bm; 207 | for (int i = 0; i < query_count; ++i) { 208 | cin >> q; 209 | switch (q.type) { 210 | case QueryType::NewBus: 211 | bm.AddBus(q.bus, q.stops); 212 | break; 213 | case QueryType::BusesForStop: 214 | cout << bm.GetBusesForStop(q.stop) << endl; 215 | break; 216 | case QueryType::StopsForBus: 217 | cout << bm.GetStopsForBus(q.bus) << endl; 218 | break; 219 | case QueryType::AllBuses: 220 | cout << bm.GetAllBuses() << endl; 221 | break; 222 | } 223 | } 224 | 225 | return 0; 226 | } 227 | --------------------------------------------------------------------------------