├── LICENSE ├── README.md ├── Week_1 ├── 01 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── matrix_sum.cpp │ └── Source │ │ └── matrix_sum.cpp ├── 02 Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── temperature.cpp ├── 03 Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── blocks_weight.cpp ├── 04 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── find_max_repetition_count.cpp ├── 05 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── team_tasks.cpp ├── 06 Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── sqr_all.cpp ├── 07 Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── element_reference.cpp └── week1.pdf ├── Week_2 ├── 01 Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── solution.cpp │ └── Source │ │ ├── correct.cpp │ │ └── starter.cpp ├── 02 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── test_equeation.cpp │ └── Source │ │ └── test_equation.cpp ├── 03 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── test_person.cpp │ └── Source │ │ └── test_person.cpp ├── 04 Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── test_rational.cpp │ └── Source │ │ └── test_rational.cpp ├── 05 Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── test_palindrom.cpp │ └── Source │ │ └── test_palindrome.cpp └── week2.pdf ├── Week_3 ├── 01 Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── sum_reverse_sort.cpp │ └── Source │ │ └── sum_reverse_sort.h ├── 02 Programming Assignment │ ├── Example.cpp │ ├── README.md │ ├── Solution │ │ └── phone_number.cpp │ └── Source │ │ └── phone_number.h ├── 03 Practice Programming Assignment │ ├── Example.h │ ├── README.md │ └── Solution │ │ └── rectangle.h ├── 04 Programming Assignment │ ├── Example │ │ ├── README.md │ │ └── code_decomposition.zip │ ├── README.md │ ├── Solution │ │ ├── bus_manager.cpp │ │ ├── bus_manager.h │ │ ├── main.cpp │ │ ├── project.7z │ │ ├── query.cpp │ │ ├── query.h │ │ ├── responses.cpp │ │ └── responses.h │ └── Source │ │ └── main.cpp └── week3.pdf ├── Week_4 ├── 01 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── print_vector_part.cpp ├── 02 Programming Assignment │ ├── Example │ │ ├── Example.cpp │ │ └── README.md │ ├── README.md │ └── Solution │ │ └── find_greater_elements.cpp ├── 03 Programming Assignment │ ├── Example │ │ ├── Example.cpp │ │ └── README.md │ ├── README.md │ └── Solution │ │ └── split_into_words.cpp ├── 04 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── remove_duplicates.cpp ├── 05 Programming Assignment │ ├── Example │ │ ├── Example.cpp │ │ └── README.md │ ├── README.md │ └── Solution │ │ └── print_permutations.cpp ├── 06 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── print_stats.cpp ├── 07 Programming Assignment │ ├── Example │ │ ├── Example_merge_sort_div2.cpp │ │ ├── Example_merge_sort_div3.cpp │ │ └── README.md │ ├── README.md │ └── Solution │ │ ├── merge_sort_div2.cpp │ │ └── merge_sort_div3.cpp ├── 08 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── find_nearest_element.cpp ├── 09 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── person_names.cpp ├── 10 Programming Assignment │ ├── Example │ │ ├── find_starts_with_char.cpp │ │ └── find_starts_with_string.cpp │ ├── README.md │ └── Solution │ │ ├── find_starts_with_char.cpp │ │ └── find_starts_with_string.cpp ├── 11 Programming Assignment │ ├── Example │ │ ├── build_expression.cpp │ │ └── build_expression_without_redundant.cpp │ ├── README.md │ └── Solution │ │ ├── build_expression.cpp │ │ └── build_expression_without_redundant.cpp └── week4.pdf ├── Week_5 ├── 01 Programming Assignment │ ├── Example │ │ └── Example.cpp │ ├── README.md │ └── Solution │ │ └── inheritance.cpp ├── 02 Practice Programming Assignment │ ├── Example.cpp │ ├── README.md │ └── Solution │ │ └── notifiers.cpp ├── 03 Programming Assignment │ ├── Example │ │ └── Example.cpp │ ├── README.md │ └── Solution │ │ └── figures.cpp ├── 04-Peer-graded-Assignment │ ├── README.md │ ├── Solution │ │ └── refactoring.cpp │ └── Source │ │ └── refactoring.cpp └── week5.pdf ├── Week_6 └── 01 Programming Assignment │ ├── Example │ ├── condition_parser.cpp │ ├── condition_parser.h │ ├── condition_parser_test.cpp │ ├── course_project_yellow.zip │ ├── database.cpp │ ├── database.h │ ├── database_test.cpp │ ├── date.cpp │ ├── date.h │ ├── date_test.cpp │ ├── event_set.cpp │ ├── event_set.h │ ├── main.cpp │ ├── node.cpp │ ├── node.h │ ├── node_test.cpp │ ├── token.cpp │ └── token.h │ ├── README.md │ ├── Solution │ ├── condition_parser.cpp │ ├── condition_parser.h │ ├── condition_parser_test.cpp │ ├── course_project_yellow.7z │ ├── database.cpp │ ├── database.h │ ├── date.cpp │ ├── date.h │ ├── main.cpp │ ├── node.cpp │ ├── node.h │ ├── test_runner.cpp │ ├── test_runner.h │ ├── token.cpp │ ├── token.h │ └── unit_tests.cpp │ ├── Source │ ├── condition_parser.cpp │ ├── condition_parser.h │ ├── condition_parser_test.cpp │ ├── main.cpp │ ├── token.cpp │ └── token.h │ ├── help1.pdf │ ├── help2.pdf │ ├── help3.pdf │ └── help4.pdf └── img.jpg /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Основы разработки на C++: желтый пояс 2 | 3 | ![alt-текст](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/img.jpg) 4 | 5 | | Basic Info | Course 2 of 5 in the [Искусство разработки на современном C++ Specialization](https://www.coursera.org/learn/c-plus-plus-yellow)| 6 | | ------------- | ------------- | 7 | | Level | Intermediate | 8 | | Language | Russian | 9 | | How To Pass | Pass all graded assignments to complete the course. | 10 | | User Ratings | Average User Rating 4.8 [See what learners said](https://www.coursera.org/learn/c-plus-plus-yellow#ratings)| 11 | 12 | * WEEK 1 ---> [Open](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/tree/master/Week_1) 13 | * WEEK 2 ---> [Open](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/tree/master/Week_2) 14 | * WEEK 3 ---> [Open](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/tree/master/Week_3) 15 | * WEEK 4 ---> [Open](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/tree/master/Week_4) 16 | * WEEK 5 ---> [Open](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/tree/master/Week_5) 17 | * WEEK 6 ---> [Open](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/tree/master/Week_6) 18 | 19 | [Основы разработки на C++: красный пояс](https://github.com/Hitoku/basics-of-c-plus-plus-development-red-belt) 20 | -------------------------------------------------------------------------------- /Week_1/01 Practice Programming Assignment/Example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Matrix { 9 | private: 10 | int num_rows_; 11 | int num_columns_; 12 | 13 | vector> elements_; 14 | 15 | public: 16 | Matrix() { 17 | num_rows_ = 0; 18 | num_columns_ = 0; 19 | } 20 | 21 | Matrix(int num_rows, int num_columns) { 22 | Reset(num_rows, num_columns); 23 | } 24 | 25 | void Reset(int num_rows, int num_columns) { 26 | if (num_rows < 0) { 27 | throw out_of_range("num_rows must be >= 0"); 28 | } 29 | if (num_columns < 0) { 30 | throw out_of_range("num_columns must be >= 0"); 31 | } 32 | if (num_rows == 0 || num_columns == 0) { 33 | num_rows = num_columns = 0; 34 | } 35 | 36 | num_rows_ = num_rows; 37 | num_columns_ = num_columns; 38 | elements_.assign(num_rows, vector(num_columns)); 39 | } 40 | 41 | int& At(int row, int column) { 42 | return elements_.at(row).at(column); 43 | } 44 | 45 | int At(int row, int column) const { 46 | return elements_.at(row).at(column); 47 | } 48 | 49 | int GetNumRows() const { 50 | return num_rows_; 51 | } 52 | 53 | int GetNumColumns() const { 54 | return num_columns_; 55 | } 56 | }; 57 | 58 | bool operator==(const Matrix& one, const Matrix& two) { 59 | if (one.GetNumRows() != two.GetNumRows()) { 60 | return false; 61 | } 62 | 63 | if (one.GetNumColumns() != two.GetNumColumns()) { 64 | return false; 65 | } 66 | 67 | for (int row = 0; row < one.GetNumRows(); ++row) { 68 | for (int column = 0; column < one.GetNumColumns(); ++column) { 69 | if (one.At(row, column) != two.At(row, column)) { 70 | return false; 71 | } 72 | } 73 | } 74 | 75 | return true; 76 | } 77 | 78 | Matrix operator+(const Matrix& one, const Matrix& two) { 79 | if (one.GetNumRows() != two.GetNumRows()) { 80 | throw invalid_argument("Mismatched number of rows"); 81 | } 82 | 83 | if (one.GetNumColumns() != two.GetNumColumns()) { 84 | throw invalid_argument("Mismatched number of columns"); 85 | } 86 | 87 | Matrix result(one.GetNumRows(), one.GetNumColumns()); 88 | for (int row = 0; row < result.GetNumRows(); ++row) { 89 | for (int column = 0; column < result.GetNumColumns(); ++column) { 90 | result.At(row, column) = one.At(row, column) + two.At(row, column); 91 | } 92 | } 93 | 94 | return result; 95 | } 96 | 97 | istream& operator>>(istream& in, Matrix& matrix) { 98 | int num_rows, num_columns; 99 | in >> num_rows >> num_columns; 100 | 101 | matrix.Reset(num_rows, num_columns); 102 | for (int row = 0; row < num_rows; ++row) { 103 | for (int column = 0; column < num_columns; ++column) { 104 | in >> matrix.At(row, column); 105 | } 106 | } 107 | 108 | return in; 109 | } 110 | 111 | ostream& operator<<(ostream& out, const Matrix& matrix) { 112 | out << matrix.GetNumRows() << " " << matrix.GetNumColumns() << endl; 113 | for (int row = 0; row < matrix.GetNumRows(); ++row) { 114 | for (int column = 0; column < matrix.GetNumColumns(); ++column) { 115 | if (column > 0) { 116 | out << " "; 117 | } 118 | out << matrix.At(row, column); 119 | } 120 | out << endl; 121 | } 122 | 123 | return out; 124 | } 125 | 126 | int main() { 127 | Matrix one; 128 | Matrix two; 129 | 130 | cin >> one >> two; 131 | cout << one + two << endl; 132 | return 0; 133 | } -------------------------------------------------------------------------------- /Week_1/01 Practice Programming Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Предисловие #### 2 | 3 | Если вы не уверены, стоит ли вам сначала пройти наш первый курс, или у вас достаточно знаний, чтобы начать с «Жёлтого пояса», попробуйте решить эту задачу. Если вы не понимаете её условие или не можете быстро решить, скорее всего, вам надо сначала пройти «Белый пояс» 4 | 5 | #### Условие #### 6 | В этой задаче вам надо разработать класс ***Matrix*** для представления целочисленной матрицы. Более подробно класс Matrix должен иметь: 7 | 8 | * конструктор по умолчанию, который создаёт матрицу с нулём строк и нулём столбцов 9 | * конструктор от двух целочисленных параметров: num_rows и num_cols, — которые задают количество строк и столбцов матрицы соответственно 10 | * метод Reset, принимающий два целочисленных параметра, которые задают новое количество строк и столбцов матрицы соответственно; метод Reset меняет размеры матрицы на заданные и обнуляет все её элементы 11 | * константный метод At, который принимает номер строки и номер столбца (именно в этом порядке; нумерация строк и столбцов начинается с нуля) и возвращает значение в соответствущей ячейке матрицы 12 | * неконстантный метод At с такими же параметрами, но возвращающий **ссылку** на значение в соответствущей ячейке матрицы 13 | * константные методы GetNumRows и GetNumColumns, которые возвращают количество строк и столбцов матрицы соответственно 14 | 15 | Если количество строк или количество столбцов, переданное в конструктор класса Matrix или метод Reset, оказалось отрицательным, то должно быть выброшено стандартное исключение [out_of_range](https://en.cppreference.com/w/cpp/error/out_of_range). 16 | 17 | Это же исключение должен бросать метод At, если переданная в него ячейка выходит за границы матрицы. 18 | 19 | Кроме того для класса Matrix должны быть определены следующие операторы: 20 | 21 | * оператор ввода из потока istream; формат ввода простой — сначала задаётся количество строк и столбцов (именно в этом порядке), а затем все элементы матрицы: сначала элемент первой строки и первого столбца, затем элемент первой строки и второго столбца и так далее 22 | * оператор вывода в поток ostream; он должен выводить матрицу в том же формате, в каком её читает оператор ввода, — в первой строке количество строк и столбцов, во второй — элементы первой строки, в третьей — элементы второй строки и т.д. 23 | * оператор проверки на равенство (==): он должен возвращать true, если сравниваемые матрицы имеют одинаковый размер и все их соответствующие элементы равны между собой, в противном случае он должен возвращать false. 24 | * оператор сложения: он должен принимать две матрицы и возвращать новую матрицу, которая является их суммой; если переданные матрицы имеют разные размеры этот оператор должен выбрасывать стандартное исключение [invalid_argument](https://en.cppreference.com/w/cpp/error/invalid_argument). 25 | 26 | Вам дана заготовка решения, а также пример ввода и вывода. Когда вы реализуете класс Matrix, вы можете использовать этот пример, чтобы убедиться, что ваш код работает правильно. 27 | 28 | Важно! Пример не проверяет выполнение всех требований, приведённых в условии. 29 | 30 | Автор задачи — Дмитрий Минченко 31 | Файл с заготовкой решения задачи 32 | 33 | [mstrix_sum.cpp](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_1/01%20Practice%20Programming%20Assignment/Source/mstrix_sum.cpp) 34 | 35 | Пример ввода 36 | 37 | ``` 38 | 3 5 39 | 6 4 -1 9 8 40 | 12 1 2 9 -5 41 | -4 0 12 8 6 42 | 43 | 3 5 44 | 5 1 0 -8 23 45 | 14 5 -6 6 9 46 | 8 0 5 4 1 47 | ``` 48 | 49 | Пример вывода 50 | ``` 51 | 3 5 52 | 11 5 -1 1 31 53 | 26 6 -4 15 4 54 | 4 0 17 12 7 55 | ``` 56 | 57 | Примечание 58 | Матрицы с нулём строк или нулём столбцов считаются пустыми. Любые две пустые матрицы равны. Сумма двух пустых матриц также является пустой матрицей. -------------------------------------------------------------------------------- /Week_1/01 Practice Programming Assignment/Source/matrix_sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // Реализуйте здесь 9 | // * класс Matrix 10 | // * оператор ввода для класса Matrix из потока istream 11 | // * оператор вывода класса Matrix в поток ostream 12 | // * оператор проверки на равенство двух объектов класса Matrix 13 | // * оператор сложения двух объектов класса Matrix 14 | 15 | int main() { 16 | Matrix one; 17 | Matrix two; 18 | 19 | cin >> one >> two; 20 | cout << one + two << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /Week_1/02 Programming Assignment/Example.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | При решении задачи необходимо было обратить внимание на два момента: 3 | 4 | * Сумма температур может достигать 10^14, поэтому должна храниться в типе int64_t. 5 | * Сумма температур может быть отрицательной, поэтому не должна делиться на беззнаковое число при вычислении среднего арифметического. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | int main() { 14 | int n; 15 | cin >> n; 16 | vector temperatures(n); 17 | int64_t sum = 0; 18 | for (int& temperature : temperatures) { 19 | cin >> temperature; 20 | sum += temperature; 21 | } 22 | 23 | int average = sum / n; 24 | 25 | vector above_average_indices; 26 | for (int i = 0; i < n; ++i) { 27 | if (temperatures[i] > average) { 28 | above_average_indices.push_back(i); 29 | } 30 | } 31 | 32 | cout << above_average_indices.size() << endl; 33 | for (int i : above_average_indices) { 34 | cout << i << " "; 35 | } 36 | cout << endl; 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /Week_1/02 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_1/02 Programming Assignment/Solution/temperature.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //------------------------------------------------------------------------------------------------- 5 | int main() 6 | { 7 | unsigned int size = 0; 8 | std::cin >> size; 9 | 10 | int64_t sum = 0; 11 | std::vector temperatures(size); 12 | for (auto & temperature : temperatures) 13 | { 14 | std::cin >> temperature; 15 | sum += temperature; 16 | } 17 | 18 | int64_t avg = sum / static_cast(size); 19 | std::vector result; 20 | for (size_t i = 0; i < size; i++) 21 | { 22 | if (temperatures[i] > avg) 23 | { 24 | result.push_back(i); 25 | } 26 | } 27 | 28 | std::cout << result.size() << std::endl; 29 | 30 | for (const auto result_index : result) 31 | { 32 | std::cout << result_index << " "; 33 | } 34 | std::cout << std::endl; 35 | return 0; 36 | } 37 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_1/03 Programming Assignment/Example.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Главное, на что нужно было обратить внимание при решении задачи — корректный выбор целочисленных типов. Как следует 3 | из условия, максимально возможное значение массы равно 10^4 * 10^4 * 10^4 * 10^5 * 100 = 10^19, что умещается лишь в 4 | тип uint64_t. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | int main() { 13 | int N, R; 14 | cin >> N >> R; 15 | uint64_t answer = 0; 16 | for (int i = 0; i < N; ++i) { 17 | int W, H, D; 18 | cin >> W >> H >> D; 19 | // Если не привести W к типу uint64_t перед умножением, 20 | // произведение будет иметь тип int и случится переполнение. 21 | // Альтернативное решение — хранить сами W, H, D в uint64_t 22 | answer += static_cast(W) * H * D; 23 | } 24 | answer *= R; 25 | cout << answer << endl; 26 | return 0; 27 | } -------------------------------------------------------------------------------- /Week_1/03 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_1/03 Programming Assignment/Solution/blocks_weight.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //---------------------------------------------------------------------------------------------------- 5 | int main() 6 | { 7 | int quantity = 0; 8 | std::cin >> quantity; 9 | 10 | int density = 0; 11 | std::cin >> density; 12 | 13 | uint64_t weight = 0; 14 | 15 | for (int i = 0; i < quantity; ++i) 16 | { 17 | int width = 0; 18 | std::cin >> width; 19 | 20 | int height = 0; 21 | std::cin >> height; 22 | 23 | int length = 0; 24 | std::cin >> length; 25 | 26 | weight += static_cast(width) * height * length; 27 | } 28 | weight *= density; 29 | std::cout << weight << std::endl; 30 | 31 | return 0; 32 | } 33 | //---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_1/04 Practice Programming Assignment/Example.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 repetition_count; 15 | for (const Region& region : regions) { 16 | result = max(result, ++repetition_count[region]); 17 | } 18 | return result; 19 | } -------------------------------------------------------------------------------- /Week_1/04 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_, а также дополнительных функций, если это необходим. __Этот файл не должен содержать типы Lang и Region__. В противном случае вы получите ошибку компиляции. -------------------------------------------------------------------------------- /Week_1/04 Practice Programming Assignment/Solution/find_max_repetition_count.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //------------------------------------------------------------------------------------------------- 6 | /* 7 | enum class Lang 8 | { 9 | DE, FR, IT 10 | }; 11 | */ 12 | //------------------------------------------------------------------------------------------------- 13 | /* 14 | struct Region 15 | { 16 | std::string std_name; 17 | std::string parent_std_name; 18 | std::map names; 19 | int64_t population; 20 | }; 21 | */ 22 | //------------------------------------------------------------------------------------------------- 23 | bool operator<(const Region& lhs, const Region& rhs) 24 | { 25 | return std::tie(lhs.std_name, lhs.parent_std_name, lhs.names, lhs.population) < 26 | std::tie(rhs.std_name, rhs.parent_std_name, rhs.names, rhs.population); 27 | } 28 | //------------------------------------------------------------------------------------------------- 29 | int FindMaxRepetitionCount(const vector& regions) 30 | { 31 | int result = 0; 32 | map repetition_count; 33 | 34 | for (const Region& region : regions) 35 | { 36 | result = std::max(result, ++repetition_count[region]); 37 | } 38 | return result; 39 | } 40 | //------------------------------------------------------------------------------------------------- 41 | /* 42 | int main() 43 | { 44 | std::cout << FindMaxRepetitionCount({ 45 | { 46 | "Moscow", 47 | "Russia", 48 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 49 | 89 50 | }, { 51 | "Russia", 52 | "Eurasia", 53 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 54 | 89 55 | }, { 56 | "Moscow", 57 | "Russia", 58 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 59 | 89 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 | }) << std::endl; 72 | 73 | std::cout << FindMaxRepetitionCount({ 74 | { 75 | "Moscow", 76 | "Russia", 77 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 78 | 89 79 | }, { 80 | "Russia", 81 | "Eurasia", 82 | {{Lang::DE, "Russland"}, {Lang::FR, "Russie"}, {Lang::IT, "Russia"}}, 83 | 89 84 | }, { 85 | "Moscow", 86 | "Russia", 87 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou deux"}, {Lang::IT, "Mosca"}}, 88 | 89 89 | }, { 90 | "Moscow", 91 | "Toulouse", 92 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 93 | 89 94 | }, { 95 | "Moscow", 96 | "Russia", 97 | {{Lang::DE, "Moskau"}, {Lang::FR, "Moscou"}, {Lang::IT, "Mosca"}}, 98 | 31 99 | }, 100 | }) << std::endl; 101 | 102 | return 0; 103 | } 104 | */ 105 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_1/06 Programming Assignment/Example.cpp: -------------------------------------------------------------------------------- 1 | //Реализуем функцию Sqr для чисел, словарей, векторов и пар. 2 | 3 | // Объявим функции без тела, 4 | // чтобы их можно было использовать в произвольном порядке 5 | 6 | // Для простых типов 7 | template 8 | T Sqr(T value); 9 | 10 | // Для вектора 11 | template 12 | vector Sqr(const vector& value); 13 | 14 | // Для словаря 15 | template 16 | map Sqr(const map& value); 17 | 18 | // Для пары 19 | template 20 | pair Sqr(const pair& value); 21 | 22 | // Теперь реализуем их в соответствии с заданием 23 | template 24 | T Sqr(T value) { 25 | return value * value; 26 | } 27 | 28 | template 29 | vector Sqr(const vector& value) { 30 | vector result; 31 | for (const T& x : value) { 32 | // Здесь важно, что вместо x * x вызывается функция Sqr: 33 | // это позволяет возводить в квадрат составные объекты 34 | result.push_back(Sqr(x)); 35 | } 36 | 37 | return result; 38 | } 39 | 40 | template 41 | map Sqr(const map& value) { 42 | map result; 43 | for (const auto& element : value) { 44 | result[element.first] = Sqr(element.second); 45 | } 46 | return result; 47 | } 48 | 49 | template 50 | pair Sqr(const pair& value) { 51 | return {Sqr(value.first), Sqr(value.second)}; 52 | } -------------------------------------------------------------------------------- /Week_1/06 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_1/06 Programming Assignment/Solution/sqr_all.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //------------------------------------------------------------------------------------------------- 6 | template 7 | T Sqr(T value); 8 | template 9 | std::vector Sqr(const std::vector& vectr); 10 | template 11 | std::map Sqr(const std::map& map_arg); 12 | template 13 | std::pair Sqr(const std::pair& pair_arg); 14 | //------------------------------------------------------------------------------------------------- 15 | int main() 16 | { 17 | // Пример вызова функции 18 | std::vector v = { 1, 2, 3 }; 19 | 20 | std::cout << "vector:"; 21 | 22 | for (int x : Sqr(v)) 23 | { 24 | std::cout << ' ' << x; 25 | } 26 | std::cout << std::endl; 27 | 28 | std::map> map_of_pairs = 29 | { 30 | {4, {2, 2}}, 31 | {7, {4, 3}} 32 | }; 33 | std::cout << "map of pairs:" << std::endl; 34 | 35 | for (const auto& x : Sqr(map_of_pairs)) 36 | { 37 | std::cout << x.first << ' ' << x.second.first << ' ' << x.second.second << std::endl; 38 | } 39 | return 0; 40 | } 41 | //------------------------------------------------------------------------------------------------- 42 | template 43 | T Sqr(T value) 44 | { 45 | return value * value; 46 | } 47 | //------------------------------------------------------------------------------------------------- 48 | template 49 | std::vector Sqr(const std::vector& vectr) 50 | { 51 | std::vector tmp; 52 | 53 | for (const T & item : vectr) 54 | { 55 | tmp.push_back(Sqr(item)); 56 | } 57 | return tmp; 58 | } 59 | //------------------------------------------------------------------------------------------------- 60 | template 61 | std::map Sqr(const std::map& map_arg) 62 | { 63 | std::map temp; 64 | for (auto & item : map_arg) 65 | { 66 | temp[item.first] = Sqr(item.second); 67 | } 68 | return temp; 69 | } 70 | //------------------------------------------------------------------------------------------------- 71 | template 72 | std::pair Sqr(const std::pair& pair_arg) 73 | { 74 | return {Sqr(pair_arg.first), Sqr(pair_arg.second)}; 75 | } 76 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_1/07 Programming Assignment/Example.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_1/07 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_1/07 Programming Assignment/Solution/element_reference.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //------------------------------------------------------------------------------------------------- 5 | template 6 | type & GetRefStrict(std::map & map_prm, key key_prm) 7 | { 8 | if (map_prm.count(key_prm) == 0) 9 | { 10 | throw std::runtime_error("item by key k in the collection is missing"); 11 | } 12 | return map_prm[key_prm]; 13 | } 14 | //------------------------------------------------------------------------------------------------- 15 | int main() 16 | { 17 | std::map m = { {0, "value"} }; 18 | std::string& item = GetRefStrict(m, 0); 19 | item = "newvalue"; 20 | std::cout << m[0] << std::endl; 21 | 22 | return 0; 23 | } 24 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_1/week1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_1/week1.pdf -------------------------------------------------------------------------------- /Week_2/01 Programming Assignment/Source/correct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | int q; 10 | cin >> q; 11 | 12 | map> buses_to_stops, stops_to_buses; 13 | 14 | for (int i = 0; i < q; ++i) { 15 | string operation_code; 16 | cin >> operation_code; 17 | 18 | if (operation_code == "NEW_BUS") { 19 | 20 | string bus; 21 | cin >> bus; 22 | int stop_count; 23 | cin >> stop_count; 24 | vector& stops = buses_to_stops[bus]; 25 | stops.resize(stop_count); 26 | for (string& stop : stops) { 27 | cin >> stop; 28 | stops_to_buses[stop].push_back(bus); 29 | } 30 | 31 | } else if (operation_code == "BUSES_FOR_STOP") { 32 | 33 | string stop; 34 | cin >> stop; 35 | if (stops_to_buses.count(stop) == 0) { 36 | cout << "No stop" << endl; 37 | } else { 38 | for (const string& bus : stops_to_buses[stop]) { 39 | cout << bus << " "; 40 | } 41 | cout << endl; 42 | } 43 | 44 | } else if (operation_code == "STOPS_FOR_BUS") { 45 | 46 | string bus; 47 | cin >> bus; 48 | if (buses_to_stops.count(bus) == 0) { 49 | cout << "No bus" << endl; 50 | } else { 51 | for (const string& stop : buses_to_stops[bus]) { 52 | cout << "Stop " << stop << ": "; 53 | if (stops_to_buses[stop].size() == 1) { 54 | cout << "no interchange"; 55 | } else { 56 | for (const string& other_bus : stops_to_buses[stop]) { 57 | if (bus != other_bus) { 58 | cout << other_bus << " "; 59 | } 60 | } 61 | } 62 | cout << endl; 63 | } 64 | } 65 | 66 | } else if (operation_code == "ALL_BUSES") { 67 | 68 | if (buses_to_stops.empty()) { 69 | cout << "No buses" << endl; 70 | } else { 71 | for (const auto& bus_item : buses_to_stops) { 72 | cout << "Bus " << bus_item.first << ": "; 73 | for (const string& stop : bus_item.second) { 74 | cout << stop << " "; 75 | } 76 | cout << endl; 77 | } 78 | } 79 | 80 | } 81 | } 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /Week_2/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_2/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/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_2/02%20Practice%20Programming%20Assignment/Source/test_equation.cpp) -------------------------------------------------------------------------------- /Week_2/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_2/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/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_2/03%20Practice%20Programming%20Assignment/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_), но не умеет это делать для классов. -------------------------------------------------------------------------------- /Week_2/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_2/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 | int Numerator() const; 11 | int Denominator() const; 12 | }; 13 | ``` 14 | Список требований, предъявляемых к реализации интерфейса класса _Rational_: 15 | 16 | 1. Конструктор по умолчанию должен создавать дробь с числителем 0 и знаменателем 1. 17 | 2. При конструировании объекта класса _Rational_ с параметрами p и q должно выполняться сокращение дроби p/q. 18 | 3. Если дробь p/q отрицательная, то объект _Rational(p, q)_ должен иметь отрицательный числитель и положительный знаменатель. 19 | 4. Если дробь p/q положительная, то объект _Rational(p, q)_ должен иметь положительные числитель и знаменатель (обратите внимание на случай _Rational(-2, -3)_). 20 | 5. Если числитель дроби равен нулю, то знаменатель должен быть равен 1. 21 | 22 | Разработайте набор юнит-тестов, которые будут проверять корректность реализации класса _Rational_. **Тестировать случай, когда знаменатель равен нулю, не надо**. 23 | 24 | Начать работу вы можете с шаблона, который содержит наш фреймворк юнит-тестов и заготовку класса _Rational_. 25 | 26 | [test_rational.cpp](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_2/04%20Programming%20Assignment/Source/test_rational.cpp) 27 | 28 | ##### Примечание ##### 29 | Перед отправкой вашего файла убедитесь, что он не содержит класса _Person_. В противном случае вы получите ошибку компиляции. Наша тестирующая система умеет игнорировать функции в файлах (поэтому, например, в задаче "Тесты для функции _IsPalindrom_" необязательно удалять функцию _IsPalindrom_), но не умеет это делать для классов. -------------------------------------------------------------------------------- /Week_2/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_2/05 Programming Assignment/Example.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 | } -------------------------------------------------------------------------------- /Week_2/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/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_2/05%20Programming%20Assignment/Source/test_palindrome.cpp) -------------------------------------------------------------------------------- /Week_2/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_2/week2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_2/week2.pdf -------------------------------------------------------------------------------- /Week_3/01 Programming Assignment/Example.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 | } -------------------------------------------------------------------------------- /Week_3/01 Programming Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Реализовать функции, объявленные в заголовочном файле #### 2 | 3 | 4 | Вам дан заголовочный файл *sum_reverse_sort.h*, содержащий объявления трёх функций 5 | 6 | [sum_reverse_sort.h](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_3/01%20Programming%20Assignment/Source/sum_reverse_sort.h) 7 | 8 | ```objectivec 9 | #pragma once 10 | #include 11 | #include 12 | using namespace std; 13 | int Sum(int x, int y); 14 | string Reverse(string s); 15 | void Sort(vector& nums); 16 | ``` 17 | Вам надо прислать *cpp*-файл, содержащий определения этих функций. 18 | 19 | ##### Как будет тестироваться ваш код ##### 20 | Автоматическая тестирующая система добавит ваш *cpp*-файл в проект, содержащий другой *cpp*-файл с юнит-тестами для всех трёх функций, а также файл *sum_reverse_sort.h*. Затем она соберёт этот проект и, если компиляция будет выполнена успешно, запустит получившийся исполняемый файл. Если он завершится успешно (т. е. юнит-тесты не найдут ошибок в вашей реализации), то ваша посылка будет засчитана. -------------------------------------------------------------------------------- /Week_3/01 Programming Assignment/Solution/sum_reverse_sort.cpp: -------------------------------------------------------------------------------- 1 | #include "sum_reverse_sort.h" 2 | #include 3 | 4 | //------------------------------------------------------------------------------------------------- 5 | int Sum(int x, int y) 6 | { 7 | return x + y; 8 | } 9 | //------------------------------------------------------------------------------------------------- 10 | string Reverse(string s) 11 | { 12 | std::reverse(s.begin(), s.end()); 13 | return s; 14 | } 15 | //------------------------------------------------------------------------------------------------- 16 | void Sort(vector& nums) 17 | { 18 | std::sort(nums.begin(), nums.end()); 19 | } 20 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_3/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_3/02 Programming Assignment/Example.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 | } -------------------------------------------------------------------------------- /Week_3/02 Programming Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Реализовать класс, объявленный в заголовочном файле #### 2 | 3 | 4 | Вам дан заголовочный файл *phone_number.h*, содержащий объявление класса *PhoneNumber*. При этом в комментариях описано поведение, которое ожидается от реализации этого класса. 5 | 6 | [phone_number.h](https://github.com/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_3/02%20Programming%20Assignment/Source/phone_number.h) 7 | 8 | ```objectivec 9 | #pragma once 10 | #include 11 | using namespace std; 12 | class PhoneNumber { 13 | public: 14 | /* Принимает строку в формате +XXX-YYY-ZZZZZZ 15 | Часть от '+' до первого '-' - это код страны. 16 | Часть между первым и вторым символами '-' - код города 17 | Всё, что идёт после второго символа '-' - местный номер. 18 | Код страны, код города и местный номер не должны быть пустыми. 19 | Если строка не соответствует этому формату, нужно выбросить исключение invalid_argument. Проверять, что номер содержит только цифры, не нужно. 20 | Примеры: 21 | * +7-495-111-22-33 22 | * +7-495-1112233 23 | * +323-22-460002 24 | * +1-2-coursera-cpp 25 | * 1-2-333 - некорректный номер - не начинается на '+' 26 | * +7-1233 - некорректный номер - есть только код страны и города 27 | */ 28 | explicit PhoneNumber(const string &international_number); 29 | string GetCountryCode() const; 30 | string GetCityCode() const; 31 | string GetLocalNumber() const; 32 | string GetInternationalNumber() const; 33 | private: 34 | string country_code_; 35 | string city_code_; 36 | string local_number_; 37 | }; 38 | ``` 39 | Пришлите *cpp*-файл **с определениями методов** класса *PhoneNumber*, которые реализуют описанное поведение. 40 | 41 | ##### Как будет тестироваться ваш код ##### 42 | Автоматическая тестирующая система добавит ваш *cpp*-файл в проект, содержащий другой *cpp*-файл с юнит-тестами для класса *PhoneNumber*, а также файл *phone_number.h*. Затем она соберёт этот проект и, если компиляция будет выполнена успешно, запустит получившийся исполняемый файл. Если он завершится успешно (т. е. юнит-тесты не найдут ошибок в вашей реализации), то ваша посылка будет засчитана. 43 | Автоматическая тестирующая система добавит ваш *cpp*-файл в проект, содержащий другой *cpp*-файл с юнит-тестами для класса *PhoneNumber*, а также файл *phone_number.h*. Затем она соберёт этот проект и, если компиляция будет выполнена успешно, запустит получившийся исполняемый файл. Если он завершится успешно (т. е. юнит-тесты не найдут ошибок в вашей реализации), то ваша посылка будет засчитана. -------------------------------------------------------------------------------- /Week_3/02 Programming Assignment/Solution/phone_number.cpp: -------------------------------------------------------------------------------- 1 | #include "phone_number.h" 2 | #include 3 | 4 | //------------------------------------------------------------------------------------------------- 5 | PhoneNumber::PhoneNumber(const string& international_number) 6 | { 7 | std::istringstream in_string(international_number); 8 | const char sign = in_string.get(); 9 | 10 | if (in_string) 11 | { 12 | std::getline(in_string, country_code_, '-'); 13 | std::getline(in_string, city_code_, '-'); 14 | std::getline(in_string, local_number_, '\n'); 15 | } 16 | 17 | if (sign != '+' || country_code_.empty()) 18 | { 19 | throw invalid_argument("The country code must begin with a + sign and be at least one character"); 20 | } 21 | 22 | if (city_code_.empty()) 23 | { 24 | throw invalid_argument("Area code cannot be empty"); 25 | } 26 | 27 | if (local_number_.empty()) 28 | { 29 | throw invalid_argument("Phone number cannot be empty"); 30 | } 31 | } 32 | //------------------------------------------------------------------------------------------------- 33 | string PhoneNumber::GetCountryCode() const 34 | { 35 | return country_code_; 36 | } 37 | //------------------------------------------------------------------------------------------------- 38 | string PhoneNumber::GetCityCode() const 39 | { 40 | return city_code_; 41 | } 42 | //------------------------------------------------------------------------------------------------- 43 | string PhoneNumber::GetLocalNumber() const 44 | { 45 | return local_number_; 46 | } 47 | //------------------------------------------------------------------------------------------------- 48 | string PhoneNumber::GetInternationalNumber() const 49 | { 50 | return ("+" + country_code_ + "-" + city_code_ + "-" + local_number_); 51 | } 52 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_3/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_3/03 Practice Programming Assignment/Example.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 | }; -------------------------------------------------------------------------------- /Week_3/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 | int GetArea() const { 12 | return width_ * height_; 13 | } 14 | int GetPerimeter() const { 15 | return 2 * (width_ + height_); 16 | } 17 | int GetWidth() const { return width_; } 18 | int GetHeight() const { return height_; } 19 | private: 20 | int width_, height_; 21 | }; 22 | ``` 23 | Пришлите заголовочный файл *rectangle.h*, содержащий объявление класса *Rectangle*. Это должен быть полноценный заголовочный файл, который можно использовать в большом проекте. В частности, в нём должна быть решена проблема двойного включения. -------------------------------------------------------------------------------- /Week_3/03 Practice Programming Assignment/Solution/rectangle.h: -------------------------------------------------------------------------------- 1 | #ifndef _RECTANGLE_H_ 2 | #define _RECTANGLE_H_ 3 | 4 | //------------------------------------------------------------------------------------------------- 5 | class Rectangle 6 | { 7 | public: 8 | Rectangle(int width, int height); 9 | 10 | int GetArea() const; 11 | int GetPerimeter() const; 12 | int GetWidth() const; 13 | int GetHeight() const; 14 | private: 15 | int width_; 16 | int height_; 17 | }; 18 | //------------------------------------------------------------------------------------------------- 19 | #endif //_RECTANGLE_H_ -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Example/README.md: -------------------------------------------------------------------------------- 1 | Многофайловый проект приведён в архиве *code_decomposition.zip* -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Example/code_decomposition.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_3/04 Programming Assignment/Example/code_decomposition.zip -------------------------------------------------------------------------------- /Week_3/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/Hitoku/basics-of-c-plus-plus-development-yellow-belt/blob/master/Week_3/04%20Programming%20Assignment/Source/main.cpp) -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/bus_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "bus_manager.h" 2 | 3 | //------------------------------------------------------------------------------------------------- 4 | void BusManager::AddBus(const std::string& bus, const std::vector& stops) 5 | { 6 | buses_to_stops[bus] = stops; 7 | for (const auto& stop : stops) 8 | { 9 | stops_to_buses[stop].push_back(bus); 10 | } 11 | } 12 | //------------------------------------------------------------------------------------------------- 13 | BusesForStopResponse BusManager::GetBusesForStop(const std::string& stop) const 14 | { 15 | if (stops_to_buses.count(stop) == 0) 16 | { 17 | return BusesForStopResponse{ std::vector() }; 18 | } 19 | else 20 | { 21 | return BusesForStopResponse{ stops_to_buses.at(stop) }; 22 | } 23 | } 24 | //------------------------------------------------------------------------------------------------- 25 | StopsForBusResponse BusManager::GetStopsForBus(const std::string& bus) const 26 | { 27 | std::vector>> result; 28 | if (buses_to_stops.count(bus) > 0) 29 | { 30 | for (const auto& stop : buses_to_stops.at(bus)) 31 | { 32 | result.push_back(make_pair(stop, stops_to_buses.at(stop))); 33 | } 34 | } 35 | return StopsForBusResponse{ bus, result }; 36 | } 37 | //------------------------------------------------------------------------------------------------- 38 | AllBusesResponse BusManager::GetAllBuses() const 39 | { 40 | return AllBusesResponse{ buses_to_stops }; 41 | } 42 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/bus_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "responses.h" 9 | 10 | //------------------------------------------------------------------------------------------------- 11 | class BusManager 12 | { 13 | private: 14 | std::map> buses_to_stops; 15 | std::map> stops_to_buses; 16 | public: 17 | void AddBus(const std::string& bus, const std::vector& stops); 18 | 19 | BusesForStopResponse GetBusesForStop(const std::string& stop) const; 20 | StopsForBusResponse GetStopsForBus(const std::string& bus) const; 21 | AllBusesResponse GetAllBuses() const; 22 | }; 23 | //------------------------------------------------------------------------------------------------- 24 | -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/main.cpp: -------------------------------------------------------------------------------- 1 | #include "bus_manager.h" 2 | #include "query.h" 3 | 4 | //------------------------------------------------------------------------------------------------- 5 | int main() 6 | { 7 | int query_count; 8 | Query q; 9 | 10 | std::cin >> query_count; 11 | 12 | BusManager bm; 13 | for (int i = 0; i < query_count; ++i) 14 | { 15 | std::cin >> q; 16 | switch (q.type) 17 | { 18 | case QueryType::NewBus: 19 | bm.AddBus(q.bus, q.stops); 20 | break; 21 | case QueryType::BusesForStop: 22 | std::cout << bm.GetBusesForStop(q.stop) << std::endl; 23 | break; 24 | case QueryType::StopsForBus: 25 | std::cout << bm.GetStopsForBus(q.bus) << std::endl; 26 | break; 27 | case QueryType::AllBuses: 28 | std::cout << bm.GetAllBuses() << std::endl; 29 | break; 30 | } 31 | } 32 | } 33 | //------------------------------------------------------------------------------------------------- 34 | -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/project.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_3/04 Programming Assignment/Solution/project.7z -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/query.cpp: -------------------------------------------------------------------------------- 1 | #include "query.h" 2 | 3 | //------------------------------------------------------------------------------------------------- 4 | std::istream& operator >> (std::istream& is, Query& q) 5 | { 6 | std::string operation_code; 7 | is >> operation_code; 8 | 9 | if (operation_code == "NEW_BUS") 10 | { 11 | q.type = QueryType::NewBus; 12 | is >> q.bus; 13 | 14 | size_t stop_count = 0; 15 | is >> stop_count; 16 | 17 | q.stops.resize(stop_count); 18 | for (auto & item : q.stops) 19 | { 20 | is >> item; 21 | } 22 | } 23 | else 24 | if (operation_code == "BUSES_FOR_STOP") 25 | { 26 | q.type = QueryType::BusesForStop; 27 | is >> q.stop; 28 | } 29 | else 30 | if (operation_code == "STOPS_FOR_BUS") 31 | { 32 | q.type = QueryType::StopsForBus; 33 | is >> q.bus; 34 | } 35 | else 36 | if (operation_code == "ALL_BUSES") 37 | { 38 | q.type = QueryType::AllBuses; 39 | } 40 | return is; 41 | } 42 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/query.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //------------------------------------------------------------------------------------------------- 8 | enum class QueryType 9 | { 10 | NewBus, 11 | BusesForStop, 12 | StopsForBus, 13 | AllBuses 14 | }; 15 | //------------------------------------------------------------------------------------------------- 16 | struct Query 17 | { 18 | QueryType type; 19 | std::string bus; 20 | std::string stop; 21 | std::vector stops; 22 | }; 23 | //------------------------------------------------------------------------------------------------- 24 | std::istream& operator >> (std::istream& is, Query& q); 25 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/responses.cpp: -------------------------------------------------------------------------------- 1 | #include "responses.h" 2 | 3 | //------------------------------------------------------------------------------------------------- 4 | std::ostream& operator << (std::ostream& os, const BusesForStopResponse& r) 5 | { 6 | if (r.buses_to_stop.empty()) 7 | { 8 | os << "No stop" << std::endl; 9 | } 10 | else 11 | { 12 | for (const std::string& bus : r.buses_to_stop) 13 | { 14 | os << bus << " "; 15 | } 16 | os << std::endl; 17 | } 18 | return os; 19 | } 20 | //------------------------------------------------------------------------------------------------- 21 | std::ostream& operator << (std::ostream& os, const StopsForBusResponse& r) 22 | { 23 | if (r.stops_for_buses.empty()) 24 | { 25 | os << "No bus" << std::endl; 26 | } 27 | else 28 | { 29 | for (const auto& stop : r.stops_for_buses) 30 | { 31 | os << "Stop " << stop.first << ": "; 32 | if (stop.second.size() == 1) 33 | { 34 | os << "no interchange"; 35 | } 36 | else 37 | { 38 | for (const auto& other_bus : stop.second) 39 | { 40 | if (other_bus != r.bus) 41 | { 42 | os << other_bus << " "; 43 | } 44 | } 45 | } 46 | os << std::endl; 47 | } 48 | } 49 | return os; 50 | } 51 | //------------------------------------------------------------------------------------------------- 52 | std::ostream& operator << (std::ostream& os, const AllBusesResponse& r) 53 | { 54 | if (r.buses_to_stops.empty()) 55 | { 56 | os << "No buses" << std::endl; 57 | } 58 | else 59 | { 60 | for (const auto& bus_item : r.buses_to_stops) 61 | { 62 | os << "Bus " << bus_item.first << ": "; 63 | for (const std::string& stop : bus_item.second) 64 | { 65 | os << stop << " "; 66 | } 67 | os << std::endl; 68 | } 69 | } 70 | return os; 71 | } 72 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_3/04 Programming Assignment/Solution/responses.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //------------------------------------------------------------------------------------------------- 9 | struct BusesForStopResponse 10 | { 11 | std::vector buses_to_stop; 12 | }; 13 | std::ostream& operator << (std::ostream& os, const BusesForStopResponse& r); 14 | //------------------------------------------------------------------------------------------------- 15 | struct StopsForBusResponse 16 | { 17 | std::string bus; 18 | std::vector>> stops_for_buses; 19 | }; 20 | std::ostream& operator << (std::ostream& os, const StopsForBusResponse& r); 21 | //------------------------------------------------------------------------------------------------- 22 | struct AllBusesResponse 23 | { 24 | std::map> buses_to_stops; 25 | }; 26 | std::ostream& operator << (std::ostream& os, const AllBusesResponse& r); 27 | //------------------------------------------------------------------------------------------------- 28 | -------------------------------------------------------------------------------- /Week_3/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_3/week3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_3/week3.pdf -------------------------------------------------------------------------------- /Week_4/01 Practice Programming Assignment/Example.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 | } -------------------------------------------------------------------------------- /Week_4/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 | 4 5 8 1 6 21 | ``` -------------------------------------------------------------------------------- /Week_4/01 Practice Programming Assignment/Solution/print_vector_part.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //------------------------------------------------------------------------------------------------- 6 | void PrintVectorPart(const std::vector& numbers) 7 | { 8 | auto itr = std::find_if(numbers.begin(), numbers.end(), [](const int& x) { return x < 0; }); 9 | while (itr != numbers.begin()) 10 | { 11 | itr--; 12 | std::cout << *itr << " "; 13 | } 14 | } 15 | //------------------------------------------------------------------------------------------------- 16 | int main() 17 | { 18 | PrintVectorPart({ 6, 1, 8, -5, 4 }); 19 | std::cout << std::endl; 20 | PrintVectorPart({ -6, 1, 8, -5, 4 }); // ничего не выведется 21 | std::cout << std::endl; 22 | PrintVectorPart({ 6, 1, 8, 5, 4 }); 23 | std::cout << std::endl; 24 | 25 | return 0; 26 | } 27 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/02 Programming Assignment/Example/Example.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 | } -------------------------------------------------------------------------------- /Week_4/02 Programming Assignment/Example/README.md: -------------------------------------------------------------------------------- 1 | Ключевой момент решения — поиск первого элемента, большего *border*. Позже мы научимся делать это оптимально, а пока достаточно использовать для этого обычный цикл *while*. 2 | 3 | Как только найден итератор на первый элемент, больший *border*, достаточно создать вектор из полуинтервала, начинающегося в этом итераторе и заканчивающегося в конце множества — это и будут все элементы, большие *border*, в возрастающем порядке. -------------------------------------------------------------------------------- /Week_4/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_4/02 Programming Assignment/Solution/find_greater_elements.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | //------------------------------------------------------------------------------------------------- 8 | template 9 | std::vector FindGreaterElements(const std::set& elements, const T& border) 10 | { 11 | auto itr = std::find_if(elements.begin(), elements.end(), [border](const T& x) { return x > border; }); 12 | 13 | std::vector temp; 14 | for (auto i = itr; i != elements.end(); i++) 15 | { 16 | temp.push_back(*i); 17 | } 18 | return temp; 19 | } 20 | //------------------------------------------------------------------------------------------------- 21 | int main() 22 | { 23 | for (int x : FindGreaterElements(std::set{1, 5, 7, 8}, 5)) 24 | { 25 | std::cout << x << " "; 26 | } 27 | std::cout << std::endl; 28 | 29 | std::string to_find = "Python"; 30 | std::cout << FindGreaterElements(std::set{"C", "C++"}, to_find).size() << std::endl; 31 | 32 | return 0; 33 | } 34 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/03 Programming Assignment/Example/Example.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 | } -------------------------------------------------------------------------------- /Week_4/03 Programming Assignment/Example/README.md: -------------------------------------------------------------------------------- 1 | Идея решения заключается в итеративном поиске очередного пробела в строке. Как только он найден, его позиция задаёт конец очередного слова, которое можно добавить к ответу. Поиск следующего пробела будет продолжаться со следующей позиции. 2 | -------------------------------------------------------------------------------- /Week_4/03 Programming Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Разбиение на слова #### 2 | 3 | Напишите функцию *SplitIntoWords*, разбивающую строку на слова по пробелам. 4 | ```objectivec 5 | vector SplitIntoWords(const string& s); 6 | ``` 7 | Гарантируется, что: 8 | * строка непуста; 9 | * строка состоит лишь из латинских букв и пробелов; 10 | * первый и последний символы строки не являются пробелами; 11 | * строка не содержит двух пробелов подряд. 12 | 13 | ##### Подсказка ##### 14 | Рекомендуется следующий способ решения задачи: 15 | * искать очередной пробел с помощью алгоритма find; 16 | * создавать очередное слово с помощью конструктора строки по двум итераторам. 17 | 18 | ##### Пример кода ##### 19 | ```objectivec 20 | int main() { 21 | string s = "C Cpp Java Python"; 22 | vector words = SplitIntoWords(s); 23 | cout << words.size() << " "; 24 | for (auto it = begin(words); it != end(words); ++it) { 25 | if (it != begin(words)) { 26 | cout << "/"; 27 | } 28 | cout << *it; 29 | } 30 | cout << endl; 31 | 32 | return 0; 33 | } 34 | ``` 35 | ###### Вывод ###### 36 | ```commandline 37 | С/Cpp/Java/Python 38 | ``` -------------------------------------------------------------------------------- /Week_4/03 Programming Assignment/Solution/split_into_words.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //------------------------------------------------------------------------------------------------- 7 | std::vector SplitIntoWords(const std::string& s) 8 | { 9 | std::vector str; 10 | 11 | std::istringstream i_stream(s); 12 | std::string tmp; 13 | 14 | while (i_stream >> tmp) 15 | { 16 | str.push_back(tmp); 17 | } 18 | return str; 19 | } 20 | //------------------------------------------------------------------------------------------------- 21 | int main() 22 | { 23 | std::string s = "C Cpp Java Python"; 24 | 25 | std::vector words = SplitIntoWords(s); 26 | std::cout << words.size() << " "; 27 | 28 | for (auto it = begin(words); it != end(words); ++it) 29 | { 30 | if (it != begin(words)) 31 | { 32 | std::cout << "/"; 33 | } 34 | std::cout << *it; 35 | } 36 | std::cout << std::endl; 37 | 38 | return 0; 39 | } 40 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/04 Practice Programming Assignment/Example.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_4/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_4/04 Practice Programming Assignment/Solution/remove_duplicates.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //------------------------------------------------------------------------------------------------- 7 | template 8 | void RemoveDuplicates(std::vector& elements) 9 | { 10 | std::sort(elements.begin(), elements.end()); 11 | auto last_iter = std::unique(elements.begin(), elements.end()); 12 | elements.erase(last_iter, elements.end()); 13 | } 14 | //------------------------------------------------------------------------------------------------- 15 | int main() 16 | { 17 | std::vector v1 = { 6, 4, 7, 6, 4, 4, 0, 1 }; 18 | RemoveDuplicates(v1); 19 | for (int x : v1) 20 | { 21 | std::cout << x << " "; 22 | } 23 | std::cout << std::endl; 24 | 25 | std::vector v2 = { "C", "C++", "C++", "C", "C++" }; 26 | RemoveDuplicates(v2); 27 | for (const std::string& s : v2) 28 | { 29 | std::cout << s << " "; 30 | } 31 | std::cout << std::endl; 32 | return 0; 33 | } 34 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/05 Programming Assignment/Example/Example.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 | } -------------------------------------------------------------------------------- /Week_4/05 Programming Assignment/Example/README.md: -------------------------------------------------------------------------------- 1 | Основная идея — использовать алгоритм *prev_permutation* для итеративного построения предыдущей перестановки по заданной. Его удобно обернуть в цикл *do while*. 2 | 3 | Кроме того, для инициализации первой перестановки используем алгоритмы *iota* (заполняющий диапазон числами от *1* до *n*) и reverse. -------------------------------------------------------------------------------- /Week_4/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_4/05 Programming Assignment/Solution/print_permutations.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | //------------------------------------------------------------------------------------------------- 8 | int main() 9 | { 10 | size_t size; 11 | std::cin >> size; 12 | std::vector permutation(size); 13 | 14 | std::iota(permutation.begin(), permutation.end(), 1); 15 | std::reverse(permutation.begin(), permutation.end()); 16 | 17 | do 18 | { 19 | std::copy(permutation.begin(), permutation.end(), std::ostream_iterator(std::cout, " ")); 20 | std::cout << std::endl; 21 | } 22 | while (std::prev_permutation(permutation.begin(), permutation.end())); 23 | return 0; 24 | } 25 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/06 Practice Programming Assignment/Example.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 | } -------------------------------------------------------------------------------- /Week_4/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 | void PrintStats(vector persons); 66 | int main() { 67 | vector persons = { 68 | {31, Gender::MALE, false}, 69 | {40, Gender::FEMALE, true}, 70 | {24, Gender::MALE, true}, 71 | {20, Gender::FEMALE, true}, 72 | {80, Gender::FEMALE, false}, 73 | {78, Gender::MALE, false}, 74 | {10, Gender::FEMALE, false}, 75 | {55, Gender::MALE, true}, 76 | }; 77 | PrintStats(persons); 78 | return 0; 79 | } 80 | ``` 81 | ###### Вывод ###### 82 | ```commandline 83 | Median age = 40 84 | Median age for females = 40 85 | Median age for males = 55 86 | Median age for employed females = 40 87 | Median age for unemployed females = 80 88 | Median age for employed males = 55 89 | Median age for unemployed males = 78 90 | ``` 91 | 92 | ##### Пояснение ##### 93 | В этой задаче вам надо прислать на проверку файл с реализацией функции *PrintStats*. **Этот файл не должен содержать определения функции ComputeMedianAge и типов Person и Gender**. В противном случае вы получите ошибку компиляции. 94 | 95 | Гарантируется, что типы *Person* и *Gender* объявлены в точности так же, как в коде выше. -------------------------------------------------------------------------------- /Week_4/07 Programming Assignment/Example/Example_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 | } -------------------------------------------------------------------------------- /Week_4/07 Programming Assignment/Example/Example_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 | } -------------------------------------------------------------------------------- /Week_4/07 Programming Assignment/Example/README.md: -------------------------------------------------------------------------------- 1 | В этой задаче достаточно аккуратно реализовать предложенный алгоритм, не ошибившись при использовании итераторов. -------------------------------------------------------------------------------- /Week_4/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_4/07 Programming Assignment/Solution/merge_sort_div2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //------------------------------------------------------------------------------------------------- 7 | template 8 | void MergeSort(RandomIt range_begin, RandomIt range_end) 9 | { 10 | if (std::distance(range_begin, range_end) < 2) 11 | { 12 | return; 13 | } 14 | else 15 | { 16 | std::vector elements(range_begin, range_end); 17 | 18 | auto itr_part_1 = elements.begin() + elements.size() / 2; 19 | 20 | MergeSort(elements.begin(), itr_part_1); 21 | MergeSort(itr_part_1, elements.end()); 22 | 23 | std::merge(elements.begin(), itr_part_1, itr_part_1, elements.end(), range_begin); 24 | } 25 | } 26 | //------------------------------------------------------------------------------------------------- 27 | int main() 28 | { 29 | std::vector v = { 6, 4, 7, 6, 4, 4, 0, 1, 5}; 30 | MergeSort(begin(v), end(v)); 31 | for (int x : v) 32 | { 33 | std::cout << x << " "; 34 | } 35 | std::cout << std::endl; 36 | 37 | return 0; 38 | } 39 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/07 Programming Assignment/Solution/merge_sort_div3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //------------------------------------------------------------------------------------------------- 7 | template 8 | void MergeSort(RandomIt range_begin, RandomIt range_end) 9 | { 10 | if (std::distance(range_begin, range_end) < 2) 11 | { 12 | return; 13 | } 14 | else 15 | { 16 | std::vector elements(range_begin, range_end); 17 | 18 | auto itr_part_1 = elements.begin() + elements.size() / 3; 19 | auto itr_part_2 = itr_part_1 + elements.size() / 3; 20 | 21 | MergeSort(elements.begin(), itr_part_1); 22 | MergeSort(itr_part_1, itr_part_2); 23 | MergeSort(itr_part_2, elements.end()); 24 | 25 | std::vector temp; 26 | 27 | std::merge(elements.begin(), itr_part_1, itr_part_1, itr_part_2, std::back_inserter(temp)); 28 | std::merge(temp.begin(), temp.end(), itr_part_2, elements.end(), range_begin); 29 | } 30 | } 31 | //------------------------------------------------------------------------------------------------- 32 | int main() 33 | { 34 | std::vector v = { 6, 4, 7, 6, 4, 4, 0, 1, 5}; 35 | MergeSort(begin(v), end(v)); 36 | for (int x : v) 37 | { 38 | std::cout << x << " "; 39 | } 40 | std::cout << std::endl; 41 | 42 | return 0; 43 | } 44 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/08 Practice Programming Assignment/Example.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 | } -------------------------------------------------------------------------------- /Week_4/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_4/08 Practice Programming Assignment/Solution/find_nearest_element.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //------------------------------------------------------------------------------------------------- 6 | std::set::const_iterator FindNearestElement(const std::set& numbers, int border) 7 | { 8 | auto nearest = numbers.lower_bound(border); 9 | 10 | if (nearest != std::begin(numbers)) 11 | { 12 | if (nearest == std::end(numbers)) 13 | { 14 | return std::prev(nearest); 15 | } 16 | else 17 | if (abs(*nearest - border) >= abs(border - *std::prev(nearest))) 18 | { 19 | return std::prev(nearest); 20 | } 21 | else 22 | { 23 | return nearest; 24 | } 25 | } 26 | return nearest; 27 | } 28 | //------------------------------------------------------------------------------------------------- 29 | int main() 30 | { 31 | std::set numbers = { 1, 4, 6 }; 32 | std::cout << 33 | *FindNearestElement(numbers, 0) << " " << 34 | *FindNearestElement(numbers, 3) << " " << 35 | *FindNearestElement(numbers, 5) << " " << 36 | *FindNearestElement(numbers, 6) << " " << 37 | *FindNearestElement(numbers, 100) 38 | << std::endl; 39 | 40 | std::set empty_set; 41 | 42 | std::cout << (FindNearestElement(empty_set, 8) == end(empty_set)) << std::endl; 43 | 44 | return 0; 45 | } 46 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/09 Practice Programming Assignment/Example.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 | }; -------------------------------------------------------------------------------- /Week_4/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_4/09 Practice Programming Assignment/Solution/person_names.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //------------------------------------------------------------------------------------------------- 6 | class Person 7 | { 8 | public: 9 | void ChangeFirstName(int year, const std::string & first_name) 10 | { 11 | // добавить факт изменения имени на first_name в год year 12 | first_names[year] = first_name; 13 | } 14 | 15 | void ChangeLastName(int year, const std::string & last_name) 16 | { 17 | // добавить факт изменения фамилии на last_name в год year 18 | last_names[year] = last_name; 19 | } 20 | 21 | std::string GetFullName(int year) 22 | { 23 | // получить имя и фамилию по состоянию на конец года year 24 | const std::string first_name = find_name(first_names,year); 25 | const std::string last_name = find_name(last_names, year); 26 | 27 | if (first_name.empty() && last_name.empty()) 28 | { 29 | return "Incognito"; 30 | } 31 | else 32 | if (first_name.empty()) 33 | { 34 | 35 | return last_name + " with unknown first name"; 36 | } 37 | else 38 | if (last_name.empty()) 39 | { 40 | 41 | return first_name + " with unknown last name"; 42 | } 43 | return first_name + " " + last_name; 44 | } 45 | private: 46 | std::string find_name(std::map& names, int year) 47 | { 48 | auto itr_name = names.upper_bound(year); 49 | 50 | if (itr_name != names.begin()) 51 | { 52 | return std::prev(itr_name)->second; 53 | } 54 | return std::string(""); 55 | } 56 | std::map first_names; 57 | std::map last_names; 58 | }; 59 | //------------------------------------------------------------------------------------------------- 60 | int main() 61 | { 62 | Person person; 63 | 64 | person.ChangeFirstName(1965, "Polina"); 65 | person.ChangeLastName(1967, "Sergeeva"); 66 | for (int year : {1900, 1965, 1990}) 67 | { 68 | std::cout << person.GetFullName(year) << std::endl; 69 | } 70 | 71 | person.ChangeFirstName(1970, "Appolinaria"); 72 | for (int year : {1969, 1970}) 73 | { 74 | std::cout << person.GetFullName(year) << std::endl; 75 | } 76 | 77 | person.ChangeLastName(1968, "Volkova"); 78 | for (int year : {1969, 1970}) 79 | { 80 | std::cout << person.GetFullName(year) << std::endl; 81 | } 82 | return 0; 83 | } 84 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/10 Programming Assignment/Example/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 | } -------------------------------------------------------------------------------- /Week_4/10 Programming Assignment/Example/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 | } -------------------------------------------------------------------------------- /Week_4/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_4/10 Programming Assignment/Solution/find_starts_with_char.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //------------------------------------------------------------------------------------------------- 7 | template 8 | std::pair FindStartsWith(RandomIt range_begin, RandomIt range_end, char prefix) 9 | { 10 | auto itr = std::equal_range(range_begin, range_end, std::string(1, prefix), 11 | [](const std::string& x, const std::string& y) 12 | { 13 | return x[0] < y[0]; 14 | }); 15 | return std::make_pair(itr.first, itr.second); 16 | } 17 | //-------------------------------------------------------------------------------------------------- 18 | int main() 19 | { 20 | const std::vector sorted_strings = { "moscow", "murmansk", "vologda" }; 21 | 22 | const auto m_result = FindStartsWith(std::begin(sorted_strings), std::end(sorted_strings), 'm'); 23 | 24 | for (auto it = m_result.first; it != m_result.second; ++it) 25 | { 26 | std::cout << *it << " "; 27 | } 28 | std::cout << std::endl; 29 | 30 | const auto p_result = FindStartsWith(std::begin(sorted_strings), std::end(sorted_strings), 'p'); 31 | std::cout << (p_result.first - std::begin(sorted_strings)) << " " 32 | << (p_result.second - std::begin(sorted_strings)) << std::endl; 33 | 34 | const auto z_result = FindStartsWith(std::begin(sorted_strings), std::end(sorted_strings), 'z'); 35 | std::cout << (z_result.first - std::begin(sorted_strings)) << " " 36 | << (z_result.second - begin(sorted_strings)) << std::endl; 37 | 38 | return 0; 39 | } 40 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/10 Programming Assignment/Solution/find_starts_with_string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //------------------------------------------------------------------------------------------------- 7 | template 8 | std::pair FindStartsWith(RandomIt range_begin, RandomIt range_end, const std::string& prefix) 9 | { 10 | auto itr = std::equal_range(range_begin, range_end, prefix, 11 | [&prefix](const std::string& x, const std::string& y) 12 | { 13 | return x.compare(0, prefix.length(), y.substr(0, prefix.length())) < 0;; 14 | }); 15 | return std::make_pair(itr.first, itr.second); 16 | } 17 | //-------------------------------------------------------------------------------------------------- 18 | int main() 19 | { 20 | const std::vector sorted_strings = { "moscow", "motovilikha", "murmansk" }; 21 | 22 | const auto mo_result = FindStartsWith(begin(sorted_strings), end(sorted_strings), "mo"); 23 | 24 | for (auto it = mo_result.first; it != mo_result.second; ++it) 25 | { 26 | std::cout << *it << " "; 27 | } 28 | std::cout << std::endl; 29 | 30 | const auto mt_result = FindStartsWith(begin(sorted_strings), end(sorted_strings), "mt"); 31 | std::cout << (mt_result.first - begin(sorted_strings)) << " " 32 | << (mt_result.second - begin(sorted_strings)) << std::endl; 33 | 34 | const auto na_result = FindStartsWith(begin(sorted_strings), end(sorted_strings), "na"); 35 | std::cout << (na_result.first - begin(sorted_strings)) << " " 36 | <<(na_result.second - begin(sorted_strings)) << std::endl; 37 | 38 | return 0; 39 | } 40 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/11 Programming Assignment/Example/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 | } -------------------------------------------------------------------------------- /Week_4/11 Programming Assignment/Example/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 | } -------------------------------------------------------------------------------- /Week_4/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_4/11 Programming Assignment/Solution/build_expression.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //-------------------------------------------------------------------------------------------------- 6 | int main() 7 | { 8 | int number = 0; 9 | std::cin >> number; 10 | 11 | size_t size = 0; 12 | std::cin >> size; 13 | 14 | std::deque expr(size); 15 | expr.push_back(std::to_string(number)); 16 | 17 | for (size_t i = 0; i < size; i++) 18 | { 19 | char operation = 0; 20 | std::cin >> operation; 21 | 22 | int value = 0; 23 | std::cin >> value; 24 | 25 | expr.push_front("("); 26 | expr.push_back(") "); 27 | expr.push_back(std::string(1, operation)); 28 | expr.push_back(" "); 29 | expr.push_back(std::to_string(value)); 30 | } 31 | 32 | for (auto& item : expr) 33 | { 34 | std::cout << item; 35 | } 36 | return 0; 37 | } 38 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/11 Programming Assignment/Solution/build_expression_without_redundant.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //-------------------------------------------------------------------------------------------------- 6 | int main() 7 | { 8 | int number = 0; 9 | std::cin >> number; 10 | 11 | size_t size = 0; 12 | std::cin >> size; 13 | 14 | std::deque expr(size); 15 | expr.push_back(std::to_string(number)); 16 | 17 | char last_op = 0; 18 | for (size_t i = 0; i < size; i++) 19 | { 20 | char operation = 0; 21 | std::cin >> operation; 22 | 23 | int value = 0; 24 | std::cin >> value; 25 | 26 | if ((last_op == '+' || last_op == '-') && (operation == '*' || operation == '/')) 27 | { 28 | expr.push_front("("); 29 | expr.push_back(")"); 30 | } 31 | expr.push_back(" "); 32 | expr.push_back(std::string(1, operation)); 33 | expr.push_back(" "); 34 | expr.push_back(std::to_string(value)); 35 | last_op = operation; 36 | } 37 | 38 | for (auto& item : expr) 39 | { 40 | std::cout << item; 41 | } 42 | return 0; 43 | } 44 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_4/week4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_4/week4.pdf -------------------------------------------------------------------------------- /Week_5/01 Programming Assignment/Example/Example.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 | }; -------------------------------------------------------------------------------- /Week_5/01 Programming Assignment/README.md: -------------------------------------------------------------------------------- 1 | #### Задание по программированию: Наследование своими руками #### 2 | 3 | 4 | Дан следующий код: 5 | ```objectivec 6 | #include 7 | using namespace std; 8 | class Animal { 9 | public: 10 | // ваш код 11 | const string Name; 12 | }; 13 | class Dog { 14 | public: 15 | // ваш код 16 | void Bark() { 17 | cout << Name << " barks: woof!" << endl; 18 | } 19 | }; 20 | ``` 21 | Определите до конца тела классов, соблюдая следующие требования: 22 | 23 | 1. Класс *Dog* должен являться наследником класса *Animal*. 24 | 2. Конструктор класса *Dog* должен принимать параметр типа *string* и инициализировать им поле *Name* в классе *Animal*. -------------------------------------------------------------------------------- /Week_5/01 Programming Assignment/Solution/inheritance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //-------------------------------------------------------------------------------------------------- 5 | class Animal 6 | { 7 | public: 8 | Animal(const std::string& str = "animal") : Name(str) 9 | { 10 | 11 | } 12 | public: 13 | const std::string Name; 14 | }; 15 | //-------------------------------------------------------------------------------------------------- 16 | class Dog : public Animal 17 | { 18 | public: 19 | Dog(const std::string& str = "dog") : Animal(str) 20 | { 21 | 22 | } 23 | void Bark() 24 | { 25 | std::cout << Name << " barks: woof!" << std::endl; 26 | } 27 | }; 28 | //-------------------------------------------------------------------------------------------------- 29 | int main() 30 | { 31 | Dog dg; 32 | dg.Bark(); 33 | return 0; 34 | } 35 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_5/02 Practice Programming Assignment/Example.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 | } -------------------------------------------------------------------------------- /Week_5/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 | using namespace std; 30 | void SendSms(const string& number, const string& message) { 31 | cout << "Send '" << message << "' to number " << number << endl; 32 | } 33 | void SendEmail(const string& email, const string& message) { 34 | cout << "Send '" << message << "' to e-mail " << email << endl; 35 | } 36 | /* 37 | Реализуйте здесь классы INotifier, SmsNotifier, EmailNotifier 38 | */ 39 | void Notify(INotifier& notifier, const string& message) { 40 | notifier.Notify(message); 41 | } 42 | int main() { 43 | SmsNotifier sms{"+7-495-777-77-77"}; 44 | EmailNotifier email{"na-derevnyu@dedushke.ru"}; 45 | Notify(sms, "I have White belt in C++"); 46 | Notify(email, "And want a Yellow one"); 47 | return 0; 48 | } 49 | ``` 50 | Когда вы реализуете нужные классы, программа выше должна вывести: 51 | ```commandline 52 | Send 'I have White belt in C++' to number +7-495-777-77-77 53 | Send 'And want a Yellow one' to e-mail na-derevnyu@dedushke.ru 54 | ``` 55 | 56 | Уточним ещё раз, что файл, отправляемый на проверку, должен содержать реализации классов INotifier, SmsNotifier, EmailNotifier. -------------------------------------------------------------------------------- /Week_5/02 Practice Programming Assignment/Solution/notifiers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //-------------------------------------------------------------------------------------------------- 5 | void SendSms(const std::string& number, const std::string& message) 6 | { 7 | std::cout << "Send '" << message << "' to number " << number << std::endl; 8 | } 9 | //-------------------------------------------------------------------------------------------------- 10 | void SendEmail(const std::string& email, const std::string& message) 11 | { 12 | std::cout << "Send '" << message << "' to e-mail " << email << std::endl; 13 | } 14 | //-------------------------------------------------------------------------------------------------- 15 | class INotifier 16 | { 17 | public: 18 | virtual void Notify(const std::string& message) const = 0; 19 | }; 20 | //-------------------------------------------------------------------------------------------------- 21 | class SmsNotifier : public INotifier 22 | { 23 | private: 24 | const std::string number; 25 | public: 26 | SmsNotifier(const std::string& num = "+8-800-555-35-35") : number(num) 27 | { 28 | 29 | } 30 | 31 | void Notify(const std::string& message) const override 32 | { 33 | SendSms(number, message); 34 | } 35 | }; 36 | //-------------------------------------------------------------------------------------------------- 37 | class EmailNotifier : public INotifier 38 | { 39 | private: 40 | const std::string e_mail; 41 | public: 42 | EmailNotifier(const std::string& mail = "yandex@yandex.ru") : e_mail(mail) 43 | { 44 | 45 | } 46 | 47 | void Notify(const std::string& message) const override 48 | { 49 | SendEmail(e_mail, message); 50 | } 51 | }; 52 | //-------------------------------------------------------------------------------------------------- 53 | void Notify(INotifier& notifier, const std::string& message) 54 | { 55 | notifier.Notify(message); 56 | } 57 | //-------------------------------------------------------------------------------------------------- 58 | //int main() 59 | //{ 60 | // SmsNotifier sms{ "+7-495-777-77-77" }; 61 | // EmailNotifier email{ "na-derevnyu@dedushke.ru" }; 62 | // 63 | // Notify(sms, "I have White belt in C++"); 64 | // Notify(email, "And want a Yellow one"); 65 | // return 0; 66 | //} 67 | //------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_5/03 Programming Assignment/Example/Example.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 | } -------------------------------------------------------------------------------- /Week_5/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 | string command; 11 | is >> command; 12 | if (command == "ADD") { 13 | figures.push_back(CreateFigure(is)); 14 | } else if (command == "PRINT") { 15 | for (const auto& current_figure : figures) { 16 | cout << fixed << setprecision(3) 17 | << current_figure->Name() << " " 18 | << current_figure->Perimeter() << " " 19 | << current_figure->Area() << endl; 20 | } 21 | } 22 | } 23 | return 0; 24 | } 25 | ``` 26 | Как видно из кода, есть два вида команд: 27 | * **ADD** — добавить фигуру в набор; 28 | * **PRINT** — для каждой фигуры в наборе распечатать название, периметр и площадь. 29 | 30 | Программа поддерживает три вида фигур: прямоугольник, треугольник и круг. Их добавление описывается так: 31 | 1. **ADD RECT *width* *height*** — добавить прямоугольник с размерами ***width*** и ***height*** (например, **ADD RECT *2* *3***). 32 | 2. **ADD TRIANGLE *a* *b* *c*** — добавить треугольник со сторонами ***a***, ***b*** и ***c*** (например, **ADD TRIANGLE *3* *4* *5***). 33 | 3. **ADD CIRCLE *r*** — добавить круг радиуса ***r*** (например, **ADD CIRCLE *5***). 34 | 35 | ##### Пример работы программы ##### 36 | ###### Ввод ###### 37 | ```commandline 38 | ADD RECT 2 3 39 | ADD TRIANGLE 3 4 5 40 | ADD RECT 10 20 41 | ADD CIRCLE 5 42 | PRINT 43 | ``` 44 | ###### Вывод ###### 45 | ```commandline 46 | RECT 10.000 6.000 47 | TRIANGLE 12.000 6.000 48 | RECT 60.000 200.000 49 | CIRCLE 31.400 78.500 50 | ``` 51 | 52 | **Не меняя функцию main**, реализуйте недостающие функции и классы: 53 | * базовый класс *Figure* с чисто виртуальными методами *Name*, *Perimeter* и *Area*; 54 | * классы *Triangle*, *Rect* и *Circle*, которые являются наследниками класса *Figure* и переопределяют его виртуальные методы; 55 | * функцию *CreateFigure*, которая в зависимости от содержимого входного потока создаёт *shared_ptr\*, *shared_ptr\* или *shared_ptr\*. 56 | 57 | Гарантируется, что все команды *ADD* корректны; размеры всех фигур — это натуральные числа не больше *1000*. В качестве значения π используйте *3,14*. 58 | 59 | ##### Как будет тестироваться ваш код ##### 60 | Автоматическая проверяющая система заменит в вашей программе функцию *main* на ту, которая приведена в условии задачи, скомпилирует получившийся файл и прогонит на наборе тестов. Кроме того, отдельно проверяется, что функция *CreateFigure* возвращает объект, созданный с помощью *make_shared\*, если во входном потоке задан прямоугольник, объект, созданный с помощью *make_shared\*, если во входном потоке задан круг, и т. д. -------------------------------------------------------------------------------- /Week_5/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_5/04-Peer-graded-Assignment/Source/refactoring.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | 8 | class Student { 9 | public: 10 | 11 | Student(string name, string favouriteSong) { 12 | Name = name; 13 | FavouriteSong = favouriteSong; 14 | } 15 | 16 | void Learn() { 17 | cout << "Student: " << Name << " learns" << endl; 18 | } 19 | 20 | void Walk(string destination) { 21 | cout << "Student: " << Name << " walks to: " << destination << endl; 22 | cout << "Student: " << Name << " sings a song: " << FavouriteSong << endl; 23 | } 24 | 25 | void SingSong() { 26 | cout << "Student: " << Name << " sings a song: " << FavouriteSong << endl; 27 | } 28 | 29 | public: 30 | string Name; 31 | string FavouriteSong; 32 | }; 33 | 34 | 35 | class Teacher { 36 | public: 37 | 38 | Teacher(string name, string subject) { 39 | Name = name; 40 | Subject = subject; 41 | } 42 | 43 | void Teach() { 44 | cout << "Teacher: " << Name << " teaches: " << Subject << endl; 45 | } 46 | 47 | void Walk(string destination) { 48 | cout << "Teacher: " << Name << " walks to: " << destination << endl; 49 | } 50 | 51 | public: 52 | string Name; 53 | string Subject; 54 | }; 55 | 56 | 57 | class Policeman { 58 | public: 59 | Policeman(string name) { 60 | Name = name; 61 | } 62 | 63 | void Check(Teacher t) { 64 | cout << "Policeman: " << Name << " checks Teacher. Teacher's name is: " << t.Name << endl; 65 | } 66 | 67 | void Check(Student s) { 68 | cout << "Policeman: " << Name << " checks Student. Student's name is: " << s.Name << endl; 69 | } 70 | 71 | void Check(Policeman p) { 72 | cout << "Policeman: " << Name << " checks Policeman. Policeman's name is: " << p.Name << endl; 73 | } 74 | 75 | void Walk(string destination) { 76 | cout << "Policeman: " << Name << " walks to: " << destination << endl; 77 | } 78 | 79 | public: 80 | string Name; 81 | }; 82 | 83 | 84 | void VisitPlaces(Teacher t, vector places) { 85 | for (auto p : places) { 86 | t.Walk(p); 87 | } 88 | } 89 | 90 | void VisitPlaces(Student s, vector places) { 91 | for (auto p : places) { 92 | s.Walk(p); 93 | } 94 | } 95 | 96 | void VisitPlaces(Policeman pol, vector places) { 97 | for (auto p : places) { 98 | pol.Walk(p); 99 | } 100 | } 101 | 102 | 103 | int main() { 104 | Teacher t("Jim", "Math"); 105 | Student s("Ann", "We will rock you"); 106 | Policeman p("Bob"); 107 | 108 | VisitPlaces(t, {"Moscow", "London"}); 109 | p.Check(s); 110 | VisitPlaces(s, {"Moscow", "London"}); 111 | return 0; 112 | } -------------------------------------------------------------------------------- /Week_5/week5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_5/week5.pdf -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/condition_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "condition_parser.h" 2 | #include "token.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | template shared_ptr ParseComparison(It& current, It end) { 8 | if (current == end) { 9 | throw logic_error("Expected column name: date or event"); 10 | } 11 | 12 | Token& column = *current; 13 | if (column.type != TokenType::COLUMN) { 14 | throw logic_error("Expected column name: date or event"); 15 | } 16 | ++current; 17 | 18 | if (current == end) { 19 | throw logic_error("Expected comparison operation"); 20 | } 21 | 22 | Token& op = *current; 23 | if (op.type != TokenType::COMPARE_OP) { 24 | throw logic_error("Expected comparison operation"); 25 | } 26 | ++current; 27 | 28 | if (current == end) { 29 | throw logic_error("Expected right value of comparison"); 30 | } 31 | 32 | Comparison cmp; 33 | if (op.value == "<") { 34 | cmp = Comparison::Less; 35 | } else if (op.value == "<=") { 36 | cmp = Comparison::LessOrEqual; 37 | } else if (op.value == ">") { 38 | cmp = Comparison::Greater; 39 | } else if (op.value == ">=") { 40 | cmp = Comparison::GreaterOrEqual; 41 | } else if (op.value == "==") { 42 | cmp = Comparison::Equal; 43 | } else if (op.value == "!=") { 44 | cmp = Comparison::NotEqual; 45 | } else { 46 | throw logic_error("Unknown comparison token: " + op.value); 47 | } 48 | 49 | const string& value = current->value; 50 | ++current; 51 | 52 | if (column.value == "date") { 53 | istringstream is(value); 54 | return make_shared(cmp, ParseDate(is)); 55 | } else { 56 | return make_shared(cmp, value); 57 | } 58 | } 59 | 60 | template 61 | shared_ptr ParseExpression(It& current, It end, unsigned precedence) { 62 | if (current == end) { 63 | return shared_ptr(); 64 | } 65 | 66 | shared_ptr left; 67 | 68 | if (current->type == TokenType::PAREN_LEFT) { 69 | ++current; // consume '(' 70 | left = ParseExpression(current, end, 0u); 71 | if (current == end || current->type != TokenType::PAREN_RIGHT) { 72 | throw logic_error("Missing right paren"); 73 | } 74 | ++current; // consume ')' 75 | } else { 76 | left = ParseComparison(current, end); 77 | } 78 | 79 | const map precedences = { 80 | {LogicalOperation::Or, 1}, {LogicalOperation::And, 2} 81 | }; 82 | 83 | while (current != end && current->type != TokenType::PAREN_RIGHT) { 84 | if (current->type != TokenType::LOGICAL_OP) { 85 | throw logic_error("Expected logic operation"); 86 | } 87 | 88 | const auto logical_operation = current->value == "AND" ? LogicalOperation::And 89 | : LogicalOperation::Or; 90 | const auto current_precedence = precedences.at(logical_operation); 91 | if (current_precedence <= precedence) { 92 | break; 93 | } 94 | 95 | ++current; // consume op 96 | 97 | left = make_shared( 98 | logical_operation, left, ParseExpression(current, end, current_precedence) 99 | ); 100 | } 101 | 102 | return left; 103 | } 104 | 105 | shared_ptr ParseCondition(istream& is) { 106 | auto tokens = Tokenize(is); 107 | auto current = tokens.begin(); 108 | auto top_node = ParseExpression(current, tokens.end(), 0u); 109 | 110 | if (!top_node) { 111 | top_node = make_shared(); 112 | } 113 | 114 | if (current != tokens.end()) { 115 | throw logic_error("Unexpected tokens after condition"); 116 | } 117 | 118 | return top_node; 119 | } 120 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/condition_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "node.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | shared_ptr ParseCondition(istream& is); 11 | 12 | void TestParseCondition(); 13 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/course_project_yellow.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_6/01 Programming Assignment/Example/course_project_yellow.zip -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/database.cpp: -------------------------------------------------------------------------------- 1 | #include "database.h" 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | void Database::Add(const Date& date, const string& event) { 8 | data_[date].Add(event); 9 | } 10 | 11 | void Database::Print(ostream& os) const { 12 | for (const auto& kv : data_) { 13 | for (const auto& event : kv.second.GetAll()) { 14 | os << kv.first << ' ' << event << endl; 15 | } 16 | } 17 | } 18 | 19 | Entry Database::Last(const Date& date) const { 20 | auto it = data_.upper_bound(date); 21 | if (it == data_.begin()) { 22 | throw invalid_argument(""); 23 | } 24 | --it; 25 | return {it->first, it->second.GetAll().back()}; 26 | } 27 | 28 | ostream& operator << (ostream& os, const Entry& e) { 29 | return os << e.date << " " << e.event; 30 | } 31 | 32 | bool operator == (const Entry& lhs, const Entry& rhs) { 33 | return tie(lhs.date, lhs.event) == tie(rhs.date, rhs.event); 34 | } 35 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/database.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "date.h" 4 | #include "event_set.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | struct Entry { 13 | Date date; 14 | string event; 15 | }; 16 | 17 | ostream& operator << (ostream& os, const Entry& e); 18 | bool operator == (const Entry& lhs, const Entry& rhs); 19 | 20 | class Database { 21 | public: 22 | void Add(const Date& date, const string& event); 23 | 24 | template 25 | int RemoveIf(Predicate predicate) { 26 | int result = 0; 27 | for (auto& kv : data_) { 28 | const Date& date = kv.first; 29 | result += kv.second.RemoveIf([=](const string& event) { 30 | return predicate(date, event); 31 | }); 32 | } 33 | for (auto it = data_.begin(); it != data_.end(); ) { 34 | if (it->second.GetAll().empty()) { 35 | data_.erase(it++); 36 | } else { 37 | ++it; 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | template 44 | vector FindIf(Predicate predicate) const { 45 | vector result; 46 | for (auto& kv : data_) { 47 | for (const auto& event : kv.second.GetAll()) { 48 | if (predicate(kv.first, event)) { 49 | result.push_back(Entry{kv.first, event}); 50 | } 51 | } 52 | } 53 | return result; 54 | } 55 | 56 | void Print(ostream& os) const; 57 | 58 | // throws invalid_argument if there is no last event for the given date 59 | Entry Last(const Date& date) const; 60 | 61 | private: 62 | map data_; 63 | }; 64 | 65 | // Tests 66 | void TestDatabaseAddAndPrint(); 67 | void TestDatabaseFind(); 68 | void TestDatabaseRemove(); 69 | void TestDatabaseLast(); 70 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/date.cpp: -------------------------------------------------------------------------------- 1 | #include "date.h" 2 | 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | Date ParseDate(istream& is) { 8 | Date result; 9 | is >> result.year; 10 | is.ignore(1); 11 | is >> result.month; 12 | is.ignore(1); 13 | is >> result.day; 14 | return result; 15 | } 16 | 17 | ostream& operator << (ostream& os, const Date& date) { 18 | os << setw(4) << setfill('0') << date.year << '-' 19 | << setw(2) << setfill('0') << date.month << '-' 20 | << setw(2) << setfill('0') << date.day; 21 | return os; 22 | } 23 | 24 | bool operator == (const Date& lhs, const Date& rhs) { 25 | return tie(lhs.year, lhs.month, lhs.day) == tie(rhs.year, rhs.month, rhs.day); 26 | } 27 | 28 | bool operator != (const Date& lhs, const Date& rhs) { 29 | return tie(lhs.year, lhs.month, lhs.day) != tie(rhs.year, rhs.month, rhs.day); 30 | } 31 | 32 | bool operator < (const Date& lhs, const Date& rhs) { 33 | return tie(lhs.year, lhs.month, lhs.day) < tie(rhs.year, rhs.month, rhs.day); 34 | } 35 | 36 | bool operator <= (const Date& lhs, const Date& rhs) { 37 | return tie(lhs.year, lhs.month, lhs.day) <= tie(rhs.year, rhs.month, rhs.day); 38 | } 39 | 40 | bool operator > (const Date& lhs, const Date& rhs) { 41 | return tie(lhs.year, lhs.month, lhs.day) > tie(rhs.year, rhs.month, rhs.day); 42 | } 43 | 44 | bool operator >= (const Date& lhs, const Date& rhs) { 45 | return tie(lhs.year, lhs.month, lhs.day) >= tie(rhs.year, rhs.month, rhs.day); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/date.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct Date { 8 | int year, month, day; 9 | }; 10 | 11 | ostream& operator << (ostream& os, const Date& date); 12 | bool operator == (const Date& lhs, const Date& rhs); 13 | bool operator != (const Date& lhs, const Date& rhs); 14 | bool operator < (const Date& lhs, const Date& rhs); 15 | bool operator <= (const Date& lhs, const Date& rhs); 16 | bool operator > (const Date& lhs, const Date& rhs); 17 | bool operator >= (const Date& lhs, const Date& rhs); 18 | 19 | Date ParseDate(istream& is); 20 | 21 | // Tests 22 | void TestDateOutput(); 23 | void TestParseDate(); 24 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/date_test.cpp: -------------------------------------------------------------------------------- 1 | #include "date.h" 2 | #include "test_runner.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | void TestDateOutput() { 8 | { 9 | ostringstream os; 10 | os << Date{2017, 11, 15}; 11 | AssertEqual(os.str(), "2017-11-15", "Date output: simple"); 12 | } 13 | { 14 | ostringstream os; 15 | os << Date{2017, 1, 1}; 16 | AssertEqual(os.str(), "2017-01-01", "Date output: day and month less than 10"); 17 | } 18 | { 19 | ostringstream os; 20 | os << Date{2, 10, 10}; 21 | AssertEqual(os.str(), "0002-10-10", "Date output: year less than 1000"); 22 | } 23 | } 24 | 25 | void TestParseDate() { 26 | istringstream is("2017-11-15"); 27 | const Date date = ParseDate(is); 28 | 29 | AssertEqual(date.year, 2017, "Parse date: year"); 30 | AssertEqual(date.month, 11, "Parse date: month"); 31 | AssertEqual(date.day, 15, "Parse date: day"); 32 | } 33 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/event_set.cpp: -------------------------------------------------------------------------------- 1 | #include "event_set.h" 2 | 3 | void EventSet::Add(const string& event) { 4 | auto insert_result = events_.insert(event); 5 | if (insert_result.second) { 6 | event_order_.push_back(event); 7 | } 8 | } 9 | 10 | const vector& EventSet::GetAll() const { 11 | return event_order_; 12 | } 13 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/event_set.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | class EventSet { 10 | public: 11 | void Add(const string& event); 12 | 13 | const vector& GetAll() const; 14 | 15 | template 16 | int RemoveIf(Predicate predicate) { 17 | auto split_point = stable_partition(event_order_.begin(), event_order_.end(), predicate); 18 | int result = split_point - event_order_.begin(); 19 | for (auto i = event_order_.begin(); i != split_point; ++i) { 20 | events_.erase(*i); 21 | } 22 | event_order_.erase(event_order_.begin(), split_point); 23 | 24 | return result; 25 | } 26 | 27 | private: 28 | set events_; 29 | vector event_order_; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/main.cpp: -------------------------------------------------------------------------------- 1 | #include "database.h" 2 | #include "date.h" 3 | #include "condition_parser.h" 4 | #include "node.h" 5 | #include "test_runner.h" 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | string ParseEvent(istream& is) { 13 | while (isspace(is.peek())) { 14 | is.ignore(); 15 | } 16 | string event; 17 | getline(is, event); 18 | return event; 19 | } 20 | 21 | void TestAll(); 22 | 23 | int main() { 24 | TestAll(); 25 | 26 | Database db; 27 | 28 | for (string line; getline(cin, line); ) { 29 | istringstream is(line); 30 | 31 | string command; 32 | is >> command; 33 | if (command == "Add") { 34 | const auto date = ParseDate(is); 35 | const auto event = ParseEvent(is); 36 | db.Add(date, event); 37 | } else if (command == "Print") { 38 | db.Print(cout); 39 | } else if (command == "Del") { 40 | auto condition = ParseCondition(is); 41 | auto predicate = [condition](const Date& date, const string& event) { 42 | return condition->Evaluate(date, event); 43 | }; 44 | auto count = db.RemoveIf(predicate); 45 | cout << "Removed " << count << " entries" << endl; 46 | } else if (command == "Find") { 47 | auto condition = ParseCondition(is); 48 | auto predicate = [condition](const Date& date, const string& event) { 49 | return condition->Evaluate(date, event); 50 | }; 51 | 52 | const auto entries = db.FindIf(predicate); 53 | for (const auto& entry : entries) { 54 | cout << entry << endl; 55 | } 56 | cout << "Found " << entries.size() << " entries" << endl; 57 | } else if (command == "Last") { 58 | try { 59 | cout << db.Last(ParseDate(is)) << endl; 60 | } catch (invalid_argument&) { 61 | cout << "No entries" << endl; 62 | } 63 | } else if (command.empty()) { 64 | continue; 65 | } else { 66 | throw logic_error("Unknown command: " + command); 67 | } 68 | } 69 | 70 | return 0; 71 | } 72 | 73 | void TestParseEvent() { 74 | { 75 | istringstream is("event"); 76 | AssertEqual(ParseEvent(is), "event", "Parse event without leading spaces"); 77 | } 78 | { 79 | istringstream is(" sport event "); 80 | AssertEqual(ParseEvent(is), "sport event ", "Parse event with leading spaces"); 81 | } 82 | { 83 | istringstream is(" first event \n second event"); 84 | vector events; 85 | events.push_back(ParseEvent(is)); 86 | events.push_back(ParseEvent(is)); 87 | AssertEqual(events, vector{"first event ", "second event"}, "Parse multiple events"); 88 | } 89 | } 90 | 91 | void TestAll() { 92 | TestRunner tr; 93 | tr.RunTest(TestParseEvent, "TestParseEvent"); 94 | tr.RunTest(TestDateOutput, "TestDateOutput"); 95 | tr.RunTest(TestParseDate, "TestParseDate"); 96 | tr.RunTest(TestDatabaseAddAndPrint, "TestDatabaseAddAndPrint"); 97 | tr.RunTest(TestDatabaseFind, "TestDatabaseFind"); 98 | tr.RunTest(TestDatabaseRemove, "TestDatabaseRemove"); 99 | tr.RunTest(TestDatabaseLast, "TestDatabaseLast"); 100 | tr.RunTest(TestDateComparisonNode, "TestDateComparisonNode"); 101 | tr.RunTest(TestEventComparisonNode, "TestEventComparisonNode"); 102 | tr.RunTest(TestLogicalOperationNode, "TestLogicalOperationNode"); 103 | tr.RunTest(TestParseCondition, "TestParseCondition"); 104 | } 105 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/node.cpp: -------------------------------------------------------------------------------- 1 | #include "node.h" 2 | 3 | bool EmptyNode::Evaluate(const Date& date, const string& event) const { 4 | return true; 5 | } 6 | 7 | template 8 | bool CompareTo(const T& lhs, const T& rhs, Comparison cmp) { 9 | switch (cmp) { 10 | case Comparison::Less: 11 | return lhs < rhs; 12 | case Comparison::LessOrEqual: 13 | return lhs <= rhs; 14 | case Comparison::Equal: 15 | return lhs == rhs; 16 | case Comparison::NotEqual: 17 | return lhs != rhs; 18 | case Comparison::Greater: 19 | return lhs > rhs; 20 | case Comparison::GreaterOrEqual: 21 | return lhs >= rhs; 22 | } 23 | return false; // make compiler happy 24 | } 25 | 26 | DateComparisonNode::DateComparisonNode(Comparison comparison, const Date& value) 27 | : comparison_(comparison) 28 | , value_(value) 29 | { 30 | } 31 | 32 | bool DateComparisonNode::Evaluate(const Date& date, const string&) const { 33 | return CompareTo(date, value_, comparison_); 34 | } 35 | 36 | EventComparisonNode::EventComparisonNode(Comparison comparison, const string& value) 37 | : comparison_(comparison) 38 | , value_(value) 39 | { 40 | } 41 | 42 | bool EventComparisonNode::Evaluate(const Date&, const string& event) const { 43 | return CompareTo(event, value_, comparison_); 44 | } 45 | 46 | LogicalOperationNode::LogicalOperationNode( 47 | LogicalOperation operation, shared_ptr left, shared_ptr right 48 | ) 49 | : operation_(operation) 50 | , left_(left) 51 | , right_(right) 52 | { 53 | } 54 | 55 | bool LogicalOperationNode::Evaluate(const Date& date, const string& event) const { 56 | switch (operation_) { 57 | case LogicalOperation::And: 58 | return left_->Evaluate(date, event) && right_->Evaluate(date, event); 59 | case LogicalOperation::Or: 60 | return left_->Evaluate(date, event) || right_->Evaluate(date, event); 61 | } 62 | return false; // make compiler happy 63 | } 64 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/node.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "date.h" 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | struct Node { 10 | virtual bool Evaluate(const Date& date, const string& event) const = 0; 11 | }; 12 | 13 | struct EmptyNode : public Node { 14 | bool Evaluate(const Date& date, const string& event) const override; 15 | }; 16 | 17 | enum class Comparison { 18 | Less, 19 | LessOrEqual, 20 | Equal, 21 | NotEqual, 22 | Greater, 23 | GreaterOrEqual, 24 | }; 25 | 26 | class DateComparisonNode : public Node { 27 | public: 28 | DateComparisonNode(Comparison comparison, const Date& value); 29 | bool Evaluate(const Date& date, const string& event) const override; 30 | 31 | private: 32 | Comparison comparison_; 33 | Date value_; 34 | }; 35 | 36 | class EventComparisonNode : public Node { 37 | public: 38 | EventComparisonNode(Comparison comparison, const string& value); 39 | bool Evaluate(const Date& date, const string& event) const override; 40 | 41 | private: 42 | Comparison comparison_; 43 | string value_; 44 | }; 45 | 46 | enum class LogicalOperation { 47 | And, 48 | Or, 49 | }; 50 | 51 | class LogicalOperationNode : public Node { 52 | public: 53 | LogicalOperationNode(LogicalOperation operation, shared_ptr left, shared_ptr right); 54 | bool Evaluate(const Date& date, const string& event) const override; 55 | 56 | private: 57 | LogicalOperation operation_; 58 | shared_ptr left_, right_; 59 | }; 60 | 61 | void TestDateComparisonNode(); 62 | void TestEventComparisonNode(); 63 | void TestLogicalOperationNode(); 64 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/node_test.cpp: -------------------------------------------------------------------------------- 1 | #include "node.h" 2 | #include "test_runner.h" 3 | 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | void TestDateComparisonNode() { 9 | const Date november_1{2017, 11, 1}; 10 | const Date november_2{2017, 11, 2}; 11 | const Date november_3{2017, 11, 3}; 12 | 13 | DateComparisonNode less(Comparison::Less, november_2); 14 | Assert(less.Evaluate(november_1, ""), "DateComparisonNode: less 1"); 15 | Assert(!less.Evaluate(november_3, ""), "DateComparisonNode: less 2"); 16 | 17 | DateComparisonNode not_equal(Comparison::NotEqual, november_2); 18 | Assert(not_equal.Evaluate(november_1, ""), "DateComparisonNode: not_equal 1"); 19 | Assert(!not_equal.Evaluate(november_2, ""), "DateComparisonNode: not_equal 2"); 20 | 21 | DateComparisonNode greater_eq(Comparison::GreaterOrEqual, november_2); 22 | Assert(greater_eq.Evaluate(november_2, ""), "DateComparisonNode: greater_eq 1"); 23 | Assert(greater_eq.Evaluate(november_3, ""), "DateComparisonNode: greater_eq 2"); 24 | Assert(!greater_eq.Evaluate(november_1, ""), "DateComparisonNode: greater_eq 3"); 25 | } 26 | 27 | void TestEventComparisonNode() { 28 | const Date january_1{1970, 1, 1}; 29 | 30 | EventComparisonNode less_eq(Comparison::LessOrEqual, "b"); 31 | Assert(less_eq.Evaluate(january_1, "a"), "EventComparisonNode: less_eq 1"); 32 | Assert(!less_eq.Evaluate(january_1, "c"), "EventComparisonNode: less_eq 2"); 33 | Assert(less_eq.Evaluate(january_1, "b"), "EventComparisonNode: less_eq 3"); 34 | 35 | EventComparisonNode equal(Comparison::Equal, "b"); 36 | Assert(equal.Evaluate(january_1, "b"), "EventComparisonNode: equal 1"); 37 | Assert(!equal.Evaluate(january_1, "a"), "EventComparisonNode: equal 2"); 38 | Assert(!equal.Evaluate(january_1, "c"), "EventComparisonNode: equal 3"); 39 | 40 | EventComparisonNode greater(Comparison::Greater, "b"); 41 | Assert(greater.Evaluate(january_1, "c"), "EventComparisonNode: greater 1"); 42 | Assert(!greater.Evaluate(january_1, "b"), "EventComparisonNode: greater 2"); 43 | Assert(!greater.Evaluate(january_1, "a"), "EventComparisonNode: greater 3"); 44 | } 45 | 46 | struct FalseNode : Node { 47 | bool Evaluate(const Date&, const string&) const override { 48 | return false; 49 | }; 50 | }; 51 | 52 | void TestLogicalOperationNode() { 53 | { 54 | map> bool_to_node = { 55 | {false, make_shared()}, 56 | {true, make_shared()} 57 | }; 58 | 59 | for (bool value_one : {false, true}) { 60 | for (bool value_two : {false, true}) { 61 | LogicalOperationNode or_node( 62 | LogicalOperation::Or, bool_to_node[value_one], bool_to_node[value_two] 63 | ); 64 | LogicalOperationNode and_node( 65 | LogicalOperation::And, bool_to_node[value_one], bool_to_node[value_two] 66 | ); 67 | 68 | AssertEqual(or_node.Evaluate({}, ""), value_one || value_two, "LogicalOperationNode Or"); 69 | AssertEqual(and_node.Evaluate({}, ""), value_one && value_two, "LogicalOperationNode And"); 70 | } 71 | } 72 | } 73 | { 74 | LogicalOperationNode root( 75 | LogicalOperation::And, 76 | make_shared(Comparison::Equal, Date{2017, 11, 18}), 77 | make_shared(Comparison::Equal, "Saturday") 78 | ); 79 | 80 | Assert(root.Evaluate({2017, 11, 18}, "Saturday"), "LogicalOperationNode propagates arguments 1"); 81 | Assert(!root.Evaluate({2017, 11, 18}, "Friday"), "LogicalOperationNode propagates arguments 2"); 82 | Assert(!root.Evaluate({2017, 11, 1}, "Saturday"), "LogicalOperationNode propagates arguments 1"); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/token.cpp: -------------------------------------------------------------------------------- 1 | #include "token.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector Tokenize(istream& cl) { 8 | vector tokens; 9 | 10 | char c; 11 | while (cl >> c) { 12 | if (isdigit(c)) { 13 | string date(1, c); 14 | for (int i = 0; i < 3; ++i) { 15 | while (isdigit(cl.peek())) { 16 | date += cl.get(); 17 | } 18 | if (i < 2) { 19 | date += cl.get(); // Consume '-' 20 | } 21 | } 22 | tokens.push_back({date, TokenType::DATE}); 23 | } else if (c == '"') { 24 | string event; 25 | getline(cl, event, '"'); 26 | tokens.push_back({event, TokenType::EVENT}); 27 | } else if (c == 'd') { 28 | if (cl.get() == 'a' && cl.get() == 't' && cl.get() == 'e') { 29 | tokens.push_back({"date", TokenType::COLUMN}); 30 | } else { 31 | throw logic_error("Unknown token"); 32 | } 33 | } else if (c == 'e') { 34 | if (cl.get() == 'v' && cl.get() == 'e' && cl.get() == 'n' && 35 | cl.get() == 't') { 36 | tokens.push_back({"event", TokenType::COLUMN}); 37 | } else { 38 | throw logic_error("Unknown token"); 39 | } 40 | } else if (c == 'A') { 41 | if (cl.get() == 'N' && cl.get() == 'D') { 42 | tokens.push_back({"AND", TokenType::LOGICAL_OP}); 43 | } else { 44 | throw logic_error("Unknown token"); 45 | } 46 | } else if (c == 'O') { 47 | if (cl.get() == 'R') { 48 | tokens.push_back({"OR", TokenType::LOGICAL_OP}); 49 | } else { 50 | throw logic_error("Unknown token"); 51 | } 52 | } else if (c == '(') { 53 | tokens.push_back({"(", TokenType::PAREN_LEFT}); 54 | } else if (c == ')') { 55 | tokens.push_back({")", TokenType::PAREN_RIGHT}); 56 | } else if (c == '<') { 57 | if (cl.peek() == '=') { 58 | cl.get(); 59 | tokens.push_back({"<=", TokenType::COMPARE_OP}); 60 | } else { 61 | tokens.push_back({"<", TokenType::COMPARE_OP}); 62 | } 63 | } else if (c == '>') { 64 | if (cl.peek() == '=') { 65 | cl.get(); 66 | tokens.push_back({">=", TokenType::COMPARE_OP}); 67 | } else { 68 | tokens.push_back({">", TokenType::COMPARE_OP}); 69 | } 70 | } else if (c == '=') { 71 | if (cl.get() == '=') { 72 | tokens.push_back({"==", TokenType::COMPARE_OP}); 73 | } else { 74 | throw logic_error("Unknown token"); 75 | } 76 | } else if (c == '!') { 77 | if (cl.get() == '=') { 78 | tokens.push_back({"!=", TokenType::COMPARE_OP}); 79 | } else { 80 | throw logic_error("Unknown token"); 81 | } 82 | } 83 | } 84 | 85 | return tokens; 86 | } 87 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Example/token.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | enum class TokenType { 8 | DATE, 9 | EVENT, 10 | COLUMN, 11 | LOGICAL_OP, 12 | COMPARE_OP, 13 | PAREN_LEFT, 14 | PAREN_RIGHT, 15 | }; 16 | 17 | struct Token { 18 | const string value; 19 | const TokenType type; 20 | }; 21 | 22 | vector Tokenize(istream& cl); 23 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/condition_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _CONDITION_PARSE_H_ 4 | #define _CONDITION_PARSE_H_ 5 | 6 | #include "node.h" 7 | #include "test_runner.h" 8 | 9 | #include 10 | #include 11 | 12 | //---------------------------------------------------------------------------------------------------- 13 | std::shared_ptr ParseCondition(std::istream& is); 14 | //---------------------------------------------------------------------------------------------------- 15 | void TestParseCondition(); 16 | //---------------------------------------------------------------------------------------------------- 17 | #endif // _CONDITION_PARSE_H_ -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/course_project_yellow.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_6/01 Programming Assignment/Solution/course_project_yellow.7z -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/database.cpp: -------------------------------------------------------------------------------- 1 | #include "database.h" 2 | 3 | //---------------------------------------------------------------------------------------------------- 4 | void Database::Add(const Date& date, const std::string& event) 5 | { 6 | if (db.count(date)) 7 | { 8 | const auto insert_it = db[date].first.insert(event); 9 | 10 | if (insert_it.second) 11 | { 12 | db[date].second.push_back(insert_it.first); 13 | } 14 | } 15 | else 16 | { 17 | auto insert_result = db[date].first.insert(event); 18 | db[date].second.push_back(insert_result.first); 19 | } 20 | } 21 | //---------------------------------------------------------------------------------------------------- 22 | void Database::Print(std::ostream& is) const 23 | { 24 | for (const auto& date_it : db) 25 | { 26 | for (const auto& event_it : date_it.second.second) 27 | { 28 | is << std::setw(4) << std::setfill('0') << date_it.first.GetYear() << '-'; 29 | is << std::setw(2) << std::setfill('0') << date_it.first.GetMonth() << '-'; 30 | is << std::setw(2) << std::setfill('0') << date_it.first.GetDay(); 31 | is << " " << *event_it << std::endl; 32 | } 33 | } 34 | } 35 | //---------------------------------------------------------------------------------------------------- 36 | std::string Database::Last(const Date& date) const 37 | { 38 | const auto itr_upper = db.upper_bound(date); 39 | 40 | if (itr_upper == db.begin()) 41 | { 42 | throw std::invalid_argument("No entries"); 43 | } 44 | return std::prev(itr_upper)->first.DateToStr() + " " + *std::prev(itr_upper)->second.second.back(); 45 | } 46 | //---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/database.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _DATABASE_H_ 4 | #define _DATABASE_H_ 5 | 6 | #include "date.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | //---------------------------------------------------------------------------------------------------- 15 | class Database 16 | { 17 | public: 18 | void Add(const Date& date, const std::string& event); 19 | void Print(std::ostream& is) const; 20 | std::string Last(const Date& date) const; 21 | 22 | template 23 | int RemoveIf(const Functor& func); 24 | 25 | template 26 | std::vector> FindIf(const Functor& func) const; 27 | private: 28 | std::map, std::vector::iterator>>> db; 29 | }; 30 | //---------------------------------------------------------------------------------------------------- 31 | template 32 | int Database::RemoveIf(const Functor& functor) 33 | { 34 | int count = 0; 35 | 36 | for (auto& date_it : db) 37 | { 38 | auto itr = std::stable_partition(date_it.second.second.begin(), date_it.second.second.end(), [&](const auto& event) -> bool 39 | { 40 | if (functor(date_it.first, *event)) 41 | { 42 | count++; 43 | date_it.second.first.erase(*event); 44 | return false; 45 | } 46 | return true; 47 | }); 48 | date_it.second.second.erase(itr, date_it.second.second.end()); 49 | } 50 | 51 | for (auto erase_it = db.cbegin(), next_it = erase_it; erase_it != db.cend(); erase_it = next_it) 52 | { 53 | ++next_it; 54 | if (erase_it->second.first.empty()) 55 | { 56 | db.erase(erase_it); 57 | } 58 | } 59 | return count; 60 | } 61 | //---------------------------------------------------------------------------------------------------- 62 | template 63 | std::vector> Database::FindIf(const Functor& functor) const 64 | { 65 | std::vector> temp; 66 | 67 | for (const auto& date_it : db) 68 | { 69 | auto it = std::find_if(date_it.second.second.begin(), date_it.second.second.end(), [&](const auto& event) -> bool 70 | { 71 | if (functor(date_it.first, *event)) 72 | { 73 | temp.push_back(std::make_pair(date_it.first, *event)); 74 | } 75 | return false; 76 | }); 77 | } 78 | return temp; 79 | } 80 | //---------------------------------------------------------------------------------------------------- 81 | #endif // _DATABASE_H_ -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/date.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _DATE_H_ 4 | #define _DATE_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | //---------------------------------------------------------------------------------------------------- 13 | class Date 14 | { 15 | public: 16 | Date() noexcept; 17 | Date(int new_year, int new_month, int new_day); 18 | 19 | int GetYear() const noexcept; 20 | int GetMonth() const noexcept; 21 | int GetDay() const noexcept; 22 | std::string DateToStr() const; 23 | private: 24 | int year; 25 | int month; 26 | int day; 27 | }; 28 | //---------------------------------------------------------------------------------------------------- 29 | Date ParseDate(std::istream& is); 30 | //---------------------------------------------------------------------------------------------------- 31 | std::ostream& operator << (std::ostream& os, const Date& date); 32 | std::ostream& operator << (std::ostream& os, const std::pair& pair); 33 | 34 | bool operator < (const Date& lsh, const Date& rhs) noexcept; 35 | bool operator <= (const Date& lsh, const Date& rhs) noexcept; 36 | bool operator > (const Date& lsh, const Date& rhs) noexcept; 37 | bool operator >= (const Date& lsh, const Date& rhs) noexcept; 38 | bool operator == (const Date& lsh, const Date& rhs) noexcept; 39 | bool operator != (const Date& lsh, const Date& rhs) noexcept; 40 | //---------------------------------------------------------------------------------------------------- 41 | #endif // _DATE_H_ -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/node.cpp: -------------------------------------------------------------------------------- 1 | #include "node.h" 2 | 3 | //---------------------------------------------------------------------------------------------------- 4 | EmptyNode::EmptyNode() noexcept 5 | { 6 | //Constructor body 7 | } 8 | //---------------------------------------------------------------------------------------------------- 9 | bool EmptyNode::Evaluate(const Date& date, const std::string& event) const noexcept 10 | { 11 | return true; 12 | } 13 | //---------------------------------------------------------------------------------------------------- 14 | DateComparisonNode::DateComparisonNode(const Comparison& comprs, const Date& date) noexcept : cmpr(comprs), dt(date) 15 | { 16 | //Constructor body 17 | } 18 | //---------------------------------------------------------------------------------------------------- 19 | bool DateComparisonNode::Evaluate(const Date& date, const std::string& event) const noexcept 20 | { 21 | switch (cmpr) 22 | { 23 | case Comparison::Less: 24 | return date < dt; 25 | case Comparison::LessOrEqual: 26 | return date <= dt; 27 | case Comparison::Greater: 28 | return date > dt; 29 | case Comparison::GreaterOrEqual: 30 | return date >= dt; 31 | case Comparison::Equal: 32 | return date == dt; 33 | case Comparison::NotEqual: 34 | return date != dt; 35 | default: 36 | return 0; 37 | break; 38 | } 39 | } 40 | //---------------------------------------------------------------------------------------------------- 41 | EventComparisonNode::EventComparisonNode(const Comparison& comprs, const std::string& event) : cmpr(comprs), evnt(event) 42 | { 43 | //Constructor body 44 | } 45 | //---------------------------------------------------------------------------------------------------- 46 | bool EventComparisonNode::Evaluate(const Date& date, const std::string& event) const noexcept 47 | { 48 | switch (cmpr) 49 | { 50 | case Comparison::Less: 51 | return event < evnt; 52 | case Comparison::LessOrEqual: 53 | return event <= evnt; 54 | case Comparison::Greater: 55 | return event > evnt; 56 | case Comparison::GreaterOrEqual: 57 | return event >= evnt; 58 | case Comparison::Equal: 59 | return event == evnt; 60 | case Comparison::NotEqual: 61 | return event != evnt; 62 | default: 63 | return 0; 64 | break; 65 | } 66 | } 67 | //---------------------------------------------------------------------------------------------------- 68 | LogicalOperationNode::LogicalOperationNode(const LogicalOperation& logical_operation, 69 | const std::shared_ptr& lhs, 70 | const std::shared_ptr& rhs) noexcept : lgc_op(logical_operation), 71 | lhs_node(lhs), rhs_node(rhs) 72 | { 73 | //Constructor body 74 | } 75 | //---------------------------------------------------------------------------------------------------- 76 | bool LogicalOperationNode::Evaluate(const Date& date, const std::string& event) const 77 | { 78 | switch (lgc_op) 79 | { 80 | case LogicalOperation::Or: 81 | return lhs_node->Evaluate(date, event) || rhs_node->Evaluate(date, event); 82 | case LogicalOperation::And: 83 | return lhs_node->Evaluate(date, event) && rhs_node->Evaluate(date, event); 84 | default: 85 | return 0; 86 | break; 87 | } 88 | } 89 | //---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/node.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _NODE_H_ 4 | #define _NODE_H_ 5 | 6 | #include "date.h" 7 | 8 | #include 9 | #include 10 | 11 | //---------------------------------------------------------------------------------------------------- 12 | enum class Comparison 13 | { 14 | Less, 15 | LessOrEqual, 16 | Greater, 17 | GreaterOrEqual, 18 | Equal, 19 | NotEqual 20 | }; 21 | //---------------------------------------------------------------------------------------------------- 22 | enum class LogicalOperation 23 | { 24 | Or, 25 | And 26 | }; 27 | //---------------------------------------------------------------------------------------------------- 28 | class Node 29 | { 30 | public: 31 | virtual bool Evaluate(const Date& date, const std::string& event) const = 0; 32 | virtual ~Node() = default; 33 | }; 34 | //---------------------------------------------------------------------------------------------------- 35 | class EmptyNode : public Node 36 | { 37 | public: 38 | EmptyNode() noexcept; 39 | bool Evaluate(const Date& date, const std::string& event) const noexcept override; 40 | }; 41 | //---------------------------------------------------------------------------------------------------- 42 | class DateComparisonNode : public Node 43 | { 44 | public: 45 | DateComparisonNode(const Comparison& comprs, const Date& date) noexcept; 46 | bool Evaluate(const Date& date, const std::string& event) const noexcept override; 47 | private: 48 | const Comparison cmpr; 49 | const Date dt; 50 | }; 51 | //---------------------------------------------------------------------------------------------------- 52 | class EventComparisonNode : public Node 53 | { 54 | public: 55 | EventComparisonNode(const Comparison& comprs, const std::string& event); 56 | bool Evaluate(const Date& date, const std::string& event) const noexcept override; 57 | private: 58 | const Comparison cmpr; 59 | const std::string evnt; 60 | }; 61 | //---------------------------------------------------------------------------------------------------- 62 | class LogicalOperationNode : public Node 63 | { 64 | public: 65 | LogicalOperationNode(const LogicalOperation& logical_operation, 66 | const std::shared_ptr& lhs, 67 | const std::shared_ptr& rhs) noexcept; 68 | bool Evaluate(const Date& date, const std::string& event) const override; 69 | private: 70 | const LogicalOperation lgc_op; 71 | const std::shared_ptr lhs_node; 72 | const std::shared_ptr rhs_node; 73 | }; 74 | //---------------------------------------------------------------------------------------------------- 75 | #endif // _NODE_H_ -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/test_runner.cpp: -------------------------------------------------------------------------------- 1 | #include "test_runner.h" 2 | 3 | //---------------------------------------------------------------------------------------------------- 4 | void Assert(bool b, const std::string& hint) 5 | { 6 | AssertEqual(b, true, hint); 7 | } 8 | //---------------------------------------------------------------------------------------------------- 9 | TestRunner::~TestRunner() 10 | { 11 | if (fail_count > 0) 12 | { 13 | std::cerr << "========================================" << std::endl; 14 | std::cerr << "FAILED (failures = " << fail_count << ")" << std::endl; 15 | std::cerr << "========================================" << std::endl; 16 | exit(1); 17 | } 18 | else 19 | { 20 | std::cerr << "========================================" << std::endl; 21 | std::cerr << "OK" << std::endl; 22 | std::cerr << "========================================" << std::endl; 23 | } 24 | } 25 | //---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/test_runner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _TEST_RUNNER_H_ 4 | #define _TEST_RUNNER_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | //------------------------------------------------------------------------------------------------- 14 | class TestRunner 15 | { 16 | public: 17 | template 18 | void RunTest(test_func func, const std::string& test_name); 19 | 20 | TestRunner() = default; 21 | ~TestRunner(); 22 | private: 23 | int fail_count = 0; 24 | }; 25 | //------------------------------------------------------------------------------------------------- 26 | template 27 | void TestRunner::RunTest(test_func func, const std::string& test_name) 28 | { 29 | try 30 | { 31 | func(); 32 | std::cerr << "PASSED: " << test_name << std::endl; 33 | } 34 | catch (const std::runtime_error & e) 35 | { 36 | ++fail_count; 37 | std::cerr << "FAIL: " << test_name << e.what() << std::endl; 38 | } 39 | } 40 | //------------------------------------------------------------------------------------------------- 41 | template 42 | std::ostream& operator << (std::ostream& os, const std::set& s) 43 | { 44 | os << "{"; 45 | bool first = true; 46 | for (const auto& x : s) 47 | { 48 | if (!first) 49 | { 50 | os << ", "; 51 | } 52 | first = false; 53 | os << x; 54 | } 55 | return os << "}"; 56 | } 57 | //------------------------------------------------------------------------------------------------- 58 | template 59 | std::ostream& operator << (std::ostream& os, const std::map& map) 60 | { 61 | os << "{"; 62 | bool first = true; 63 | for (const auto& kv : map) 64 | { 65 | if (!first) 66 | { 67 | os << ", "; 68 | } 69 | first = false; 70 | os << kv.first << ": " << kv.second; 71 | } 72 | return os << "}"; 73 | } 74 | //------------------------------------------------------------------------------------------------- 75 | template 76 | std::ostream& operator << (std::ostream& os, const std::vector& s) 77 | { 78 | os << "{"; 79 | bool first = true; 80 | for (const auto& x : s) 81 | { 82 | if (!first) 83 | { 84 | os << ", "; 85 | } 86 | first = false; 87 | os << x; 88 | } 89 | return os << "}"; 90 | } 91 | //------------------------------------------------------------------------------------------------- 92 | void Assert(bool b, const std::string& hint); 93 | //------------------------------------------------------------------------------------------------- 94 | template 95 | void AssertEqual(const T& t, const U& u, const std::string& hint) 96 | { 97 | if (t != u) 98 | { 99 | std::ostringstream os; 100 | os << " Assertion failed: " << std::endl; 101 | os << t << " != " << u << " hint: " << hint; 102 | throw std::runtime_error(os.str()); 103 | } 104 | } 105 | //------------------------------------------------------------------------------------------------- 106 | #endif // _TEST_RUNNER_H_ -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Solution/token.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _TOKEN_H_ 4 | #define _TOKEN_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | //---------------------------------------------------------------------------------------------------- 11 | enum class TokenType 12 | { 13 | DATE, 14 | EVENT, 15 | COLUMN, 16 | LOGICAL_OP, 17 | COMPARE_OP, 18 | PAREN_LEFT, 19 | PAREN_RIGHT, 20 | }; 21 | //---------------------------------------------------------------------------------------------------- 22 | struct Token 23 | { 24 | const std::string value; 25 | const TokenType type; 26 | }; 27 | //---------------------------------------------------------------------------------------------------- 28 | std::vector Tokenize(std::istream& cl); 29 | //---------------------------------------------------------------------------------------------------- 30 | #endif // _TOKEN_H_ -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Source/condition_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "condition_parser.h" 2 | #include "token.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | template shared_ptr ParseComparison(It& current, It end) { 8 | if (current == end) { 9 | throw logic_error("Expected column name: date or event"); 10 | } 11 | 12 | Token& column = *current; 13 | if (column.type != TokenType::COLUMN) { 14 | throw logic_error("Expected column name: date or event"); 15 | } 16 | ++current; 17 | 18 | if (current == end) { 19 | throw logic_error("Expected comparison operation"); 20 | } 21 | 22 | Token& op = *current; 23 | if (op.type != TokenType::COMPARE_OP) { 24 | throw logic_error("Expected comparison operation"); 25 | } 26 | ++current; 27 | 28 | if (current == end) { 29 | throw logic_error("Expected right value of comparison"); 30 | } 31 | 32 | Comparison cmp; 33 | if (op.value == "<") { 34 | cmp = Comparison::Less; 35 | } else if (op.value == "<=") { 36 | cmp = Comparison::LessOrEqual; 37 | } else if (op.value == ">") { 38 | cmp = Comparison::Greater; 39 | } else if (op.value == ">=") { 40 | cmp = Comparison::GreaterOrEqual; 41 | } else if (op.value == "==") { 42 | cmp = Comparison::Equal; 43 | } else if (op.value == "!=") { 44 | cmp = Comparison::NotEqual; 45 | } else { 46 | throw logic_error("Unknown comparison token: " + op.value); 47 | } 48 | 49 | const string& value = current->value; 50 | ++current; 51 | 52 | if (column.value == "date") { 53 | istringstream is(value); 54 | return make_shared(cmp, ParseDate(is)); 55 | } else { 56 | return make_shared(cmp, value); 57 | } 58 | } 59 | 60 | template 61 | shared_ptr ParseExpression(It& current, It end, unsigned precedence) { 62 | if (current == end) { 63 | return shared_ptr(); 64 | } 65 | 66 | shared_ptr left; 67 | 68 | if (current->type == TokenType::PAREN_LEFT) { 69 | ++current; // consume '(' 70 | left = ParseExpression(current, end, 0u); 71 | if (current == end || current->type != TokenType::PAREN_RIGHT) { 72 | throw logic_error("Missing right paren"); 73 | } 74 | ++current; // consume ')' 75 | } else { 76 | left = ParseComparison(current, end); 77 | } 78 | 79 | const map precedences = { 80 | {LogicalOperation::Or, 1}, {LogicalOperation::And, 2} 81 | }; 82 | 83 | while (current != end && current->type != TokenType::PAREN_RIGHT) { 84 | if (current->type != TokenType::LOGICAL_OP) { 85 | throw logic_error("Expected logic operation"); 86 | } 87 | 88 | const auto logical_operation = current->value == "AND" ? LogicalOperation::And 89 | : LogicalOperation::Or; 90 | const auto current_precedence = precedences.at(logical_operation); 91 | if (current_precedence <= precedence) { 92 | break; 93 | } 94 | 95 | ++current; // consume op 96 | 97 | left = make_shared( 98 | logical_operation, left, ParseExpression(current, end, current_precedence) 99 | ); 100 | } 101 | 102 | return left; 103 | } 104 | 105 | shared_ptr ParseCondition(istream& is) { 106 | auto tokens = Tokenize(is); 107 | auto current = tokens.begin(); 108 | auto top_node = ParseExpression(current, tokens.end(), 0u); 109 | 110 | if (!top_node) { 111 | top_node = make_shared(); 112 | } 113 | 114 | if (current != tokens.end()) { 115 | throw logic_error("Unexpected tokens after condition"); 116 | } 117 | 118 | return top_node; 119 | } 120 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Source/condition_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "node.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | shared_ptr ParseCondition(istream& is); 11 | 12 | void TestParseCondition(); 13 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Source/main.cpp: -------------------------------------------------------------------------------- 1 | #include "database.h" 2 | #include "date.h" 3 | #include "condition_parser.h" 4 | #include "node.h" 5 | #include "test_runner.h" 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | string ParseEvent(istream& is) { 13 | // Реализуйте эту функцию 14 | } 15 | 16 | void TestAll(); 17 | 18 | int main() { 19 | TestAll(); 20 | 21 | Database db; 22 | 23 | for (string line; getline(cin, line); ) { 24 | istringstream is(line); 25 | 26 | string command; 27 | is >> command; 28 | if (command == "Add") { 29 | const auto date = ParseDate(is); 30 | const auto event = ParseEvent(is); 31 | db.Add(date, event); 32 | } else if (command == "Print") { 33 | db.Print(cout); 34 | } else if (command == "Del") { 35 | auto condition = ParseCondition(is); 36 | auto predicate = [condition](const Date& date, const string& event) { 37 | return condition->Evaluate(date, event); 38 | }; 39 | int count = db.RemoveIf(predicate); 40 | cout << "Removed " << count << " entries" << endl; 41 | } else if (command == "Find") { 42 | auto condition = ParseCondition(is); 43 | auto predicate = [condition](const Date& date, const string& event) { 44 | return condition->Evaluate(date, event); 45 | }; 46 | 47 | const auto entries = db.FindIf(predicate); 48 | for (const auto& entry : entries) { 49 | cout << entry << endl; 50 | } 51 | cout << "Found " << entries.size() << " entries" << endl; 52 | } else if (command == "Last") { 53 | try { 54 | cout << db.Last(ParseDate(is)) << endl; 55 | } catch (invalid_argument&) { 56 | cout << "No entries" << endl; 57 | } 58 | } else if (command.empty()) { 59 | continue; 60 | } else { 61 | throw logic_error("Unknown command: " + command); 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | void TestParseEvent() { 69 | { 70 | istringstream is("event"); 71 | AssertEqual(ParseEvent(is), "event", "Parse event without leading spaces"); 72 | } 73 | { 74 | istringstream is(" sport event "); 75 | AssertEqual(ParseEvent(is), "sport event ", "Parse event with leading spaces"); 76 | } 77 | { 78 | istringstream is(" first event \n second event"); 79 | vector events; 80 | events.push_back(ParseEvent(is)); 81 | events.push_back(ParseEvent(is)); 82 | AssertEqual(events, vector{"first event ", "second event"}, "Parse multiple events"); 83 | } 84 | } 85 | 86 | void TestAll() { 87 | TestRunner tr; 88 | tr.RunTest(TestParseEvent, "TestParseEvent"); 89 | tr.RunTest(TestParseCondition, "TestParseCondition"); 90 | } 91 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Source/token.cpp: -------------------------------------------------------------------------------- 1 | #include "token.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector Tokenize(istream& cl) { 8 | vector tokens; 9 | 10 | char c; 11 | while (cl >> c) { 12 | if (isdigit(c)) { 13 | string date(1, c); 14 | for (int i = 0; i < 3; ++i) { 15 | while (isdigit(cl.peek())) { 16 | date += cl.get(); 17 | } 18 | if (i < 2) { 19 | date += cl.get(); // Consume '-' 20 | } 21 | } 22 | tokens.push_back({date, TokenType::DATE}); 23 | } else if (c == '"') { 24 | string event; 25 | getline(cl, event, '"'); 26 | tokens.push_back({event, TokenType::EVENT}); 27 | } else if (c == 'd') { 28 | if (cl.get() == 'a' && cl.get() == 't' && cl.get() == 'e') { 29 | tokens.push_back({"date", TokenType::COLUMN}); 30 | } else { 31 | throw logic_error("Unknown token"); 32 | } 33 | } else if (c == 'e') { 34 | if (cl.get() == 'v' && cl.get() == 'e' && cl.get() == 'n' && 35 | cl.get() == 't') { 36 | tokens.push_back({"event", TokenType::COLUMN}); 37 | } else { 38 | throw logic_error("Unknown token"); 39 | } 40 | } else if (c == 'A') { 41 | if (cl.get() == 'N' && cl.get() == 'D') { 42 | tokens.push_back({"AND", TokenType::LOGICAL_OP}); 43 | } else { 44 | throw logic_error("Unknown token"); 45 | } 46 | } else if (c == 'O') { 47 | if (cl.get() == 'R') { 48 | tokens.push_back({"OR", TokenType::LOGICAL_OP}); 49 | } else { 50 | throw logic_error("Unknown token"); 51 | } 52 | } else if (c == '(') { 53 | tokens.push_back({"(", TokenType::PAREN_LEFT}); 54 | } else if (c == ')') { 55 | tokens.push_back({")", TokenType::PAREN_RIGHT}); 56 | } else if (c == '<') { 57 | if (cl.peek() == '=') { 58 | cl.get(); 59 | tokens.push_back({"<=", TokenType::COMPARE_OP}); 60 | } else { 61 | tokens.push_back({"<", TokenType::COMPARE_OP}); 62 | } 63 | } else if (c == '>') { 64 | if (cl.peek() == '=') { 65 | cl.get(); 66 | tokens.push_back({">=", TokenType::COMPARE_OP}); 67 | } else { 68 | tokens.push_back({">", TokenType::COMPARE_OP}); 69 | } 70 | } else if (c == '=') { 71 | if (cl.get() == '=') { 72 | tokens.push_back({"==", TokenType::COMPARE_OP}); 73 | } else { 74 | throw logic_error("Unknown token"); 75 | } 76 | } else if (c == '!') { 77 | if (cl.get() == '=') { 78 | tokens.push_back({"!=", TokenType::COMPARE_OP}); 79 | } else { 80 | throw logic_error("Unknown token"); 81 | } 82 | } 83 | } 84 | 85 | return tokens; 86 | } 87 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/Source/token.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | enum class TokenType { 8 | DATE, 9 | EVENT, 10 | COLUMN, 11 | LOGICAL_OP, 12 | COMPARE_OP, 13 | PAREN_LEFT, 14 | PAREN_RIGHT, 15 | }; 16 | 17 | struct Token { 18 | const string value; 19 | const TokenType type; 20 | }; 21 | 22 | vector Tokenize(istream& cl); 23 | -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/help1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_6/01 Programming Assignment/help1.pdf -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/help2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_6/01 Programming Assignment/help2.pdf -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/help3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_6/01 Programming Assignment/help3.pdf -------------------------------------------------------------------------------- /Week_6/01 Programming Assignment/help4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/Week_6/01 Programming Assignment/help4.pdf -------------------------------------------------------------------------------- /img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reavolt/basics-of-c-plus-plus-development-yellow-belt/4e86d1c23485dcea7acb4cbfa5d5d3d16ab9ac24/img.jpg --------------------------------------------------------------------------------