├── .gitignore ├── README.md ├── week1 ├── 1.cxx ├── 2.cpp ├── 3.cpp ├── 4.py └── 5.cxx ├── week10 ├── 10.1.cpp └── 10.2.cpp ├── week2 ├── 2.1.cpp ├── 2.2.cpp ├── 2.3.cpp └── 2.5.cpp ├── week3 ├── 3.1.cpp └── zwei_correct.cxx ├── week4 ├── 4.1.cpp ├── 4.2.cpp ├── 4.3.cpp ├── 4.4.cpp └── 4.5.cpp ├── week5 ├── 5.1.cpp ├── eins.cxx └── zwei.cxx ├── week6 ├── 6.1.cpp ├── 6.2.cpp ├── 6.3.cpp └── 6.4.cpp ├── week7 ├── 1.7.cxx ├── 2.7.cxx ├── 2_2.7.cxx ├── 3.7.cpp ├── 4.cxx └── 5.7.cxx ├── week8 ├── 1.py ├── third.cpp └── zwei.cxx └── week9 ├── 1.cpp ├── procto.cxx └── zprocto.cxx /.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | /.idea 3 | /cmake-build-debug -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Решения для заданий с курса "Алгоритмы программирования и структуры данных" 2 | 3 | Ссылка на курс [тык](https://courses.openedu.ru/courses/course-v1:ITMOUniversity+PADS+spring_2020_ITMO/info#_=_) 4 | 5 | Кому помог поставьте звездочку :) 6 | -------------------------------------------------------------------------------- /week1/1.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomas on 15.02.2020. 3 | // 4 | 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main() { 12 | long long a, b; 13 | 14 | { 15 | ifstream input("input.txt"); 16 | input >> a >> b; 17 | } 18 | 19 | { 20 | ofstream output("output.txt"); 21 | output << a + b; 22 | } 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /week1/2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomas on 15.02.2020. 3 | // 4 | 5 | #include 6 | 7 | int main() { 8 | long long a, b; 9 | 10 | { 11 | std::ifstream input("input.txt"); 12 | input >> a >> b; 13 | } 14 | 15 | { 16 | std::ofstream output("output.txt"); 17 | output << a + b * b; 18 | } 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /week1/3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomas on 15.02.2020. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | void sort(std::vector &to_sorted, std::vector &target) { 9 | target.push_back(1); 10 | for (int i = 1; i < to_sorted.size(); i++) { 11 | int j; 12 | for (j = i; j > 0 && to_sorted[j - 1] > to_sorted[j]; j--) { 13 | int tmp = to_sorted[j - 1]; 14 | to_sorted[j - 1] = to_sorted[j]; 15 | to_sorted[j] = tmp; 16 | } 17 | target.push_back(j + 1); 18 | } 19 | 20 | } 21 | 22 | int main() { 23 | int n; 24 | std::vector vec_inp = {}; 25 | std::vector weirder = {}; 26 | { 27 | std::ifstream input("input.txt"); 28 | input >> n; 29 | 30 | vec_inp.reserve(n); 31 | weirder.reserve(n); 32 | for (int i = 0; i < n; i++) { 33 | int tmp; 34 | input >> tmp; 35 | vec_inp.push_back(tmp); 36 | } 37 | } 38 | 39 | 40 | sort(vec_inp, weirder); 41 | 42 | { 43 | std::ofstream output("output.txt"); 44 | for (auto i : weirder) 45 | output << i << " "; 46 | output << std::endl; 47 | 48 | for (auto i : vec_inp) 49 | output << i << " "; 50 | } 51 | 52 | return 0; 53 | } -------------------------------------------------------------------------------- /week1/4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | 4 | def main(): 5 | numbers = [] 6 | with open("input.txt", "r") as f: 7 | ss = f.read() 8 | ss = ss.strip().split("\n")[1].strip().split() 9 | for y, x in enumerate(ss): 10 | numbers.append((float(x), y + 1)) 11 | 12 | numbers = sorted(numbers, key=lambda x: x[0]) 13 | 14 | # print(numbers[0][1], numbers[int((len(numbers) - 1) / 2)][1], numbers[len(numbers) - 1][1]) 15 | with open("output.txt", "w") as f: 16 | f.write("{} {} {}".format(numbers[0][1], numbers[int((len(numbers) - 1) / 2)][1], numbers[len(numbers) - 1][1])) 17 | 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /week1/5.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomas on 16.02.2020. 3 | // 4 | 5 | 6 | #include 7 | #include 8 | 9 | void quickSort(std::vector &numbers, int left, int right, std::vector> &target) { 10 | int pivot; // разрешающий элемент 11 | int l_hold = left; //левая граница 12 | int r_hold = right; // правая граница 13 | pivot = numbers[left]; 14 | while (left < right) // пока границы не сомкнутся 15 | { 16 | while ((numbers[right] >= pivot) && (left < right)) 17 | right--; // сдвигаем правую границу пока элемент [right] больше [pivot] 18 | if (left != right) // если границы не сомкнулись 19 | { 20 | numbers[left] = numbers[right]; // перемещаем элемент [right] на место разрешающего 21 | target.emplace_back(std::min(left, right) + 1, std::max(left, right) + 1); 22 | left++; // сдвигаем левую границу вправо 23 | } 24 | while ((numbers[left] <= pivot) && (left < right)) 25 | left++; // сдвигаем левую границу пока элемент [left] меньше [pivot] 26 | if (left != right) // если границы не сомкнулись 27 | { 28 | numbers[right] = numbers[left]; // перемещаем элемент [left] на место [right] 29 | target.emplace_back(std::min(left, right) + 1, std::max(left, right) + 1); 30 | right--; // сдвигаем правую границу вправо 31 | } 32 | } 33 | numbers[left] = pivot; // ставим разрешающий элемент на место 34 | pivot = left; 35 | left = l_hold; 36 | right = r_hold; 37 | if (left < pivot) // Рекурсивно вызываем сортировку для левой и правой части массива 38 | quickSort(numbers, left, pivot - 1, target); 39 | if (right > pivot) 40 | quickSort(numbers, pivot + 1, right, target); 41 | } 42 | 43 | int main() { 44 | int n; 45 | std::vector vec_inp = {}; 46 | std::vector> weirder = {}; 47 | { 48 | std::ifstream input("input.txt"); 49 | input >> n; 50 | 51 | vec_inp.reserve(n * n); 52 | weirder.reserve(n); 53 | for (int i = 0; i < n; i++) { 54 | int tmp; 55 | input >> tmp; 56 | vec_inp.push_back(tmp); 57 | } 58 | } 59 | 60 | 61 | quickSort(vec_inp, 0, vec_inp.size() - 1, weirder); 62 | 63 | { 64 | std::ofstream output("output.txt"); 65 | for (auto i : weirder) 66 | output << "Swap elements at indices " << i.first << " and " << i.second << ".\n"; 67 | output << "No more swaps needed." << std::endl; 68 | 69 | for (auto i : vec_inp) 70 | output << i << " "; 71 | } 72 | 73 | return 0; 74 | } -------------------------------------------------------------------------------- /week10/10.1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Постройте префикс-функцию для всех непустых префиксов заданной строки . 3 | */ 4 | 5 | #include 6 | #include 7 | #include "edx-io.hpp" 8 | 9 | std::vector prefix(std::string &s) { 10 | std::vector p = {0}; 11 | for (int i = 1; i < s.length(); i++) { 12 | int k = p[i - 1]; 13 | while (k > 0 && s[i] != s[k]) 14 | k = p[k - 1]; 15 | if (s[i] == s[k]) 16 | k++; 17 | p.push_back(k); 18 | } 19 | return p; 20 | } 21 | 22 | int main() { 23 | std::string s; 24 | io >> s; 25 | std::vector p = prefix(s); 26 | for (auto s: p) { 27 | io << s << " "; 28 | } 29 | } -------------------------------------------------------------------------------- /week10/10.2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Постройте Z-функцию для заданной строки . 3 | */ 4 | 5 | #include "edx-io.hpp" 6 | #include 7 | #include 8 | 9 | std::vector zFunction(std::string& s) { 10 | std::vector z(s.length(), 0); 11 | 12 | //начальные значения l и r непринципиальны 13 | for (int i = 1, l = 0, r = 0; i < s.length(); i++) { 14 | if (i <= r) { //если i входит в уже обработанный отрезок 15 | z[i] = std::min(z[i - l], r - i + 1); //используем предыдущие вычисления 16 | } 17 | 18 | //иначе начальным значением z[i] остаётся 0 19 | 20 | //пытаемся увеличить z[i] наивным алгоритмом 21 | while (i + z[i] < s.length()) { 22 | if (s[i + z[i]] == s[z[i]]) { 23 | z[i]++; 24 | } else { 25 | break; 26 | } 27 | } 28 | 29 | //если мы можем увеличить r, делаем это 30 | if (z[i] > 0 && i + z[i] - 1 > r) { 31 | l = i; 32 | r = i + z[i] - 1; 33 | } 34 | } 35 | 36 | return z; 37 | } 38 | 39 | int main() { 40 | std::string s; 41 | io >> s; 42 | std::vector zf = zFunction(s); 43 | for (int i = 1; i < s.size(); i++) { 44 | io << zf[i] << " "; 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /week2/2.1.cpp: -------------------------------------------------------------------------------- 1 | //Дан массив целых чисел. Ваша задача — отсортировать его в порядке неубывания с помощью сортировки слиянием. 2 | // 3 | //Чтобы убедиться, что Вы действительно используете сортировку слиянием, мы просим Вас, после каждого осуществленного 4 | //слияния (то есть, когда соответствующий подмассив уже отсортирован!), выводить индексы граничных элементов и их значения. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int min(int x, int y) { return (x < y) ? x : y; } 12 | 13 | void merge(int *A, int p, int q, int r, std::ofstream& outputFile) { 14 | int n1, n2, i, j, k; 15 | bool merging = false; 16 | 17 | n1 = q - p + 1; 18 | n2 = r - q; 19 | 20 | int *L = new int[n1]; 21 | int *R = new int[n2]; 22 | 23 | for (i = 0; i < n1; i++) { 24 | L[i] = A[p + i]; 25 | } 26 | 27 | for (j = 0; j < n2; j++) { 28 | R[j] = A[q + j + 1]; 29 | } 30 | 31 | i = 0, j = 0; 32 | 33 | for (k = p; i < n1 && j < n2; k++) { 34 | if (L[i] < R[j]) { 35 | A[k] = L[i++]; 36 | merging = true; 37 | } else { 38 | A[k] = R[j++]; 39 | merging = true; 40 | } 41 | } 42 | 43 | while (i < n1) { 44 | A[k++] = L[i++]; 45 | } 46 | 47 | while (j < n2) { 48 | A[k++] = R[j++]; 49 | } 50 | 51 | if (merging) { 52 | outputFile << p + 1 << " " << r + 1 << " " << A[p] << " " << A[r] << std::endl; 53 | } 54 | 55 | delete[] L; 56 | delete[] R; 57 | } 58 | 59 | void mergeSort(int *arr, int n) { 60 | int curr_size; 61 | int left_start; 62 | std::ofstream outputFile("output.txt", std::ios_base::app); 63 | 64 | for (curr_size = 1; curr_size <= n - 1; curr_size = 2 * curr_size) { 65 | for (left_start = 0; left_start < n - 1; left_start += 2 * curr_size) { 66 | int mid = min(left_start + curr_size - 1, n - 1); 67 | 68 | int right_end = min(left_start + 2 * curr_size - 1, n - 1); 69 | 70 | merge(arr, left_start, mid, right_end, outputFile); 71 | } 72 | } 73 | 74 | outputFile.close(); 75 | } 76 | 77 | int main() { 78 | std::ifstream inputFile("input.txt"); 79 | int size; 80 | inputFile >> size; 81 | int *array = new int[size]; 82 | 83 | for (int i = 0; i < size; i++) { 84 | inputFile >> array[i]; 85 | } 86 | 87 | inputFile.close(); 88 | mergeSort(array, size); 89 | 90 | std::ofstream outputFile("output.txt", std::ios_base::app); 91 | 92 | for (size_t i = 0; i < size; i++) { 93 | outputFile << array[i] << " "; 94 | } 95 | 96 | outputFile.close(); 97 | delete[] array; 98 | return 0; 99 | } -------------------------------------------------------------------------------- /week2/2.2.cpp: -------------------------------------------------------------------------------- 1 | //Дан массив целых чисел. Ваша задача — подсчитать число инверсий в нем. 2 | // 3 | //Подсказка: чтобы сделать это быстрее, можно воспользоваться модификацией сортировки слиянием. 4 | 5 | #include 6 | #include 7 | 8 | long long int merge(int arr[], int temp[], int left, int mid, int right) { 9 | int i, j, k; 10 | long long int count = 0; 11 | i = left; //i to locate first array location 12 | j = mid; //i to locate second array location 13 | k = left; //i to locate merged array location 14 | while ((i <= mid - 1) && (j <= right)) { 15 | if (arr[i] <= arr[j]){ //when left item is less than right item 16 | temp[k++] = arr[i++]; 17 | } else { 18 | temp[k++] = arr[j++]; 19 | count += (mid - i); //find how many convertion is performed 20 | } 21 | } 22 | while (i <= mid - 1) //if first list has remaining item, add them in the list 23 | temp[k++] = arr[i++]; 24 | while (j <= right) //if second list has remaining item, add them in the list 25 | temp[k++] = arr[j++]; 26 | for (i=left; i <= right; i++) 27 | arr[i] = temp[i]; //store temp Array to main array 28 | return count; 29 | } 30 | long long int mergeSort(int arr[], int temp[], int left, int right){ 31 | int mid; 32 | long long int count = 0; 33 | if (right > left) { 34 | mid = (right + left)/2; //find mid index of the array 35 | count = mergeSort(arr, temp, left, mid); //merge sort left sub array 36 | count += mergeSort(arr, temp, mid+1, right); //merge sort right sub array 37 | count += merge(arr, temp, left, mid+1, right); //merge two sub arrays 38 | } 39 | return count; 40 | } 41 | long long arrInversion(int arr[], int n) { 42 | int *temp = new int[n]; 43 | return mergeSort(arr, temp, 0, n - 1); 44 | } 45 | 46 | int main() { 47 | std::ifstream inputFile("input.txt"); 48 | int size = 0; 49 | inputFile >> size; 50 | int *array = new int[size]; 51 | 52 | for (int i = 0; i < size; i++) { 53 | inputFile >> array[i]; 54 | } 55 | 56 | inputFile.close(); 57 | 58 | long long int inversions = arrInversion(array, size); 59 | 60 | std::ofstream outputFile("output.txt"); 61 | outputFile << inversions; 62 | outputFile.close(); 63 | 64 | delete[] array; 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /week2/2.3.cpp: -------------------------------------------------------------------------------- 1 | //Хотя QuickSort является очень быстрой сортировкой в среднем, существуют тесты, на которых она работает очень долго. 2 | //Оценивать время работы алгоритма будем числом сравнений 3 | //с элементами массива (то есть, суммарным числом сравнений в первом и втором while). 4 | //Требуется написать программу, генерирующую тест, на котором быстрая сортировка сделает наибольшее число таких сравнений. 5 | 6 | #include 7 | 8 | void swap (int &a, int &b) { 9 | int temp = a; 10 | a = b; 11 | b = temp; 12 | } 13 | 14 | int main() { 15 | std::ifstream inputFile("input.txt"); 16 | int size = 0; 17 | inputFile >> size; 18 | inputFile.close(); 19 | 20 | std::ofstream output("output.txt"); 21 | int *array = new int[size]; 22 | 23 | for (int i = 0; i < size; i++) { 24 | array[i] = i + 1; 25 | } 26 | for (int i = 2; i < size; i++) { 27 | swap(array[i], array[i/2]); 28 | } 29 | for (int i = 0; i < size; i++) { 30 | output << array[i] << " "; 31 | } 32 | output.close(); 33 | delete[] array; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /week2/2.5.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | «Сортировка пугалом» — это давно забытая народная потешка, которую восстановили по летописям 3 | специалисты платформы «Открытое образование» специально для этого курса. 4 | 5 | Участнику под верхнюю одежду продевают деревянную палку, так что у него оказываются растопырены руки, как у огородного пугала. 6 | Перед ним ставятся матрёшек в ряд. Из-за палки единственное, что он может сделать — это взять в руки две матрешки 7 | на расстоянии друг от друга (то есть -ую и -ую), развернуться и поставить их обратно в ряд, таким образом поменяв их местами. 8 | 9 | Задача участника — расположить матрёшки по неубыванию размера. Может ли он это сделать? 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | void quickSort(int *, int, int, int); 16 | 17 | void swap(int &, int &); 18 | 19 | bool check(const int *array, int size); 20 | 21 | #include 22 | using namespace std::chrono; 23 | 24 | int main() { 25 | auto start = high_resolution_clock::now(); 26 | std::ifstream inputFile("input.txt"); 27 | int size = 0; 28 | int k = 0; 29 | int *array = new int[size]; 30 | inputFile >> size >> k; 31 | for (int i = 0; i < size; i++) { 32 | inputFile >> array[i]; 33 | } 34 | inputFile.close(); 35 | 36 | quickSort(array, 0, size - 1, k); 37 | 38 | std::ofstream output("output.txt"); 39 | output << (check(array, size) ? "YES" : "NO"); 40 | output.close(); 41 | delete[] array; 42 | auto stop = high_resolution_clock::now(); 43 | auto duration = duration_cast(stop - start); 44 | std::cout << duration.count() / 1e+6 << std::endl; 45 | return 0; 46 | } 47 | 48 | void quickSort(int *arr, int left, int right, int k) { 49 | int i = left; 50 | int j = right; 51 | int key = arr[(left + right) / 2]; 52 | 53 | while (i <= j) { 54 | while (arr[i] < key) { 55 | i += 1; 56 | } 57 | while (arr[j] > key) { 58 | j -= 1; 59 | } 60 | if (i <= j) { 61 | if (abs(i - j) == k) { 62 | swap(arr[i], arr[j]); 63 | } 64 | i += 1; 65 | j -= 1; 66 | } 67 | } 68 | 69 | if (left < j) 70 | quickSort(arr, left, j, k); 71 | if (right > i) 72 | quickSort(arr, i, right, k); 73 | } 74 | 75 | void swap(int &a, int &b) { 76 | int temp = a; 77 | a = b; 78 | b = temp; 79 | } 80 | 81 | bool check(const int *array, int size) { 82 | for (int i = 0; i < size - 1; i++) { 83 | if (array[i] > array[i + 1]) return false; 84 | } 85 | return true; 86 | } 87 | -------------------------------------------------------------------------------- /week3/3.1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | В этой задаче Вам нужно будет отсортировать много неотрицательных целых чисел. 3 | 4 | Вам даны два массива, и , содержащие соответственно и элементов. Числа, которые нужно будет отсортировать, имеют вид... 5 | Иными словами, каждый элемент первого массива нужно умножить на каждый элемент второго массива. 6 | 7 | Пусть из этих чисел получится отсортированная последовательность длиной . Выведите сумму каждого десятого элемента 8 | этой последовательности (то есть, ...). 9 | */ 10 | 11 | #include "edx-io.hpp" 12 | #include 13 | #include 14 | 15 | void int_radix_sort(int[], unsigned int); 16 | 17 | int main() { 18 | int n, m = 0; 19 | io >> n >> m; 20 | const unsigned int size = n * m; 21 | int* const firstArray = new int[n]; 22 | int* const combinedArray = new int[size]; 23 | for (int i = 0; i < n; i++) { 24 | io >> firstArray[i]; 25 | } 26 | int max = -1; 27 | for (int i = 0; i < m; i++) { 28 | int secondArrEl = -1; 29 | io >> secondArrEl; 30 | for (int j = 0; j < n; j++) { 31 | int res = firstArray[j] * secondArrEl; 32 | if (res > max) 33 | max = res; 34 | combinedArray[j + i * n] = res; 35 | } 36 | } 37 | int_radix_sort(combinedArray, size); 38 | long long int sum = 0; 39 | for (int i = 0; i < size; i += 10) { 40 | sum += combinedArray[i]; 41 | } 42 | io << sum; 43 | delete[] combinedArray; 44 | delete[] firstArray; 45 | return 0; 46 | } 47 | 48 | /* 49 | Integer Radix LSD sort. Stable and out-of-place. 50 | ---Parameters--- 51 | 52 | vector[] - Pointer to the orginal array of integers 53 | size - Size of the array to sort 54 | 55 | ---List of optimizations implemented--- 56 | For a list of all optimizations implemented check the github README.md 57 | over at https://github.com/AwardOfSky/Fast-Radix-Sort 58 | */ 59 | void int_radix_sort(int vector[], unsigned int size) { 60 | 61 | /* Support for variable sized integers without overflow warnings */ 62 | #define MAX_UINT__ ((unsigned int)(~0) >> 1) 63 | #define LAST_EXP__ (sizeof(int) << 3) 64 | /* Define std preliminary, abosulte max value and if there are bytes left */ 65 | #define PRELIMINARY__ 64 66 | #define ABS_MAX__ ((max < -exp) ? -exp : max) 67 | #define MISSING_BITS__ exp < LAST_EXP__ && (max >> exp) > 0 68 | /* Check for max and min integer in [a, b[ array segment */ 69 | #define LOOP_MAX__(a, b) \ 70 | for(s = &vector[a], k = &vector[b]; s < k; ++s) { \ 71 | if(*s > max || *s < exp) { \ 72 | if(*s > max) { \ 73 | max = *s; \ 74 | } else { \ 75 | exp = *s; \ 76 | } \ 77 | } \ 78 | } 79 | 80 | register int* helper; /* Helper array */ 81 | register int* s, * k, i; /* Array iterators */ 82 | register int exp = *vector; /* Bits sorted */ 83 | register int max = exp; /* Maximun range in array */ 84 | register unsigned char* n, * m; /* Iterator of a byte within an integer */ 85 | int swap = 0; /* Tells where sorted array is (if, sorted is in vector) */ 86 | int last_byte_sorted = 0; /* 1 if we had to sort the last byte */ 87 | int next = 0; /* If 1 we skip the byte (all buckets are the same) */ 88 | unsigned int init_size = size; /* Copy (needed if doing subdivisions) */ 89 | 90 | /* Preliminary value to retrieve some initial info from the array */ 91 | const int prel = (size > (PRELIMINARY__ << 1)) ? PRELIMINARY__ : (size >> 3); 92 | 93 | /* Get max value (to know how many bytes to sort) */ 94 | LOOP_MAX__(1, prel); 95 | LOOP_MAX__(size - prel, size); 96 | if (ABS_MAX__ <= (MAX_UINT__ >> 7) || (max - exp == 0)) { 97 | LOOP_MAX__(prel, size - prel); 98 | } 99 | unsigned int diff = max - exp; 100 | max = ABS_MAX__; 101 | 102 | /* Set number of bytes to sort according to max */ 103 | int bytes_to_sort = 0; 104 | if (diff != 0) { 105 | bytes_to_sort = 1; 106 | exp = 8; 107 | while (exp < LAST_EXP__ && (max >> (exp - 1)) > 0) { 108 | bytes_to_sort++; 109 | exp += 8; 110 | } 111 | } else { /* 1 unique element */ 112 | return; 113 | } 114 | 115 | /* Helper array initialization */ 116 | helper = (int*) malloc(sizeof(int) * size); 117 | 118 | /* Core algorithm template: */ 119 | /* 1 - Fill the buckets (using byte iterators) */ 120 | /* 2 - Check if there is 1 bucket w/ all elements (no need to sort byte) */ 121 | /* 3 - Set the pointers to the helper array if setting the byte */ 122 | /* 4 - Iterate the bucket values within the orginal array and chnage the */ 123 | /* corresponding values in the helper */ 124 | #define SORT_BYTE__(vector, helper, shift, bucket, \ 125 | pointer, ptr_init, optional_ptr_init) \ 126 | int bucket[0x100] = {0}; \ 127 | n = (unsigned char *)(vector) + (exp >> 3); \ 128 | for(m = (unsigned char *)(&vector[size & (~0 << 3)]); n < m;) { \ 129 | ++bucket[*n]; n += sizeof(int); \ 130 | ++bucket[*n]; n += sizeof(int); \ 131 | ++bucket[*n]; n += sizeof(int); \ 132 | ++bucket[*n]; n += sizeof(int); \ 133 | ++bucket[*n]; n += sizeof(int); \ 134 | ++bucket[*n]; n += sizeof(int); \ 135 | ++bucket[*n]; n += sizeof(int); \ 136 | ++bucket[*n]; n += sizeof(int); \ 137 | } \ 138 | for(n = (unsigned char *)(&vector[size & (~0 << 3)]) + (exp >> 3), \ 139 | m = (unsigned char *)(&vector[size]); n < m;) { \ 140 | ++bucket[*n]; n += sizeof(int); \ 141 | } \ 142 | s = helper; \ 143 | next = 0; \ 144 | if(size > 65535) { \ 145 | for(i = 0; i < 0x100 && !next; ++i) { \ 146 | if(bucket[i] == size) { \ 147 | optional_ptr_init; \ 148 | next = 1; \ 149 | } \ 150 | } \ 151 | } \ 152 | if(!next) { \ 153 | if(exp != (LAST_EXP__ - 8)) { \ 154 | for(i = 0; i < 0x100; s += bucket[i++]) { \ 155 | ptr_init; \ 156 | } \ 157 | } else { \ 158 | for(i = 128; i < 0x100; s += bucket[i++]) { \ 159 | ptr_init; \ 160 | } \ 161 | for(i = 0; i < 128; s += bucket[i++]) { \ 162 | ptr_init; \ 163 | } \ 164 | } \ 165 | for(s = vector, k = &vector[size & (~0 << 3)]; s < k;) { \ 166 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 167 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 168 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 169 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 170 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 171 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 172 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 173 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 174 | } \ 175 | for(s = &vector[size & (~0 << 3)], k = &vector[size]; s < k;) { \ 176 | *pointer[(*s shift) & 0xFF]++ = *s; ++s; \ 177 | } \ 178 | swap = 1 - swap; \ 179 | } \ 180 | exp += 8; 181 | 182 | int* point[0x100] = {0}; /* Array of pointers to the helper array */ 183 | 184 | if (bytes_to_sort > 1 && size > 1600000) { /* MSB order (size > 1.6M) */ 185 | 186 | exp -= 8; 187 | 188 | /* old_point will serve as a copy of the initial values of "point" */ 189 | /* Beggining of each subarray in 1st subdivision (256 subarrays) */ 190 | int* old_point[0x100] = {0}; 191 | 192 | /* Sort last byte */ 193 | SORT_BYTE__(vector, helper, >> exp, bucket, point, 194 | old_point[i] = s; point[i] = s, 195 | old_point[i] = s; point[i] = old_point[i] + size); 196 | bytes_to_sort--; 197 | if (exp == LAST_EXP__) { 198 | last_byte_sorted = 1; 199 | } 200 | 201 | /* 2nd subdivision only for 3 bytes or more (and size > 512M) */ 202 | register int j; 203 | if (bytes_to_sort > 1 && size > 512000000) { 204 | 205 | exp -= 16; 206 | 207 | /* Same purpose as "point" and old_point" but for 2nd subdivision */ 208 | int* point_2msb[0x10000] = {0}; 209 | int* old_point_2msb[0x10000] = {0}; 210 | int swap_copy = swap; /* Reset value of swap after each subarray */ 211 | 212 | /* Sort second to last byte in LSB order (256 subdivisions) */ 213 | for (j = 0; j < 0x100; ++j) { 214 | size = point[j] - old_point[j]; 215 | swap = swap_copy; 216 | 217 | /* Define temporary vector and helper according to current swap*/ 218 | register int* sub_help, * sub_vec; 219 | if (swap) { 220 | sub_vec = old_point[j]; 221 | sub_help = vector + (old_point[j] - helper); 222 | } else { 223 | sub_vec = vector + (old_point[j] - helper); 224 | sub_help = old_point[j]; 225 | } 226 | 227 | /* Temporary for ea subdivision, these work as "array riders" */ 228 | int** point_2msb_rider = point_2msb + (j << 8); 229 | int** old_point_2msb_rider = old_point_2msb + (j << 8); 230 | 231 | /* Actually sort the byte */ 232 | SORT_BYTE__(sub_vec, sub_help, >> exp, bucket1, point_2msb_rider, 233 | point_2msb_rider[i] = old_point_2msb_rider[i] = s, 234 | old_point_2msb_rider[i] = s; 235 | point_2msb_rider[i] = old_point_2msb_rider[i] + size); 236 | exp -= 8; 237 | 238 | /* Make sure the sorted array is in the original vector */ 239 | if (swap) { 240 | if (swap_copy) { 241 | memcpy(sub_help, sub_vec, sizeof(int) * size); 242 | } else { 243 | memcpy(sub_vec, sub_help, sizeof(int) * size); 244 | } 245 | } 246 | 247 | } 248 | swap = 0; /* Because now sorted array is in vector*/ 249 | bytes_to_sort--; 250 | 251 | /* Sort remaining bytes in LSB order (65536 subdivisions) */ 252 | max = 1 << ((bytes_to_sort - 1) << 3); 253 | for (j = 0; j < 0x10000; ++j) { 254 | 255 | exp = 0; 256 | size = point_2msb[j] - old_point_2msb[j]; 257 | swap = 0; /* Reset swap (last swap is always 0) */ 258 | 259 | /* Define temp arrays according to wether the first MSB byte */ 260 | /* was sorted or not (array pointed by old_point_2msb changes) */ 261 | register int* sub_help, * sub_vec; 262 | if (swap_copy) { 263 | sub_vec = old_point_2msb[j]; 264 | sub_help = helper + (old_point_2msb[j] - vector); 265 | } else { 266 | sub_vec = vector + (old_point_2msb[j] - helper); 267 | sub_help = old_point_2msb[j]; 268 | } 269 | 270 | while (MISSING_BITS__) { /* While there are remaining bytes */ 271 | if (exp) { 272 | if (swap) { 273 | SORT_BYTE__(sub_help, sub_vec, >> exp, bucket1, 274 | point, point[i] = s,); 275 | } else { /* Note: won't happen in 32 bit integers */ 276 | SORT_BYTE__(sub_vec, sub_help, >> exp, bucket1, 277 | point, point[i] = s,); 278 | } 279 | } else { 280 | SORT_BYTE__(sub_vec, sub_help, , bucket1, 281 | point, point[i] = s,); 282 | } 283 | } 284 | 285 | if (swap) { /* Force sorted segments to be in original vector */ 286 | memcpy(sub_vec, sub_help, sizeof(int) * size); 287 | } 288 | 289 | } 290 | swap = 0; 291 | 292 | } else { 293 | 294 | /* Start sorting from LSB now */ 295 | max = 1 << ((bytes_to_sort - 1) << 3); 296 | int swap_copy = swap; /* Once more, reset swap in ea subarray */ 297 | for (j = 0; j < 0x100; ++j) { 298 | exp = 0; 299 | size = point[j] - old_point[j]; 300 | swap = swap_copy; 301 | 302 | register int* sub_help, * sub_vec; /* Temprary arrays */ 303 | if (swap) { 304 | sub_help = vector + (old_point[j] - helper); 305 | sub_vec = old_point[j]; 306 | } else { 307 | sub_help = old_point[j]; 308 | sub_vec = vector + (old_point[j] - helper); 309 | } 310 | 311 | int* temp_point[0x100]; /* Temp ptrs, just to sort this segment */ 312 | while (MISSING_BITS__) { /* While there are remaining bytes */ 313 | if (exp) { 314 | if (swap != swap_copy) { 315 | SORT_BYTE__(sub_help, sub_vec, >> exp, bucket1, 316 | temp_point, temp_point[i] = s,); 317 | } else { 318 | SORT_BYTE__(sub_vec, sub_help, >> exp, bucket1, 319 | temp_point, temp_point[i] = s,); 320 | } 321 | } else { 322 | SORT_BYTE__(sub_vec, sub_help, , buckett, 323 | temp_point, temp_point[i] = s,); 324 | } 325 | } 326 | 327 | if (swap) { /* Again, make sure sorted array is the vector */ 328 | if (swap_copy) { 329 | memcpy(sub_help, sub_vec, sizeof(int) * size); 330 | } else { 331 | memcpy(sub_vec, sub_help, sizeof(int) * size); 332 | } 333 | } 334 | } 335 | swap = 0; 336 | } 337 | 338 | } else if (bytes_to_sort > 0) { /* Use normal LSB radix (no subarrays) */ 339 | 340 | exp = 0; /* Start at the first byte */ 341 | 342 | max = 1 << ((bytes_to_sort - 1) << 3); 343 | while (MISSING_BITS__) { /* Sort until there are no bytes left */ 344 | if (exp) { 345 | if (swap) { 346 | SORT_BYTE__(helper, vector, >> exp, bucket, 347 | point, point[i] = s,); 348 | } else { 349 | SORT_BYTE__(vector, helper, >> exp, bucket, 350 | point, point[i] = s,); 351 | } 352 | } else { 353 | SORT_BYTE__(vector, helper, , bucket, point, 354 | point[i] = s,); 355 | } 356 | 357 | if (exp == LAST_EXP__) { /* Check if last byte was sorted */ 358 | last_byte_sorted = 1; 359 | } 360 | } 361 | 362 | } 363 | 364 | /* Find the first negative element in the array in binsearch style */ 365 | #define BINSEARCH__(array) \ 366 | int increment = size >> 1; \ 367 | int offset = increment; \ 368 | while((array[offset] ^ array[offset - 1]) >= 0) { \ 369 | increment = (increment > 1) ? increment >> 1 : 1; \ 370 | offset = (array[offset] < 0) ? offset - increment : offset + increment; \ 371 | } 372 | 373 | size = init_size; /* Restore size */ 374 | int* v = vector; /* Temporary values for the vfector and helper arrays */ 375 | int* h = helper; 376 | /* In case the array has both negative and positive integers, find the */ 377 | /* index of the first negative integer and put those numbers in the start */ 378 | if (!last_byte_sorted && (((*v ^ v[size - 1]) < 0 && !swap) || 379 | ((*h ^ h[size - 1]) < 0 && swap))) { 380 | /* If sorted array is in vector, use helper to re-order and vs */ 381 | if (!swap) { 382 | BINSEARCH__(v); 383 | 384 | int tminusoff = size - offset; 385 | if (offset < tminusoff) { 386 | memcpy(h, v, sizeof(int) * offset); 387 | memcpy(v, v + offset, sizeof(int) * tminusoff); 388 | memcpy(v + tminusoff, h, sizeof(int) * offset); 389 | } else { 390 | memcpy(h, v + offset, sizeof(int) * tminusoff); 391 | memmove(v + tminusoff, v, sizeof(int) * offset); 392 | memcpy(v, h, sizeof(int) * tminusoff); 393 | } 394 | } else { 395 | BINSEARCH__(h); 396 | 397 | int tminusoff = size - offset; 398 | memcpy(v, h + offset, sizeof(int) * tminusoff); 399 | memcpy(v + tminusoff, h, sizeof(int) * (size - tminusoff)); 400 | } 401 | } else if (swap) { 402 | memcpy(v, h, sizeof(int) * size); 403 | } 404 | 405 | /* Free helper array */ 406 | free(helper); 407 | 408 | } -------------------------------------------------------------------------------- /week3/zwei_correct.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | 10 | 11 | int n, m, k; 12 | vector a; 13 | 14 | { 15 | ifstream inn("input.txt"); 16 | inn >> n >> m >> k; 17 | a.reserve(m); 18 | for (int i = 0; i < m; ++i) { 19 | std::string buf; 20 | inn >> buf; 21 | a.push_back(buf); 22 | } 23 | } 24 | int *pos = new int[n]; 25 | for (int i = 0; i < n; ++i) { 26 | pos[i] = i; 27 | } 28 | for (int i = 0; i < k; ++i) { 29 | string arr; 30 | int idx = m - i - 1; 31 | for (int j = 0; j < n; ++j) { 32 | arr += a[idx][pos[j]]; 33 | } 34 | int c[26] = {0}; 35 | //std::memset(&c[0], 0, sizeof(int) * 26); 36 | for (int q = 0; q < arr.size(); ++q) { 37 | char b = arr[q]; 38 | c[b - 97]++; 39 | } 40 | for (int q = 1; q < 26; ++q) { 41 | c[q] = c[q] + c[q - 1]; 42 | } 43 | int *newPos = new int[n]; 44 | for (int q = n - 1; q >= 0; q--) { 45 | newPos[c[arr[q] - 97] - 1] = pos[q]; 46 | c[arr[q] - 97]--; 47 | } 48 | for (int q = 0; q < n; ++q) { 49 | pos[q] = newPos[q]; 50 | } 51 | delete[] newPos; 52 | } 53 | 54 | { 55 | ofstream out("output.txt"); 56 | for (int i = 0; i < n; ++i) { 57 | out << pos[i] + 1 << " "; 58 | } 59 | } 60 | delete[] pos; 61 | 62 | return 0; 63 | } -------------------------------------------------------------------------------- /week4/4.1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Реализуйте работу стека. Для каждой операции изъятия элемента выведите ее результат. 3 | 4 | На вход программе подаются строки, содержащие команды. Каждая строка содержит одну команду. Команда — это либо "+ ", 5 | либо "−". Команда "+ " означает добавление в стек числа , по модулю не превышающего . Команда "−" означает изъятие элемента из стека. 6 | Гарантируется, что не происходит извлечения из пустого стека. 7 | Гарантируется, что размер стека в процессе выполнения команд не превысит элементов. 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | int main() { 14 | std::ifstream input("input.txt"); 15 | int n = 0; 16 | input >> n; 17 | std::stack stack; 18 | char sign; 19 | int num; 20 | std::ofstream output("output.txt"); 21 | for (int i = 0; i < n; i++) { 22 | input >> sign; 23 | if (sign == '+') { 24 | input >> num; 25 | stack.push(num); 26 | } 27 | else { 28 | output << stack.top() << std::endl; 29 | stack.pop(); 30 | } 31 | } 32 | output.close(); 33 | input.close(); 34 | } 35 | -------------------------------------------------------------------------------- /week4/4.2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Реализуйте работу очереди. Для каждой операции изъятия элемента выведите ее результат. 3 | 4 | На вход программе подаются строки, содержащие команды. Каждая строка содержит одну команду. Команда — это либо «+ », 5 | либо «−». Команда «+ » означает добавление в очередь числа , по модулю не превышающего . 6 | Команда «−» означает изъятие элемента из очереди. Гарантируется, что размер очереди в процессе выполнения команд не превысит элементов. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | int main() { 13 | std::ifstream input("input.txt"); 14 | int n = 0; 15 | input >> n; 16 | std::queue stack; 17 | char sign; 18 | int num; 19 | std::ofstream output("output.txt"); 20 | for (int i = 0; i < n; i++) { 21 | input >> sign; 22 | if (sign == '+') { 23 | input >> num; 24 | stack.push(num); 25 | } 26 | else { 27 | output << stack.front() << std::endl; 28 | stack.pop(); 29 | } 30 | } 31 | output.close(); 32 | input.close(); 33 | } 34 | -------------------------------------------------------------------------------- /week4/4.3.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Последовательность , состоящую из символов из множества «(», «)», «[» и «]», назовем правильной скобочной 3 | последовательностью, если выполняется одно из следующих утверждений: 4 | 5 | — пустая последовательность; 6 | первый символ последовательности — это «(», и в этой последовательности существует такой символ «)», 7 | что последовательность можно представить как , где и — правильные скобочные последовательности; 8 | первый символ последовательности — это «[», и в этой последовательности существует такой символ «]», 9 | что последовательность можно представить как , где и — правильные скобочные последовательности. 10 | Так, например, последовательности «(())» и «()[]» являются правильными скобочными последовательностями, 11 | а последовательности «[)» и «((» таковыми не являются. 12 | 13 | Входной файл содержит несколько строк, каждая из которых содержит последовательность символов «(», «)», «[» и «]». 14 | Для каждой из этих строк выясните, является ли она правильной скобочной последовательностью. 15 | */ 16 | 17 | #include 18 | #include "edx-io.hpp" 19 | 20 | void clearStack(std::stack &stack) { 21 | while (!stack.empty()) { 22 | stack.pop(); 23 | } 24 | } 25 | 26 | bool checkOnStack(std::stack &stack, char strEl) { 27 | if (stack.empty()) return false; 28 | char okBracket; 29 | 30 | if (strEl == ')') { 31 | okBracket = '('; 32 | } else { 33 | okBracket = '['; 34 | } 35 | 36 | bool correct = false; 37 | if (stack.top() == okBracket) { 38 | correct = true; 39 | } 40 | stack.pop(); 41 | return correct; 42 | } 43 | 44 | int main() { 45 | int n; 46 | io >> n; 47 | std::string sequence; 48 | std::stack stack; 49 | bool correct; 50 | for (int i = 0; i < n; i++) { 51 | io >> sequence; 52 | correct = true; 53 | for (int j = 0; j < sequence.size(); j++) { 54 | if (sequence[j] == '(' || sequence[j] == '[') { 55 | stack.push(sequence[j]); 56 | } else { 57 | correct = checkOnStack(stack, sequence[j]); 58 | if (!correct) { 59 | break; 60 | } 61 | } 62 | } 63 | if (!stack.empty()) { 64 | correct = false; 65 | } 66 | clearStack(stack); 67 | if (correct) { 68 | io << "YES" << '\n'; 69 | } else { 70 | io << "NO" << '\n'; 71 | } 72 | } 73 | return 0; 74 | } -------------------------------------------------------------------------------- /week4/4.4.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Реализуйте работу очереди. В дополнение к стандартным операциям очереди, необходимо также отвечать на запрос 3 | о минимальном элементе из тех, которые сейчас находится в очереди. Для каждой операции запроса минимального элемента 4 | выведите ее результат. 5 | 6 | На вход программе подаются строки, содержащие команды. Каждая строка содержит одну команду. Команда — это либо «+ », 7 | либо «−», либо «?». Команда «+ » означает добавление в очередь числа , по модулю не превышающего . Команда «−» означает 8 | изъятие элемента из очереди. 9 | Команда «?» означает запрос на поиск минимального элемента в очереди. 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include "edx-io.hpp" 15 | #include 16 | 17 | class Stack { 18 | private: 19 | class Element { 20 | public: 21 | int number; 22 | int opResult; 23 | 24 | Element(int el, int opRes) { 25 | number = el; 26 | opResult = opRes; 27 | } 28 | }; 29 | 30 | std::stack stack; 31 | public: 32 | void push(int el) { 33 | if (!stack.empty()) { 34 | stack.push(Element(el, std::min(el, stack.top().opResult))); 35 | } else { 36 | stack.push(Element(el, el)); 37 | } 38 | } 39 | 40 | int pop() { 41 | int num = stack.top().number; 42 | stack.pop(); 43 | return num; 44 | } 45 | 46 | int getMin() { 47 | if (stack.empty()) { 48 | return INT_MAX; 49 | } else { 50 | return stack.top().opResult; 51 | } 52 | } 53 | 54 | bool empty() { 55 | return stack.empty(); 56 | } 57 | }; 58 | 59 | class Queue { 60 | private: 61 | Stack s1; 62 | Stack s2; 63 | public: 64 | void push(int el) { 65 | s1.push(el); 66 | } 67 | int pop() { 68 | if (s2.empty()) { 69 | while(!s1.empty()) { 70 | s2.push(s1.pop()); 71 | } 72 | } 73 | return s2.pop(); 74 | } 75 | 76 | int getMin() { 77 | return std::min(s1.getMin(), s2.getMin()); 78 | } 79 | }; 80 | 81 | int main() { 82 | int n = 0; 83 | io >> n; 84 | Queue deque; 85 | char sign; 86 | int num; 87 | for (int i = 0; i < n; i++) { 88 | io >> sign; 89 | if (sign == '+') { 90 | io >> num; 91 | deque.push(num); 92 | } else if (sign == '-') { 93 | deque.pop(); 94 | } else if (sign == '?') { 95 | io << deque.getMin() << '\n'; 96 | } 97 | } 98 | } 99 | 100 | 101 | -------------------------------------------------------------------------------- /week4/4.5.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Язык Quack — забавный язык, который фигурирует в одной из задач с Internet Problem Solving Contest. В этой задаче вам 3 | требуется написать интерпретатор языка Quack. 4 | 5 | Виртуальная машина, на которой исполняется программа на языке Quack, имеет внутри себя очередь, содержащую целые числа 6 | по модулю 65536 (то есть, числа от 0 до 65535, соответствующие беззнаковому 16-битному целому типу). Слово get в описании 7 | операций означает извлечение из очереди, put — добавление в очередь. Кроме того, у виртуальной машины есть 26 регистров, 8 | которые обозначаются буквами от 'a' до 'z'. Изначально все регистры хранят нулевое значение. В языке Quack существуют 9 | следующие команды (далее под и подразумеваются некие абстрактные временные переменные): 10 | */ 11 | 12 | #include 13 | #include 14 | #include "edx-io.hpp" 15 | #include 16 | #include 17 | #include 18 | 19 | #define MODULE 65536 20 | #define memory_index_convert 97 21 | 22 | int memory_index(char reg) { 23 | return reg - memory_index_convert; 24 | } 25 | 26 | void add_to_queue(std::queue &queue, unsigned short int memory[], char ®) { 27 | queue.push(memory[memory_index(reg)]); 28 | } 29 | 30 | void add_to_memory(std::queue &queue, unsigned short int memory[], char ®) { 31 | memory[memory_index(reg)] = queue.front(); 32 | queue.pop(); 33 | } 34 | 35 | void crprint(unsigned short int memory[], char ®) { 36 | io << (char) (memory[memory_index(reg)] % 256); 37 | } 38 | 39 | void cqprint(std::queue &queue) { 40 | unsigned short int num = queue.front(); 41 | queue.pop(); 42 | io << (char) (num % 256); 43 | } 44 | 45 | void rprint(unsigned short int memory[], char ®) { 46 | io << memory[memory_index(reg)] << '\n'; 47 | } 48 | 49 | void qprint(std::queue &queue) { 50 | unsigned short int num = queue.front(); 51 | queue.pop(); 52 | io << num << '\n'; 53 | } 54 | 55 | void print(std::queue queue) { 56 | std::cout << "Queue: " << std::endl; 57 | while (!queue.empty()) { 58 | std::cout << queue.front() << " "; 59 | queue.pop(); 60 | } 61 | std::cout << std::endl; 62 | } 63 | 64 | void print(unsigned short int memory[]) { 65 | std::cout << "Memory: " << std::endl; 66 | for (int i = 0; i < 26; i++) { 67 | std::cout << (char) (i + memory_index_convert) << ": " << memory[i] << " "; 68 | } 69 | std::cout << std::endl; 70 | } 71 | 72 | void arithmop(std::queue &queue, char &op) { 73 | unsigned short int a = queue.front(); 74 | queue.pop(); 75 | unsigned short int b = queue.front(); 76 | queue.pop(); 77 | switch (op) { 78 | case '+': 79 | queue.push((a + b) % MODULE); 80 | break; 81 | case '-': 82 | queue.push((a - b) % MODULE); 83 | break; 84 | case '*': 85 | queue.push((a * b) % MODULE); 86 | break; 87 | case '/': 88 | if (b == 0) { 89 | queue.push(0); 90 | } else { 91 | queue.push(std::div(a, b).quot); 92 | } 93 | break; 94 | case '%': 95 | if (b == 0) { 96 | queue.push(0); 97 | } else { 98 | queue.push(std::div(a, b).rem); 99 | } 100 | break; 101 | } 102 | } 103 | 104 | int is_numeric(std::string &string) { 105 | int num; 106 | try { 107 | num = std::stoi(string); 108 | } 109 | catch (std::invalid_argument &e) { 110 | return -1; 111 | } 112 | return num; 113 | } 114 | 115 | bool is_arithmop(std::string &op) { 116 | return op == "+" || op == "-" || op == "*" || op == "/" || op == "%"; 117 | } 118 | 119 | void init_memory(unsigned short int memory[]) { 120 | for (int i = 0; i < 26; i++) { 121 | memory[i] = 0; 122 | } 123 | } 124 | 125 | char get_register(std::string &str) { 126 | return str[1]; 127 | } 128 | 129 | std::string get_label(std::string &str, bool clean) { 130 | if (clean) { 131 | return str; 132 | } 133 | return str.substr(1, std::string::npos); 134 | } 135 | 136 | void exec(std::queue &queue, unsigned short int memory[], std::vector &program, 137 | std::map &labels) { 138 | for (int i = 0; i < program.size(); i++) { 139 | if (program[i][0] == 'Q') { 140 | break; 141 | } 142 | 143 | int num = is_numeric(program[i]); 144 | 145 | if (num != -1) { 146 | queue.push(num); 147 | // print(queue); 148 | } else { 149 | if (is_arithmop(program[i])) { 150 | arithmop(queue, program[i][0]); 151 | // print(queue); 152 | } else if (program[i][0] == '>') { 153 | char reg = program[i][1]; 154 | add_to_memory(queue, memory, reg); 155 | // print(memory); 156 | } else if (program[i][0] == '<') { 157 | char reg = program[i][1]; 158 | add_to_queue(queue, memory, reg); 159 | // print(queue); 160 | } else if (program[i][0] == 'P') { 161 | if (program[i].length() == 2) { 162 | rprint(memory, program[i][1]); 163 | } else { 164 | qprint(queue); 165 | } 166 | } else if (program[i][0] == 'C') { 167 | if (program[i].length() == 2) { 168 | crprint(memory, program[i][1]); 169 | } else { 170 | cqprint(queue); 171 | } 172 | } else if (program[i][0] == 'J') { 173 | std::string label = get_label(program[i], false); 174 | // std::cout << labels.find(label)->second << std::endl; 175 | i = labels.find(label)->second; 176 | } else if (program[i][0] == 'Z') { 177 | char reg = program[i][1]; 178 | if (memory[memory_index(reg)] == 0) { 179 | std::string label = program[i].substr(2, std::string::npos); 180 | i = labels.find(label)->second; 181 | } 182 | } else if (program[i][0] == 'E') { 183 | char reg1 = program[i][1]; 184 | char reg2 = program[i][2]; 185 | if (memory[memory_index(reg1)] == memory[memory_index(reg2)]) { 186 | std::string label = program[i].substr(3, std::string::npos); 187 | i = labels.find(label)->second; 188 | } 189 | } else if (program[i][0] == 'G') { 190 | char reg1 = program[i][1]; 191 | char reg2 = program[i][2]; 192 | // print(memory); 193 | // std::cout << memory[memory_index(reg1)] << " " << memory[memory_index(reg2)] << std::endl; 194 | // std::cout << (memory[memory_index(reg1)] > memory[memory_index(reg2)]) << std::endl; 195 | if (memory[memory_index(reg1)] > memory[memory_index(reg2)]) { 196 | std::string label = program[i].substr(3, std::string::npos); 197 | i = labels.find(label)->second; 198 | } 199 | } 200 | } 201 | } 202 | } 203 | 204 | int main() { 205 | std::queue queue; 206 | std::string input; 207 | unsigned short int memory[26]; 208 | init_memory(memory); 209 | std::vector program; 210 | std::map labels; 211 | int count = 0; 212 | while (true) { 213 | io >> input; 214 | if (input.empty()) { 215 | break; 216 | } 217 | if (input[0] == ':') { 218 | labels.insert(make_pair(input.substr(1, std::string::npos), count)); 219 | } 220 | program.push_back(input); 221 | count++; 222 | } 223 | exec(queue, memory, program, labels); 224 | // for (auto el: labels) { 225 | // std::cout << el.first << " " << el.second << std::endl; 226 | // } 227 | return 0; 228 | } 229 | -------------------------------------------------------------------------------- /week5/5.1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Структуру данных «куча», или, более конкретно, «неубывающая пирамида», можно реализовать на основе массива. 3 | 4 | Для этого должно выполнятся основное свойство неубывающей пирамиды, которое заключается в том, что для каждого выполняются условия: 5 | 6 | если , то ; 7 | если , то . 8 | Дан массив целых чисел. Определите, является ли он неубывающей пирамидой. 9 | */ 10 | 11 | #include 12 | #include "edx-io.hpp" 13 | 14 | int main() { 15 | int num; 16 | io >> num; 17 | int *array = new int[num]; 18 | for (int i = 0; i < num; i++) { 19 | io >> array[i]; 20 | // std::cout << array[i] << " "; 21 | } 22 | // bool correct = isHeap(array, 0, num); 23 | bool correct = true; 24 | for (int i = 0; i < (num / 2) - 1; i++) { 25 | if (2 * i + 1 <= num && array[i] <= array[2 * i + 1]) { 26 | } else { 27 | correct = false; 28 | break; 29 | } 30 | if (2 * i + 2 <= num && array[i] <= array[2 * i + 2]) { 31 | 32 | } else { 33 | correct = false; 34 | break; 35 | } 36 | } 37 | if (correct) { 38 | io << "YES"; 39 | } else { 40 | io << "NO"; 41 | } 42 | delete[] array; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /week5/eins.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main() { 6 | uint32_t n; 7 | std::vector target; 8 | { 9 | std::ifstream inp("input.txt"); 10 | inp >> n; 11 | target.resize(n, 0); 12 | for (uint32_t i = 0; i < n; i++) 13 | inp >> target[i]; 14 | } 15 | 16 | std::string answer = "YES"; 17 | 18 | for (uint32_t i = 1; i <= n / 2 + 1; i++) { 19 | if (2 * i <= n) { 20 | if (target[i - 1] > target[(2 * i) - 1]) { 21 | answer = "NO"; 22 | break; 23 | } 24 | } 25 | if (2 * i + 1 <= n) { 26 | if (target[i - 1] > target[2 * i]) { 27 | answer = "NO"; 28 | break; 29 | } 30 | } 31 | } 32 | 33 | 34 | { 35 | std::ofstream outp("output.txt"); 36 | outp << answer; 37 | } 38 | 39 | return 0; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /week5/zwei.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 11.03.2020. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | uint32_t n; 11 | std::multiset target; 12 | std::vector history; 13 | 14 | std::ifstream inp("input.txt"); 15 | std::ofstream outp("output.txt"); 16 | inp >> n; 17 | 18 | history.reserve(n); 19 | 20 | for (uint32_t i = 0; i < n; i++) { 21 | char cmd = 0; 22 | int32_t value = 0; 23 | 24 | inp >> cmd; 25 | if (cmd == 'A') { 26 | inp >> value; 27 | target.insert(value); 28 | } else if (cmd == 'X') { 29 | if (target.empty()) 30 | outp << "*\n"; 31 | else { 32 | outp << *target.begin() << "\n"; 33 | target.erase(target.begin()); 34 | } 35 | } else if (cmd == 'D') { 36 | int32_t ind; 37 | inp >> ind; 38 | auto buf = history[ind - 1]; 39 | target.erase(target.find(buf)); 40 | inp >> value; 41 | target.insert(value); 42 | history[ind - 1] = value; 43 | } 44 | 45 | history.push_back(value); 46 | } 47 | 48 | return 0; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /week6/6.1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Дан массив из элементов, упорядоченный в порядке неубывания, и запросов: найти первое и последнее вхождение некоторого числа в массив. 3 | Требуется ответить на эти запросы. 4 | */ 5 | 6 | #include 7 | #include "edx-io.hpp" 8 | 9 | const int *bin_search(int const *array, int size, int key) { 10 | int left = 0; 11 | int right = size - 1; 12 | int firstIndex = -1; 13 | while (left <= right) { 14 | int mid = (left + right) / 2; 15 | if (array[mid] > key) { 16 | right = mid - 1; 17 | } else if (array[mid] < key) { 18 | left = mid + 1; 19 | } else if (array[mid] == key) { 20 | firstIndex = mid; 21 | break; 22 | } 23 | } 24 | int *const answer = new int[2]; 25 | answer[0] = -1; 26 | answer[1] = -1; 27 | if (firstIndex == -1) 28 | return answer; 29 | else { 30 | int i = firstIndex; 31 | while (array[i] == array[firstIndex]) { 32 | i += 1; 33 | } 34 | answer[1] = i; 35 | i = firstIndex; 36 | while (array[i] == array[firstIndex]) { 37 | i -= 1; 38 | } 39 | answer[0] = i + 2; 40 | // std::cout << i << std::endl; 41 | return answer; 42 | } 43 | } 44 | 45 | int main() { 46 | int arraySize, requestsCount; 47 | io >> arraySize; 48 | int *array = new int[arraySize]; 49 | for (int i = 0; i < arraySize; i++) { 50 | io >> array[i]; 51 | } 52 | io >> requestsCount; 53 | int *requests = new int[requestsCount]; 54 | for (int i = 0; i < requestsCount; i++) { 55 | io >> requests[i]; 56 | } 57 | for (int i = 0; i < requestsCount; i++) { 58 | int const *answer = bin_search(array, arraySize, requests[i]); 59 | io << answer[0] << " " << answer[1] << '\n'; 60 | delete[] answer; 61 | } 62 | delete[] requests; 63 | delete[] array; 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /week6/6.2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Гирлянда состоит из лампочек на общем проводе. Один её конец закреплён на заданной высоте мм (). 3 | Благодаря силе тяжести гирлянда прогибается: высота каждой неконцевой лампы на 1 мм меньше, чем средняя высота ближайших соседей ( для ). 4 | 5 | Требуется найти минимальное значение высоты второго конца (), такое что для любого при высоте второго конца для всех лампочек выполняется условие . 6 | Обратите внимание на то, что при данном значении высоты либо ровно одна, либо две соседних лампочки будут иметь нулевую высоту. 7 | 8 | Подсказка: для решения этой задачи можно использовать двоичный поиск (метод дихотомии). 9 | */ 10 | #include 11 | #include "edx-io.hpp" 12 | 13 | void print(double* h, int n) { 14 | for (int i = 0; i < n; i++) { 15 | std::cout << h[i] << " "; 16 | } 17 | std::cout << std::endl; 18 | } 19 | 20 | double height(double* const h, int n) { 21 | double l = 0; 22 | double r = h[0]; 23 | double epsilon = 10e-12; 24 | bool pos; 25 | while (r - l > epsilon) { 26 | h[1] = (l + r) / 2; 27 | pos = true; 28 | for (int i = 2; i < n; i++) { 29 | h[i] = 2 * h[i - 1] - h[i - 2] + 2; 30 | if (h[i] < 0) { 31 | pos = false; 32 | break; 33 | } 34 | } 35 | if (pos) { 36 | r = h[1]; 37 | } else { 38 | l = h[1]; 39 | } 40 | } 41 | return h[n - 1]; 42 | } 43 | 44 | int main() { 45 | int n; 46 | io >> n; 47 | auto* h = new double[n]; 48 | io >> h[0]; 49 | io << height(h, n); 50 | delete[] h; 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /week6/6.3.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Дано двоичное дерево поиска. В вершинах этого дерева записаны ключи — целые числа, по модулю не превышающие . 3 | Для каждой вершины дерева выполняется следующее условие: 4 | 5 | все ключи вершин из левого поддерева меньше ключа вершины ; 6 | все ключи вершин из правого поддерева больше ключа вершины . 7 | Найдите высоту данного дерева. 8 | */ 9 | 10 | #include 11 | #include "edx-io.hpp" 12 | 13 | #define LEFT_CHILD 1 14 | #define RIGHT_CHILD 2 15 | #define debugPrint(x) std::cout << x << std::endl; 16 | 17 | void print(int **, int); 18 | 19 | int countHeight(int **, int, int); 20 | 21 | int countLeftSubtree(int **, int, int); 22 | 23 | int countRightSubtree(int **, int, int); 24 | 25 | int main() { 26 | int n; 27 | io >> n; 28 | if (n == 0) { 29 | io << 0; 30 | return 0; 31 | } 32 | int **tree; 33 | tree = new int *[n]; 34 | for (int i = 0; i < n; i++) { 35 | tree[i] = new int[3]; 36 | for (int j = 0; j < 3; j++) { 37 | io >> tree[i][j]; 38 | if (j != 0) 39 | tree[i][j] -= 1; 40 | } 41 | } 42 | 43 | // print(tree, n); 44 | // debugPrint(countHeight(tree, 0, 0)); 45 | io << countHeight(tree, 0, 0); 46 | for (int i = 0; i < n; i++) { 47 | delete [] tree[i]; 48 | } 49 | delete [] tree; 50 | return 0; 51 | } 52 | 53 | void print(int **tree, int n) { 54 | for (int i = 0; i < n; i++) { 55 | for (int j = 0; j < 3; j++) { 56 | std::cout << tree[i][j] << " "; 57 | } 58 | std::cout << std::endl; 59 | } 60 | } 61 | 62 | int countHeight(int **tree, int node, int height) { 63 | int leftSubtreeHeight = countLeftSubtree(tree, node, height); 64 | int rightSubtreeHeight = countRightSubtree(tree, node, height); 65 | return leftSubtreeHeight > rightSubtreeHeight ? leftSubtreeHeight : rightSubtreeHeight; 66 | } 67 | 68 | int countLeftSubtree(int **tree, int node, int height) { 69 | height += 1; 70 | if (tree[node][LEFT_CHILD] == -1) { 71 | return height; 72 | } else { 73 | return countHeight(tree, tree[node][LEFT_CHILD], height); 74 | } 75 | } 76 | 77 | int countRightSubtree(int **tree, int node, int height) { 78 | height += 1; 79 | if (tree[node][RIGHT_CHILD] == -1) { 80 | return height; 81 | } else { 82 | return countHeight(tree, tree[node][RIGHT_CHILD], height); 83 | } 84 | } -------------------------------------------------------------------------------- /week6/6.4.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Дано некоторое двоичное дерево поиска. Также даны запросы на удаление из него вершин, имеющих заданные ключи, 3 | причем вершины удаляются целиком вместе со своими поддеревьями. 4 | 5 | После каждого запроса на удаление выведите число оставшихся вершин в дереве. 6 | */ 7 | 8 | #include "edx-io.hpp" 9 | 10 | unsigned countCildrenAndPlaceParent(int**, int, int); 11 | unsigned findValue(int**, int, int); 12 | void wipeSubtree(int**, int); 13 | void decreaseNumberOfChildren(int**, int, int); 14 | 15 | int main(){ 16 | int length; 17 | int wipes; 18 | int numberOfNodes; 19 | 20 | io >> length; 21 | numberOfNodes = length; 22 | 23 | int **tree = new int* [length + 1]; 24 | 25 | for (int i = 1; i <= length; i++){ 26 | tree[i] = new int[3]; 27 | io >> tree[i][0] >> tree[i][1] >> tree[i][2]; 28 | tree[i][3] = 0; 29 | tree[i][4] = 0; 30 | } 31 | 32 | countCildrenAndPlaceParent(tree, 1, 0); 33 | 34 | io >> wipes; 35 | 36 | for (int i = 0; i < wipes; i++){ 37 | int index = 1; 38 | int key; 39 | io >> key; 40 | 41 | index = findValue(tree, key, 1); 42 | 43 | if (index != 0){ 44 | decreaseNumberOfChildren(tree, index, tree[index][4]); 45 | wipeSubtree(tree, index); 46 | } 47 | io << tree[1][4] << '\n'; 48 | } 49 | } 50 | 51 | 52 | unsigned countCildrenAndPlaceParent(int** tree, int index, int parent){ 53 | unsigned numberOfChildren = 1; 54 | int leftChild = tree[index][1]; 55 | int rightChild = tree[index][2]; 56 | 57 | tree[index][3] = parent; 58 | 59 | if (leftChild > 0){ 60 | numberOfChildren += countCildrenAndPlaceParent(tree, leftChild, index); 61 | } 62 | if (rightChild > 0){ 63 | numberOfChildren += countCildrenAndPlaceParent(tree, rightChild, index); 64 | } 65 | 66 | tree[index][4] = numberOfChildren; 67 | return numberOfChildren; 68 | } 69 | 70 | unsigned findValue(int** tree, int value, int index){ 71 | int indexValue = tree[index][0]; 72 | if (indexValue == value){ 73 | return index; 74 | } else if (indexValue > value){ 75 | if (tree[index][1] == 0){ 76 | return 0; 77 | } 78 | return findValue(tree, value, tree[index][1]); 79 | 80 | } else { 81 | if (tree[index][2] == 0){ 82 | return 0; 83 | } 84 | return findValue(tree, value, tree[index][2]); 85 | } 86 | } 87 | 88 | void wipeSubtree(int** tree, int index){ 89 | int left = tree[index][1]; 90 | int right = tree[index][2]; 91 | tree[index][3] = 0; 92 | if (left != 0){ 93 | wipeSubtree(tree, left); 94 | } 95 | if (right != 0){ 96 | wipeSubtree(tree, right); 97 | } 98 | } 99 | 100 | void decreaseNumberOfChildren(int** tree, int index, int number){ 101 | tree[index][4] -= number; 102 | int parent = tree[index][3]; 103 | if (parent != 0){ 104 | decreaseNumberOfChildren(tree, parent, number); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /week7/1.7.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 16.03.2020. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | struct TreeNode { 9 | int32_t value = 0; 10 | uint32_t l_number = 0; 11 | uint32_t r_number = 0; 12 | uint32_t unter_size = 0; 13 | }; 14 | 15 | using DasTree = std::vector; 16 | 17 | uint32_t get_tree_height(DasTree &tree, uint32_t initial = 0) { 18 | uint32_t lv = 0, rv = 0; 19 | if (tree[initial].unter_size) 20 | return tree[initial].unter_size; 21 | 22 | if (tree[initial].l_number) 23 | lv = get_tree_height(tree, tree[initial].l_number - 1); 24 | if (tree[initial].r_number) 25 | rv = get_tree_height(tree, tree[initial].r_number - 1); 26 | 27 | tree[initial].unter_size = std::max(lv, rv) + 1; 28 | return tree[initial].unter_size; 29 | } 30 | 31 | int32_t get_tree_balance(const DasTree &tree, uint32_t initial = 0) { 32 | uint32_t lv = 0, rv = 0; 33 | 34 | if (tree[initial].l_number) 35 | lv = tree[tree[initial].l_number - 1].unter_size; 36 | if (tree[initial].r_number) 37 | rv = tree[tree[initial].r_number - 1].unter_size; 38 | 39 | return rv - lv; 40 | } 41 | 42 | void fill_sizes(DasTree &tree) { 43 | for (uint32_t i = tree.size() - 1; i > 0; i--) 44 | tree[i].unter_size = get_tree_height(tree, i); 45 | } 46 | 47 | int main() { 48 | DasTree das_tree; 49 | uint32_t n; 50 | 51 | { 52 | std::ifstream inp("input.txt"); 53 | inp >> n; 54 | das_tree.reserve(n); 55 | for (uint32_t i = 0; i < n; i++) { 56 | TreeNode buffer = {}; 57 | inp >> buffer.value >> buffer.l_number >> buffer.r_number; 58 | das_tree.push_back(buffer); 59 | } 60 | } 61 | 62 | fill_sizes(das_tree); 63 | 64 | { 65 | std::ofstream outp("output.txt"); 66 | for (uint32_t i = 0; i < n; i++) 67 | outp << get_tree_balance(das_tree, i) << "\n"; 68 | } 69 | 70 | return 0; 71 | } -------------------------------------------------------------------------------- /week7/2.7.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 16.03.2020. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | struct node // структура для представления узлов дерева 9 | { 10 | int key; 11 | uint32_t height; 12 | node *left; 13 | node *right; 14 | 15 | explicit node(int k) { 16 | key = k; 17 | left = right = nullptr; 18 | height = 1; 19 | } 20 | }; 21 | 22 | unsigned char height(node *p) { 23 | return p ? p->height : 0; 24 | } 25 | 26 | int bfactor(node *p) { 27 | return height(p->right) - height(p->left); 28 | } 29 | 30 | void fixheight(node *p) { 31 | unsigned char hl = height(p->left); 32 | unsigned char hr = height(p->right); 33 | p->height = (hl > hr ? hl : hr) + 1; 34 | } 35 | 36 | uint32_t fixheight_recursive(node *p) { 37 | uint32_t hl = 0, hr = 0; 38 | if (p->left) 39 | hl = fixheight_recursive(p->left); 40 | if (p->right) 41 | hr = fixheight_recursive(p->right); 42 | 43 | p->height = (hl > hr ? hl : hr) + 1; 44 | return p->height; 45 | } 46 | 47 | node *rotateright(node *p) // правый поворот вокруг p 48 | { 49 | node *q = p->left; 50 | p->left = q->right; 51 | q->right = p; 52 | fixheight(p); 53 | fixheight(q); 54 | return q; 55 | } 56 | 57 | node *rotateleft(node *q) // левый поворот вокруг q 58 | { 59 | node *p = q->right; 60 | q->right = p->left; 61 | p->left = q; 62 | fixheight(q); 63 | fixheight(p); 64 | return p; 65 | } 66 | 67 | node *auto_rotate_left(node *p) { 68 | node * q; 69 | if (p->right && bfactor(p->right) == -1) { 70 | p->right = rotateright(p->right); 71 | q = rotateleft(p); 72 | } else { 73 | q = rotateleft(p); 74 | } 75 | return q; 76 | } 77 | 78 | 79 | node *balance(node *p) // балансировка узла p 80 | { 81 | fixheight(p); 82 | if (bfactor(p) == 2) { 83 | if (bfactor(p->right) < 0) 84 | p->right = rotateright(p->right); 85 | return rotateleft(p); 86 | } 87 | if (bfactor(p) == -2) { 88 | if (bfactor(p->left) > 0) 89 | p->left = rotateleft(p->left); 90 | return rotateright(p); 91 | } 92 | return p; // балансировка не нужна 93 | } 94 | 95 | 96 | node *insert(node *p, int k) // вставка ключа k в дерево с корнем p 97 | { 98 | if (!p) return new node(k); 99 | if (k < p->key) 100 | p->left = insert(p->left, k); 101 | else 102 | p->right = insert(p->right, k); 103 | return balance(p); 104 | } 105 | 106 | node *findmin(node *p) // поиск узла с минимальным ключом в дереве p 107 | { 108 | return p->left ? findmin(p->left) : p; 109 | } 110 | 111 | node *removemin(node *p) // удаление узла с минимальным ключом из дерева p 112 | { 113 | if (p->left == nullptr) 114 | return p->right; 115 | p->left = removemin(p->left); 116 | return balance(p); 117 | } 118 | 119 | node *remove(node *p, int k) // удаление ключа k из дерева p 120 | { 121 | if (!p) return nullptr; 122 | if (k < p->key) 123 | p->left = remove(p->left, k); 124 | else if (k > p->key) 125 | p->right = remove(p->right, k); 126 | else // k == p->key 127 | { 128 | node *q = p->left; 129 | node *r = p->right; 130 | delete p; 131 | if (!r) return q; 132 | node *min = findmin(r); 133 | min->right = removemin(r); 134 | min->left = q; 135 | return balance(min); 136 | } 137 | return balance(p); 138 | } 139 | 140 | struct TreeNode { 141 | int32_t value = 0; 142 | uint32_t l_number = 0; 143 | uint32_t r_number = 0; 144 | }; 145 | 146 | using DasTree = std::vector; 147 | 148 | 149 | node *create_avl_tree(const DasTree &tree, uint32_t initial = 0) { 150 | auto proot = new node(tree[initial].value); 151 | 152 | if (tree[initial].l_number) 153 | proot->left = create_avl_tree(tree, tree[initial].l_number - 1); 154 | if (tree[initial].r_number) 155 | proot->right = create_avl_tree(tree, tree[initial].r_number - 1); 156 | 157 | return proot; 158 | } 159 | 160 | 161 | uint32_t push_to_das_tree(DasTree &tree, node *p_root) { 162 | tree.push_back({p_root->key, 0, 0}); 163 | auto ind = tree.size(); 164 | if (p_root->right) 165 | tree[ind - 1].r_number = push_to_das_tree(tree, p_root->right); 166 | if (p_root->left) 167 | tree[ind - 1].l_number = push_to_das_tree(tree, p_root->left); 168 | 169 | return ind; 170 | } 171 | 172 | void create_das_tree(node *p_root, DasTree &target) { 173 | push_to_das_tree(target, p_root); 174 | } 175 | 176 | 177 | int main() { 178 | DasTree das_tree; 179 | uint32_t n; 180 | 181 | { 182 | std::ifstream inp("input.txt"); 183 | inp >> n; 184 | das_tree.reserve(n); 185 | for (uint32_t i = 0; i < n; i++) { 186 | TreeNode buffer = {}; 187 | inp >> buffer.value >> buffer.l_number >> buffer.r_number; 188 | das_tree.push_back(buffer); 189 | } 190 | } 191 | 192 | auto avl_tree_root = create_avl_tree(das_tree); 193 | fixheight_recursive(avl_tree_root); 194 | avl_tree_root = auto_rotate_left(avl_tree_root); 195 | DasTree das_rotated; 196 | das_rotated.reserve(n); 197 | create_das_tree(avl_tree_root, das_rotated); 198 | 199 | { 200 | std::ofstream outp("output.txt"); 201 | outp << das_rotated.size() << "\n"; 202 | for (auto x : das_rotated) 203 | outp << x.value << " " << x.l_number << " " << x.r_number << "\n"; 204 | } 205 | 206 | return 0; 207 | } -------------------------------------------------------------------------------- /week7/2_2.7.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 17.03.2020. 3 | // 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | enum Side {right=0, left=1}; 12 | 13 | struct Input_Node 14 | { 15 | int key; 16 | int children[2]; 17 | 18 | Input_Node(int key, int left, int right) : key(key) 19 | { 20 | children[0] = left; 21 | children[1] = right; 22 | } 23 | }; 24 | 25 | struct Node 26 | { 27 | int key; 28 | int height; 29 | int inp_num; 30 | Node* children[2]; 31 | 32 | Node(int key, Node * left, Node * right, int num) : key(key), height(0), inp_num(num) 33 | { 34 | children[0] = left; 35 | children[1] = right; 36 | } 37 | 38 | Node(Input_Node * node, int num) : height(0), key(node->key), inp_num(num) 39 | { 40 | children[0] = children[1] = nullptr; 41 | } 42 | }; 43 | 44 | struct AVL_Tree 45 | { 46 | std::vector input_tree; 47 | std::vector output_tree; 48 | Node * root = nullptr; 49 | 50 | void make_tree() 51 | { 52 | root = new Node(input_tree[0], 0); 53 | dfs_make(root); 54 | } 55 | 56 | void dfs_make(Node * v) 57 | { 58 | for (int i = 0; i < 2; i++) 59 | { 60 | if (input_tree[v->inp_num]->children[i] == -1) 61 | { 62 | v->children[i] = nullptr; 63 | } 64 | else 65 | { 66 | v->children[i] = 67 | new Node(input_tree[input_tree[v->inp_num]->children[i]], input_tree[v->inp_num]->children[i]); 68 | dfs_make(v->children[i]); 69 | } 70 | } 71 | } 72 | 73 | int count_balance(Node * v) 74 | { 75 | return (v->children[1] != nullptr ? v->children[1]->height : 0) - 76 | (v->children[0] != nullptr ? v->children[0]->height : 0); 77 | } 78 | 79 | void count_height() 80 | { 81 | if (input_tree.empty()) 82 | { 83 | return ; 84 | } 85 | 86 | dfs(root); 87 | } 88 | 89 | void fix_height(Node * v) 90 | { 91 | v->height = std::max(height_left(v), height_right(v)) + 1; 92 | } 93 | 94 | int height_right(Node * v) 95 | { 96 | return v->children[1] == nullptr ? 0 : v->children[1]->height; 97 | } 98 | 99 | int height_left(Node * v) 100 | { 101 | return v->children[0] == nullptr ? 0 : v->children[0]->height; 102 | } 103 | 104 | void dfs(Node * v) 105 | { 106 | for (auto child : v->children) 107 | { 108 | if (child != nullptr) 109 | { 110 | dfs(child); 111 | } 112 | } 113 | fix_height(v); 114 | } 115 | 116 | Node * rotate(Node * v, int side) 117 | { 118 | Node * u = v->children[side == Side::left ? 1 : 0]; 119 | v->children[side == Side::left ? 1 : 0] = u->children[side == Side::left ? 0 : 1]; 120 | u->children[side == Side::left ? 0 : 1] = v; 121 | fix_height(v); 122 | fix_height(u); 123 | return u; 124 | } 125 | 126 | Node * balance(Node * v) 127 | { 128 | if (count_balance(v->children[1]) < 0) 129 | { 130 | v->children[1] = rotate(v->children[1], Side::right); 131 | } 132 | return rotate(v, Side::left); 133 | } 134 | 135 | void make_output_tree() 136 | { 137 | std::queue queue; 138 | queue.push(root); 139 | int num = 1; 140 | while (!queue.empty()) 141 | { 142 | Node * v = queue.front(); 143 | queue.pop(); 144 | int children_num[2] = {0, 0}; 145 | for (int i = 0; i < 2; i++) 146 | { 147 | if (v->children[i] != nullptr) 148 | { 149 | queue.push(v->children[i]); 150 | children_num[i] = ++num; 151 | } 152 | } 153 | output_tree.push_back(new Input_Node(v->key, children_num[0], children_num[1])); 154 | } 155 | } 156 | }; 157 | 158 | int main() 159 | { 160 | std::ifstream in("input.txt"); 161 | std::ofstream out("output.txt"); 162 | 163 | size_t n; 164 | in >> n; 165 | auto avl = new AVL_Tree(); 166 | 167 | for (int i = 0; i < n; i++) 168 | { 169 | int key; 170 | int left, right; 171 | in >> key >> left >> right; 172 | avl->input_tree.push_back(new Input_Node(key, left-1, right-1)); 173 | } 174 | 175 | avl->make_tree(); 176 | 177 | avl->count_height(); 178 | avl->root = avl->balance(avl->root); 179 | 180 | avl->make_output_tree(); 181 | 182 | out << n << std::endl; 183 | for (auto v : avl->output_tree) 184 | { 185 | out << v->key << " " << v->children[0] << " " << v->children[1] << std::endl; 186 | } 187 | } -------------------------------------------------------------------------------- /week7/3.7.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 17.03.2020. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | enum Side {right=0, left=1}; 11 | 12 | struct Input_Node 13 | { 14 | int key; 15 | int children[2]; 16 | 17 | Input_Node(int key, int left, int right) : key(key) 18 | { 19 | children[0] = left; 20 | children[1] = right; 21 | } 22 | }; 23 | 24 | struct Node 25 | { 26 | int key; 27 | int height; 28 | int inp_num; 29 | Node* children[2]; 30 | 31 | Node(int key, Node * left, Node * right, int num) : key(key), height(1), inp_num(num) 32 | { 33 | children[0] = left; 34 | children[1] = right; 35 | } 36 | 37 | Node(Input_Node * node, int num) : height(1), key(node->key), inp_num(num) 38 | { 39 | children[0] = children[1] = nullptr; 40 | } 41 | }; 42 | 43 | struct AVL_Tree 44 | { 45 | std::vector input_tree; 46 | std::vector output_tree; 47 | Node * root = nullptr; 48 | 49 | void make_tree() 50 | { 51 | root = new Node(input_tree[0], 0); 52 | dfs_make(root); 53 | } 54 | 55 | void dfs_make(Node * v) 56 | { 57 | for (int i = 0; i < 2; i++) 58 | { 59 | if (input_tree[v->inp_num]->children[i] == -1) 60 | { 61 | v->children[i] = nullptr; 62 | } 63 | else 64 | { 65 | v->children[i] = 66 | new Node(input_tree[input_tree[v->inp_num]->children[i]], input_tree[v->inp_num]->children[i]); 67 | dfs_make(v->children[i]); 68 | } 69 | } 70 | } 71 | 72 | int count_balance(Node * v) 73 | { 74 | return (v->children[1] != nullptr ? v->children[1]->height : 0) - 75 | (v->children[0] != nullptr ? v->children[0]->height : 0); 76 | } 77 | 78 | void count_height() 79 | { 80 | if (input_tree.empty()) 81 | { 82 | return ; 83 | } 84 | 85 | dfs(root); 86 | } 87 | 88 | void fix_height(Node * v) 89 | { 90 | v->height = std::max(height_left(v), height_right(v)) + 1; 91 | } 92 | 93 | int height_right(Node * v) 94 | { 95 | return v->children[1] == nullptr ? 0 : v->children[1]->height; 96 | } 97 | 98 | int height_left(Node * v) 99 | { 100 | return v->children[0] == nullptr ? 0 : v->children[0]->height; 101 | } 102 | 103 | void dfs(Node * v) 104 | { 105 | for (auto child : v->children) 106 | { 107 | if (child != nullptr) 108 | { 109 | dfs(child); 110 | } 111 | } 112 | fix_height(v); 113 | } 114 | 115 | Node * rotate(Node * v, int side) 116 | { 117 | Node * u = v->children[side == Side::left ? 1 : 0]; 118 | v->children[side == Side::left ? 1 : 0] = u->children[side == Side::left ? 0 : 1]; 119 | u->children[side == Side::left ? 0 : 1] = v; 120 | fix_height(v); 121 | fix_height(u); 122 | return u; 123 | } 124 | 125 | Node * balance(Node * v) 126 | { 127 | fix_height(v); 128 | if (count_balance(v) > 1) 129 | { 130 | 131 | if (count_balance(v->children[1]) < 0) 132 | { 133 | v->children[1] = rotate(v->children[1], Side::right); 134 | } 135 | return rotate(v, Side::left); 136 | } 137 | if (count_balance(v) < -1) 138 | { 139 | if (count_balance(v->children[0]) > 0) 140 | { 141 | v->children[0] = rotate(v->children[0], Side::left); 142 | } 143 | return rotate(v, Side::right); 144 | } 145 | return v; 146 | } 147 | 148 | void make_output_tree() 149 | { 150 | std::queue queue; 151 | queue.push(root); 152 | int num = 1; 153 | while (!queue.empty()) 154 | { 155 | Node * v = queue.front(); 156 | queue.pop(); 157 | int children_num[2] = {0, 0}; 158 | for (int i = 0; i < 2; i++) 159 | { 160 | if (v->children[i] != nullptr) 161 | { 162 | queue.push(v->children[i]); 163 | children_num[i] = ++num; 164 | } 165 | } 166 | output_tree.push_back(new Input_Node(v->key, children_num[0], children_num[1])); 167 | } 168 | } 169 | 170 | Node * insert(Node * root, int key) 171 | { 172 | if (root == nullptr) 173 | { 174 | return new Node(key, nullptr, nullptr, static_cast(input_tree.size()+1)); 175 | } 176 | root->children[key < root->key ? 0 : 1] = insert(root->children[key < root->key ? 0 : 1], key); 177 | return balance(root); 178 | } 179 | }; 180 | 181 | int main() 182 | { 183 | std::ifstream in("input.txt"); 184 | std::ofstream out("output.txt"); 185 | 186 | size_t n; 187 | in >> n; 188 | auto avl = new AVL_Tree(); 189 | 190 | for (int i = 0; i < n; i++) 191 | { 192 | int key; 193 | int left, right; 194 | in >> key >> left >> right; 195 | avl->input_tree.push_back(new Input_Node(key, left-1, right-1)); 196 | } 197 | 198 | int key; 199 | in >> key; 200 | 201 | if (n == 0) 202 | { 203 | out << 1 << "\n" << key << " " << 0 << " " << 0 << std::endl; 204 | return 0; 205 | } 206 | 207 | avl->make_tree(); 208 | avl->count_height(); 209 | avl->root = avl->insert(avl->root, key); 210 | avl->make_output_tree(); 211 | 212 | out << n + 1 << std::endl; 213 | for (auto v : avl->output_tree) 214 | { 215 | out << v->key << " " << v->children[0] << " " << v->children[1] << std::endl; 216 | } 217 | } -------------------------------------------------------------------------------- /week7/4.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 17.03.2020. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | enum Side {right=0, left=1}; 11 | 12 | struct Input_Node 13 | { 14 | int key; 15 | int children[2]; 16 | 17 | Input_Node(int key, int left, int right) : key(key) 18 | { 19 | children[0] = left; 20 | children[1] = right; 21 | } 22 | }; 23 | 24 | struct Node 25 | { 26 | int key; 27 | int height; 28 | int inp_num; 29 | Node* children[2]; 30 | 31 | Node(int key, Node * left, Node * right, int num) : key(key), height(1), inp_num(num) 32 | { 33 | children[0] = left; 34 | children[1] = right; 35 | } 36 | 37 | Node(Input_Node * node, int num) : height(1), key(node->key), inp_num(num) 38 | { 39 | children[0] = children[1] = nullptr; 40 | } 41 | }; 42 | 43 | struct AVL_Tree 44 | { 45 | std::vector input_tree; 46 | std::vector output_tree; 47 | Node * root = nullptr; 48 | 49 | void make_tree() 50 | { 51 | root = new Node(input_tree[0], 0); 52 | dfs_make(root); 53 | } 54 | 55 | void dfs_make(Node * v) 56 | { 57 | for (int i = 0; i < 2; i++) 58 | { 59 | if (input_tree[v->inp_num]->children[i] == -1) 60 | { 61 | v->children[i] = nullptr; 62 | } 63 | else 64 | { 65 | v->children[i] = 66 | new Node(input_tree[input_tree[v->inp_num]->children[i]], input_tree[v->inp_num]->children[i]); 67 | dfs_make(v->children[i]); 68 | } 69 | } 70 | } 71 | 72 | int count_balance(Node * v) 73 | { 74 | return (v->children[1] != nullptr ? v->children[1]->height : 0) - 75 | (v->children[0] != nullptr ? v->children[0]->height : 0); 76 | } 77 | 78 | void count_height() 79 | { 80 | if (input_tree.empty()) 81 | { 82 | return ; 83 | } 84 | 85 | dfs(root); 86 | } 87 | 88 | void fix_height(Node * v) 89 | { 90 | v->height = std::max(height_left(v), height_right(v)) + 1; 91 | } 92 | 93 | int height_right(Node * v) 94 | { 95 | return v->children[1] == nullptr ? 0 : v->children[1]->height; 96 | } 97 | 98 | int height_left(Node * v) 99 | { 100 | return v->children[0] == nullptr ? 0 : v->children[0]->height; 101 | } 102 | 103 | void dfs(Node * v) 104 | { 105 | for (auto child : v->children) 106 | { 107 | if (child != nullptr) 108 | { 109 | dfs(child); 110 | } 111 | } 112 | fix_height(v); 113 | } 114 | 115 | Node * rotate(Node * v, int side) 116 | { 117 | Node * u = v->children[side == Side::left ? 1 : 0]; 118 | v->children[side == Side::left ? 1 : 0] = u->children[side == Side::left ? 0 : 1]; 119 | u->children[side == Side::left ? 0 : 1] = v; 120 | fix_height(v); 121 | fix_height(u); 122 | return u; 123 | } 124 | 125 | Node * balance(Node * v) 126 | { 127 | fix_height(v); 128 | if (count_balance(v) > 1) 129 | { 130 | 131 | if (count_balance(v->children[1]) < 0) 132 | { 133 | v->children[1] = rotate(v->children[1], Side::right); 134 | } 135 | return rotate(v, Side::left); 136 | } 137 | if (count_balance(v) < -1) 138 | { 139 | if (count_balance(v->children[0]) > 0) 140 | { 141 | v->children[0] = rotate(v->children[0], Side::left); 142 | } 143 | return rotate(v, Side::right); 144 | } 145 | return v; 146 | } 147 | 148 | void make_output_tree() 149 | { 150 | std::queue queue; 151 | queue.push(root); 152 | int num = 1; 153 | while (!queue.empty()) 154 | { 155 | Node * v = queue.front(); 156 | queue.pop(); 157 | int children_num[2] = {0, 0}; 158 | for (int i = 0; i < 2; i++) 159 | { 160 | if (v->children[i] != nullptr) 161 | { 162 | queue.push(v->children[i]); 163 | children_num[i] = ++num; 164 | } 165 | } 166 | output_tree.push_back(new Input_Node(v->key, children_num[0], children_num[1])); 167 | } 168 | } 169 | 170 | Node * insert(Node * root, int key) 171 | { 172 | if (root == nullptr) 173 | { 174 | return new Node(key, nullptr, nullptr, static_cast(input_tree.size()+1)); 175 | } 176 | root->children[key < root->key ? 0 : 1] = insert(root->children[key < root->key ? 0 : 1], key); 177 | return balance(root); 178 | } 179 | 180 | Node * find_max(Node * root) 181 | { 182 | return root->children[1] == nullptr ? root : find_max(root->children[1]); 183 | } 184 | 185 | Node * remove(Node * root, int key) 186 | { 187 | if (root == nullptr) 188 | { 189 | return nullptr; 190 | } 191 | if (key != root->key) 192 | { 193 | root->children[key < root->key ? 0 : 1] = remove(root->children[key < root->key ? 0 : 1], key); 194 | } 195 | else 196 | { 197 | if (root->children[0] == nullptr && root->children[1] == nullptr) 198 | { 199 | return nullptr; 200 | } 201 | if (root->children[0] == nullptr) 202 | { 203 | root = root->children[1]; 204 | return balance(root); 205 | } 206 | Node * r = find_max(root->children[0]); 207 | root->key = r->key; 208 | root->children[0] = remove(root->children[0],r->key); 209 | } 210 | return balance(root); 211 | } 212 | }; 213 | 214 | int main() 215 | { 216 | std::ifstream in("input.txt"); 217 | std::ofstream out("output.txt"); 218 | 219 | size_t n; 220 | in >> n; 221 | auto avl = new AVL_Tree(); 222 | 223 | for (int i = 0; i < n; i++) 224 | { 225 | int key; 226 | int left, right; 227 | in >> key >> left >> right; 228 | avl->input_tree.push_back(new Input_Node(key, left-1, right-1)); 229 | } 230 | 231 | int key; 232 | in >> key; 233 | 234 | if (n == 1) 235 | { 236 | out << 0 << std::endl; 237 | return 0; 238 | } 239 | 240 | avl->make_tree(); 241 | avl->count_height(); 242 | avl->root = avl->remove(avl->root, key); 243 | avl->make_output_tree(); 244 | 245 | out << n - 1 << std::endl; 246 | for (auto v : avl->output_tree) 247 | { 248 | out << v->key << " " << v->children[0] << " " << v->children[1] << std::endl; 249 | } 250 | } -------------------------------------------------------------------------------- /week7/5.7.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 17.03.2020. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | enum Side {right=0, left=1}; 11 | 12 | struct Node 13 | { 14 | int key; 15 | int height; 16 | Node* children[2]; 17 | 18 | Node(int key, Node * left, Node * right) : key(key), height(1) 19 | { 20 | children[0] = left; 21 | children[1] = right; 22 | } 23 | }; 24 | 25 | struct AVL_Tree 26 | { 27 | Node * root = nullptr; 28 | 29 | int count_balance(Node * v) 30 | { 31 | if (v == nullptr) 32 | { 33 | return 0; 34 | } 35 | return (v->children[1] != nullptr ? v->children[1]->height : 0) - 36 | (v->children[0] != nullptr ? v->children[0]->height : 0); 37 | } 38 | 39 | void fix_height(Node * v) 40 | { 41 | v->height = std::max(height_left(v), height_right(v)) + 1; 42 | } 43 | 44 | int height_right(Node * v) 45 | { 46 | return v->children[1] == nullptr ? 0 : v->children[1]->height; 47 | } 48 | 49 | int height_left(Node * v) 50 | { 51 | return v->children[0] == nullptr ? 0 : v->children[0]->height; 52 | } 53 | 54 | Node * rotate(Node * v, int side) 55 | { 56 | Node * u = v->children[side == Side::left ? 1 : 0]; 57 | v->children[side == Side::left ? 1 : 0] = u->children[side == Side::left ? 0 : 1]; 58 | u->children[side == Side::left ? 0 : 1] = v; 59 | fix_height(v); 60 | fix_height(u); 61 | return u; 62 | } 63 | 64 | Node * balance(Node * v) 65 | { 66 | fix_height(v); 67 | if (count_balance(v) > 1) 68 | { 69 | 70 | if (count_balance(v->children[1]) < 0) 71 | { 72 | v->children[1] = rotate(v->children[1], Side::right); 73 | } 74 | return rotate(v, Side::left); 75 | } 76 | if (count_balance(v) < -1) 77 | { 78 | if (count_balance(v->children[0]) > 0) 79 | { 80 | v->children[0] = rotate(v->children[0], Side::left); 81 | } 82 | return rotate(v, Side::right); 83 | } 84 | return v; 85 | } 86 | 87 | Node * insert(Node * root, int key) 88 | { 89 | if (root == nullptr) 90 | { 91 | return new Node(key, nullptr, nullptr); 92 | } 93 | root->children[key < root->key ? 0 : 1] = insert(root->children[key < root->key ? 0 : 1], key); 94 | return balance(root); 95 | } 96 | 97 | Node * find_max(Node * root) 98 | { 99 | return root->children[1] == nullptr ? root : find_max(root->children[1]); 100 | } 101 | 102 | Node * remove(Node * root, int key) 103 | { 104 | if (root == nullptr) 105 | { 106 | return nullptr; 107 | } 108 | if (key != root->key) 109 | { 110 | root->children[key < root->key ? 0 : 1] = remove(root->children[key < root->key ? 0 : 1], key); 111 | } 112 | else 113 | { 114 | if (root->children[0] == nullptr && root->children[1] == nullptr) 115 | { 116 | return nullptr; 117 | } 118 | if (root->children[0] == nullptr) 119 | { 120 | root = root->children[1]; 121 | return balance(root); 122 | } 123 | Node * r = find_max(root->children[0]); 124 | root->key = r->key; 125 | root->children[0] = remove(root->children[0],r->key); 126 | } 127 | return balance(root); 128 | } 129 | 130 | Node * search(Node * root, int key) 131 | { 132 | if (root == nullptr || key == root->key) 133 | { 134 | return root; 135 | } 136 | return search(root->children[key < root->key ? 0 : 1], key); 137 | } 138 | }; 139 | 140 | int main() 141 | { 142 | std::ifstream in("input.txt"); 143 | std::ofstream out("output.txt"); 144 | 145 | size_t n; 146 | in >> n; 147 | auto avl = new AVL_Tree(); 148 | 149 | for (int i = 0; i < n; i++) 150 | { 151 | std::string cmd; 152 | int key; 153 | in >> cmd >> key; 154 | if (cmd == "A") 155 | { 156 | if (avl->search(avl->root, key) == nullptr) 157 | { 158 | avl->root = avl->insert(avl->root, key); 159 | } 160 | out << avl->count_balance(avl->root) << std::endl; 161 | } 162 | if (cmd == "D") 163 | { 164 | if (avl->search(avl->root, key) != nullptr) 165 | { 166 | avl->root = avl->remove(avl->root, key); 167 | } 168 | out << avl->count_balance(avl->root) << std::endl; 169 | } 170 | if (cmd == "C") 171 | { 172 | out << ((avl->search(avl->root, key) != nullptr) ? "Y" : "N") << std::endl; 173 | } 174 | } 175 | } -------------------------------------------------------------------------------- /week8/1.py: -------------------------------------------------------------------------------- 1 | with open("input.txt", 'r') as file: 2 | input = file.readlines() 3 | lines = list(map(str.strip, input)) 4 | dic = {} 5 | output = open("output.txt", 'a') 6 | for i in lines: 7 | key = '' 8 | if len(i) >= 2: 9 | key = i[2:] 10 | if i[0] == 'A': 11 | dic[key] = key 12 | elif i[0] == 'D': 13 | dic[key] = None 14 | elif i[0] == '?': 15 | try: 16 | if dic[key] is not None: 17 | output.write('Y\n') 18 | else: 19 | output.write('N\n') 20 | except KeyError: 21 | output.write('N\n') -------------------------------------------------------------------------------- /week8/third.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // pads 4 | // 5 | // Created by Alexey Ageev. 6 | // Copyright © 2020 Alexey Ageev. All rights reserved. 7 | // 8 | //MARK: Debug 9 | //#include 10 | //unsigned long startTime = clock(); 11 | //#include 12 | //#include 13 | 14 | //MARK: Code 15 | #include "edx-io.hpp" 16 | #include 17 | 18 | long long contains (std::vector, long long); 19 | 20 | unsigned hashFunction(long long value); 21 | 22 | int main() { 23 | long long N; 24 | long long X; 25 | long long A; 26 | long long B; 27 | long long Ac; 28 | long long Bc; 29 | long long Ad; 30 | long long Bd; 31 | io >> N >> X >> A >> B >> Ac >> Bc >> Ad >> Bd; 32 | std::vector vectors[131071]; 33 | for (unsigned long i = 0; i < N; i++){ 34 | long long hash = hashFunction(X); 35 | if (contains(vectors[hash], X) == -1){ 36 | vectors[hash].push_back(X); 37 | A = (A + Ad) % 1000; 38 | B = (B + Bd) % 1000000000000000; 39 | } else { 40 | A = (A + Ac) % 1000; 41 | B = (B + Bc) % 1000000000000000; 42 | } 43 | X = (X * A + B) % 1000000000000000; 44 | 45 | } 46 | io << X << " " << A << " " << B; 47 | // std::cout << std::endl << "!!!COMMENT DEBUG LINES BEFORE TESTING!!!" << std::endl << "Work time: " << 1000 * (clock() - startTime) / CLOCKS_PER_SEC << std::endl; 48 | } 49 | 50 | long long contains(std::vector vec, long long value){ 51 | for (unsigned i = 0; i < vec.size(); i++){ 52 | if (value == vec[i]){ 53 | return i; 54 | } 55 | } 56 | return -1; 57 | } 58 | 59 | unsigned hashFunction(long long value){ 60 | return abs(int((value / 4294967296) % 65536 + value % 65536) / 2); 61 | } 62 | -------------------------------------------------------------------------------- /week8/zwei.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 17.03.2020. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | struct Value 11 | { 12 | const std::string key; 13 | std::string value; 14 | 15 | Value * next; 16 | Value * linked_next; 17 | Value * linked_prev; 18 | 19 | explicit 20 | Value(std::string key, std::string value, Value * prev, Value * next) : 21 | next(nullptr), key(key), value(value), linked_prev(prev), 22 | linked_next(next) {} 23 | }; 24 | 25 | struct LinkedHashMap 26 | { 27 | // const unsigned int MOD = 200001; 28 | const unsigned int MOD = 96557; 29 | std::vector table; 30 | 31 | Value * header; 32 | 33 | Value * linked_next; 34 | Value * linked_prev; 35 | 36 | LinkedHashMap() 37 | { 38 | linked_next = nullptr; 39 | linked_prev = nullptr; 40 | header = new Value("", "", nullptr, nullptr); 41 | header->linked_prev = header; 42 | header->linked_next = header; 43 | table.resize(MOD); 44 | } 45 | 46 | int hash(const std::string& s) 47 | { 48 | int multiplier = 263; 49 | int prime = 1000000007; 50 | unsigned long long hash = 0; 51 | for (int i = s.size() - 1; i >= 0; --i) 52 | hash = (hash * multiplier + s[i]) % prime; 53 | return static_cast (hash); 54 | } 55 | 56 | 57 | void add(const std::string &key, const std::string &value) 58 | { 59 | Value * x = get_value(key); 60 | if (x != nullptr) 61 | { 62 | x->value = value; 63 | return; 64 | } 65 | int h = hash(key); 66 | Value * node = new Value(key, value, header->linked_prev, header); 67 | header->linked_prev->linked_next = node; 68 | node->next = table[h % MOD]; 69 | table[h % MOD] = node; 70 | header->linked_prev = node; 71 | } 72 | 73 | std::string next(const std::string &key) 74 | { 75 | Value * node = get_value(key); 76 | return node == nullptr ? "" : node->linked_next->value; 77 | } 78 | 79 | std::string prev(const std::string &key) 80 | { 81 | Value * node = get_value(key); 82 | return node == nullptr ? "" : node->linked_prev->value; 83 | } 84 | 85 | Value * get_value(const std::string &key) 86 | { 87 | Value * node = table[hash(key) % MOD]; 88 | while (node != nullptr) 89 | { 90 | if (node->key == key) 91 | { 92 | return node; 93 | } 94 | node = node->next; 95 | } 96 | return nullptr; 97 | } 98 | 99 | std::string get(const std::string &key) 100 | { 101 | Value * node = get_value(key); 102 | return node == nullptr ? "" : node->value; 103 | } 104 | 105 | void remove(const std::string &key) 106 | { 107 | int h = hash(key); 108 | Value * node = table[h % MOD]; 109 | Value * prev_node = nullptr; 110 | while (node != nullptr) 111 | { 112 | if (node->key == key) 113 | { 114 | node->linked_next->linked_prev = node->linked_prev; 115 | node->linked_prev->linked_next = node->linked_next; 116 | if (prev_node == nullptr) 117 | { 118 | table[h % MOD] = node->next; 119 | } 120 | else 121 | { 122 | prev_node->next = node->next; 123 | node->next = nullptr; 124 | } 125 | return; 126 | } 127 | prev_node = node; 128 | node = node->next; 129 | } 130 | } 131 | }; 132 | 133 | 134 | int main() 135 | { 136 | std::ifstream input("input.txt"); 137 | std::ofstream output("output.txt"); 138 | LinkedHashMap linkedHashMap; 139 | uint64_t n; 140 | input >> n; 141 | while (!input.eof()) 142 | { 143 | std::string operation; 144 | std::string key; 145 | input >> operation >> key; 146 | if (operation == "put") 147 | { 148 | std::string value; 149 | input >> value; 150 | linkedHashMap.add(key, value); 151 | } 152 | if (operation == "delete") 153 | { 154 | linkedHashMap.remove(key); 155 | } 156 | if (operation == "get") 157 | { 158 | output << linkedHashMap.get(key) << "\n"; 159 | } 160 | if (operation == "prev") 161 | { 162 | output << linkedHashMap.prev(key) << "\n"; 163 | } 164 | if (operation == "next") 165 | { 166 | output << linkedHashMap.next(key) << "\n"; 167 | } 168 | } 169 | return 0; 170 | } -------------------------------------------------------------------------------- /week9/1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main() { 7 | std::string eins, zwei; 8 | { 9 | std::ifstream inp("input.txt"); 10 | inp >> eins >> zwei; 11 | } 12 | 13 | std::vector positions; 14 | size_t pos = zwei.find(eins, 0); 15 | while (pos != std::string::npos) { 16 | positions.push_back(pos); 17 | pos = zwei.find(eins, pos + 1); 18 | } 19 | 20 | { 21 | std::ofstream outp("output.txt"); 22 | outp << positions.size() << "\n"; 23 | for (auto x : positions) 24 | outp << x + 1 << " "; 25 | } 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /week9/procto.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thomasf on 10.04.2020. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | inline bool check_if_r_matches(const std::string &pattern, const std::string &target, uint32_t pos) { 12 | if (target.size() < pos + pattern.size() || pattern[pattern.size() - 1] != target[pos + pattern.size() - 1]) 13 | return false; 14 | 15 | for (uint32_t x = 1; x < pattern.size() - 1; x++) { 16 | if (pattern[x] != target[pos + x]) 17 | return false; 18 | } 19 | return true; 20 | } 21 | 22 | int main() { 23 | std::string eins, zwei; 24 | { 25 | std::ifstream inp("input.txt"); 26 | inp >> eins >> zwei; 27 | } 28 | 29 | std::vector positions; 30 | positions.reserve(zwei.size()); 31 | for (uint32_t i = 0; i < zwei.size(); i++) { 32 | if (zwei[i] == eins[0] && check_if_r_matches(eins, zwei, i)) 33 | positions.push_back(i); 34 | } 35 | 36 | { 37 | std::ofstream outp("output.txt"); 38 | outp << positions.size() << "\n"; 39 | for (auto x : positions) 40 | outp << x + 1 << " "; 41 | } 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /week9/zprocto.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | void prefix_function(std::string const & text, std::vector & prefix) 6 | { 7 | prefix.push_back(0); 8 | 9 | for (size_t i = 1; i < text.size(); ++i) 10 | { 11 | int border = prefix[i - 1]; 12 | 13 | while (border > 0 && text[i] != text[border]) 14 | { 15 | border = prefix[border - 1]; 16 | } 17 | 18 | prefix.push_back(border + (text[border] == text[i] ? 1 : 0)); 19 | } 20 | } 21 | 22 | 23 | void kmp(std::string const & text, std::string const & pattern, std::vector & pos) 24 | { 25 | std::vector prefix; 26 | std::string super_string; 27 | 28 | super_string = pattern + '$' + text; 29 | 30 | prefix_function(super_string, prefix); 31 | 32 | for (int i = 0; i < static_cast(text.length() - pattern.length() + 1); ++i) 33 | { 34 | if (prefix[i + 2*pattern.size()] == pattern.size()) 35 | { 36 | pos.push_back(i + 1); 37 | } 38 | } 39 | } 40 | 41 | 42 | int main() 43 | { 44 | std::ifstream inp_file("input.txt"); 45 | std::ofstream out_file("output.txt"); 46 | 47 | std::string text, pattern; 48 | inp_file >> pattern >> text; 49 | 50 | std::vector pattern_positions; 51 | kmp(text, pattern, pattern_positions); 52 | 53 | out_file << pattern_positions.size() << std::endl; 54 | for (auto x : pattern_positions) 55 | { 56 | out_file << x << ' '; 57 | } 58 | 59 | return 0; 60 | } --------------------------------------------------------------------------------