From c2e890a73a3ef23432530336df6cf5d33154b0a1 Mon Sep 17 00:00:00 2001 From: LevTrachuk <155105125+LevTrachuk@users.noreply.github.com> Date: Tue, 16 Sep 2025 15:02:40 +0300 Subject: [PATCH 01/16] Create Trachuk Lev 4093 --- Trachuk Lev 4093 | 1 + 1 file changed, 1 insertion(+) create mode 100644 Trachuk Lev 4093 diff --git a/Trachuk Lev 4093 b/Trachuk Lev 4093 new file mode 100644 index 0000000000..1cceae7c83 --- /dev/null +++ b/Trachuk Lev 4093 @@ -0,0 +1 @@ +Trachuk Lev 4093 From 06c64308d12b7b00ac79feb1c8f7edcbce38b2ba Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Wed, 22 Oct 2025 15:29:41 +0300 Subject: [PATCH 02/16] First Lab complete --- .gitignore | 2 + CMakeLists.txt | 8 ++-- Lab1C/CMakeLists.txt | 6 --- Lab1C/lab1.c | 40 ----------------- Lab1CPP/CMakeLists.txt | 17 +++++++ {Lab1C => Lab1CPP}/input.txt | 0 Lab1CPP/main.cpp | 67 ++++++++++++++++++++++++++++ LibraryCPPClass/CMakeLists.txt | 3 +- LibraryCPPClass/Tests/CMakeLists.txt | 8 ++-- LibraryCPPClass/array.cpp | 45 ++++++++++++++++--- LibraryCPPClass/array.h | 2 + 11 files changed, 137 insertions(+), 61 deletions(-) delete mode 100644 Lab1C/CMakeLists.txt delete mode 100644 Lab1C/lab1.c create mode 100644 Lab1CPP/CMakeLists.txt rename {Lab1C => Lab1CPP}/input.txt (100%) create mode 100644 Lab1CPP/main.cpp diff --git a/.gitignore b/.gitignore index 7b4ae92774..3f84bbcefd 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ Release/* .vs/* build/* .vscode/* +.idea +out/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b40c0dd11c..891c8b1067 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,9 @@ else() add_compile_options(-Wall -Wextra -Wpedantic -Wno-gnu-empty-struct -Wno-unused-parameter) endif() -add_subdirectory(LibraryC) -add_subdirectory(LibraryCPP) +#add_subdirectory(LibraryC) +#add_subdirectory(LibraryCPP) add_subdirectory(LibraryCPPClass) -add_subdirectory(LibraryCPPTemplate) +#add_subdirectory(LibraryCPPTemplate) -add_subdirectory(Lab1C) +add_subdirectory(Lab1CPP) diff --git a/Lab1C/CMakeLists.txt b/Lab1C/CMakeLists.txt deleted file mode 100644 index f4da4d8372..0000000000 --- a/Lab1C/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_executable(Lab1C lab1.c) -target_include_directories(Lab1C PUBLIC ../LibraryC) -target_link_libraries(Lab1C LibraryC) - -add_test(NAME TestLab1C COMMAND Lab1C ${CMAKE_CURRENT_SOURCE_DIR}/input.txt) -set_property(TEST TestLab1C PROPERTY PASS_REGULAR_EXPRESSION "1 2 3 4 5") diff --git a/Lab1C/lab1.c b/Lab1C/lab1.c deleted file mode 100644 index fdf6ed1527..0000000000 --- a/Lab1C/lab1.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "array.h" - -Array *array_create_and_read(FILE *input) -{ - int n; - fscanf(input, "%d", &n); - /* Create array */ - Array *arr = array_create(n, NULL); - /* Read array data */ - for (int i = 0 ; i < n ; ++i) - { - int x; - fscanf(input, "%d", &x); - array_set(arr, i, x); - } - return arr; -} - -void task1(Array *arr) -{ -} - -void task2(Array *arr) -{ -} - -int main(int argc, char **argv) -{ - Array *arr = NULL; - FILE *input = fopen(argv[1], "r"); - arr = array_create_and_read(input); - task1(arr); - array_delete(arr); - /* Create another array here */ - arr = array_create_and_read(input); - task2(arr); - array_delete(arr); - fclose(input); -} diff --git a/Lab1CPP/CMakeLists.txt b/Lab1CPP/CMakeLists.txt new file mode 100644 index 0000000000..cdcf0fe792 --- /dev/null +++ b/Lab1CPP/CMakeLists.txt @@ -0,0 +1,17 @@ +add_executable(Lab1CPP main.cpp) +target_link_libraries(Lab1CPP LibraryCPPClass) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/input.txt + ${CMAKE_CURRENT_BINARY_DIR}/input.txt COPYONLY) + +add_test(NAME Test_1 COMMAND Lab1CPP) +set_tests_properties(Test_1 PROPERTIES + PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +add_test(NAME Test_2 COMMAND Lab1CPP) +set_tests_properties(Test_2 PROPERTIES + PASS_REGULAR_EXPRESSION "1 2 3 4" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) \ No newline at end of file diff --git a/Lab1C/input.txt b/Lab1CPP/input.txt similarity index 100% rename from Lab1C/input.txt rename to Lab1CPP/input.txt diff --git a/Lab1CPP/main.cpp b/Lab1CPP/main.cpp new file mode 100644 index 0000000000..1c601e19a6 --- /dev/null +++ b/Lab1CPP/main.cpp @@ -0,0 +1,67 @@ +#include "../LibraryCPPClass/array.h" +#include +#include + +using namespace std; + +bool is_palindrome(int n) { + if (n < 10) return true; + int start = n; + int reversed = 0; + while (n > 0) { + reversed = reversed * 10 + n % 10; + n /= 10; + } + return start == reversed; +} + +int main(){ + std::ifstream file("input.txt"); + int size1; + file >> size1; + + for (int i = 0; i < size1; i++) { + int temp; + file >> temp; + } + + Array arr1(size1); + int num = 0; + for (size_t i = 0; i < arr1.size(); i++) { + while (!is_palindrome(num)) num++; + arr1.set(i, num); + num++; + } + + for (int i = 0; i < size1; i++) { + cout << arr1.get(i) << " "; + } + cout << endl; + + int size2; + file >> size2; + + Array arr2(size2); + for (size_t i = 0; i < arr2.size(); i++) { + int val; + file >> val; + arr2.set(i, val); + } + + + for (size_t i = 0; i < arr2.size(); i++) { + int count = 0; + for (size_t j = 0; j < arr2.size(); j++) { + if (arr2.get(i) == arr2.get(j)) count++; + } + if (count == 1) { + cout << arr2.get(i) << " "; + } + } + + file.close(); + + return 0; +} + + diff --git a/LibraryCPPClass/CMakeLists.txt b/LibraryCPPClass/CMakeLists.txt index 0ddd51cba2..211b58a0b0 100644 --- a/LibraryCPPClass/CMakeLists.txt +++ b/LibraryCPPClass/CMakeLists.txt @@ -1,3 +1,2 @@ -add_library(LibraryCPPClass STATIC array.cpp list.cpp queue.cpp stack.cpp vector.cpp) - +add_library(LibraryCPPClass STATIC array.cpp) add_subdirectory(Tests) diff --git a/LibraryCPPClass/Tests/CMakeLists.txt b/LibraryCPPClass/Tests/CMakeLists.txt index 748ae652cc..14a30ada49 100644 --- a/LibraryCPPClass/Tests/CMakeLists.txt +++ b/LibraryCPPClass/Tests/CMakeLists.txt @@ -1,7 +1,7 @@ -# add_executable(TestArrayCPPClass array.cpp) -# target_include_directories(TestArrayCPPClass PUBLIC ..) -# target_link_libraries(TestArrayCPPClass LibraryCPPClass) -# add_test(TestArrayCPPClass TestArrayCPPClass) +add_executable(TestArrayCPPClass array.cpp) +target_include_directories(TestArrayCPPClass PUBLIC ..) +target_link_libraries(TestArrayCPPClass LibraryCPPClass) +add_test(TestArrayCPPClass TestArrayCPPClass) # add_executable(TestListCPPClass list.cpp) # target_include_directories(TestListCPPClass PUBLIC ..) diff --git a/LibraryCPPClass/array.cpp b/LibraryCPPClass/array.cpp index 5f9679d07f..e94339195c 100644 --- a/LibraryCPPClass/array.cpp +++ b/LibraryCPPClass/array.cpp @@ -1,32 +1,67 @@ #include "array.h" +#include -Array::Array(size_t size) +Array::Array(size_t size) : size_arr(size), data_arr(new Data[size]) { + for (size_t i = 0; i < size_arr; i++) + { + data_arr[i] = Data(0); + } } -Array::Array(const Array &a) +Array::Array(const Array& other) : size_arr(other.size_arr) { + data_arr = new Data[size_arr]; + for (size_t i = 0; i < size_arr; i++) + { + data_arr[i] = other.data_arr[i]; + } } -Array &Array::operator=(const Array &a) +Array& Array::operator=(const Array& other) { + if (this != &other) { + delete[] data_arr; + size_arr = other.size_arr; + data_arr = new Data[size_arr]; + + for (size_t i = 0; i < size_arr; i++) { + data_arr[i] = other.data_arr[i]; + } + } return *this; } Array::~Array() { + delete[] data_arr; } Data Array::get(size_t index) const { - return Data(0); + if ((index >= size_arr)) + { + throw std::out_of_range("ERROR: index out of range"); + } + else + { + return data_arr[index]; + } } void Array::set(size_t index, Data value) { + if ((index >= size_arr)) + { + throw std::out_of_range("ERROR: index out of range"); + } + else + { + data_arr[index] = value; + } } size_t Array::size() const { - return 0; + return size_arr; } diff --git a/LibraryCPPClass/array.h b/LibraryCPPClass/array.h index 7ebd54f7a1..7f06d1eb8c 100644 --- a/LibraryCPPClass/array.h +++ b/LibraryCPPClass/array.h @@ -32,6 +32,8 @@ class Array private: // private data should be here + size_t size_arr; + Data* data_arr; }; #endif From a2c9e712afb7164e2446b922d6fa8d971cf0e942 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Thu, 23 Oct 2025 16:50:09 +0300 Subject: [PATCH 03/16] =?UTF-8?q?1.=20=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=BF=D1=83=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab1CPP/CMakeLists.txt | 19 +++++-------------- Lab1CPP/input2.txt | 4 ++++ Lab1CPP/main.cpp | 43 +++++++++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 Lab1CPP/input2.txt diff --git a/Lab1CPP/CMakeLists.txt b/Lab1CPP/CMakeLists.txt index cdcf0fe792..d08b8d6b6c 100644 --- a/Lab1CPP/CMakeLists.txt +++ b/Lab1CPP/CMakeLists.txt @@ -1,17 +1,8 @@ add_executable(Lab1CPP main.cpp) +target_include_directories (Lab1CPP PUBLIC ../LibraryCPPClass) target_link_libraries(Lab1CPP LibraryCPPClass) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/input.txt - ${CMAKE_CURRENT_BINARY_DIR}/input.txt COPYONLY) - -add_test(NAME Test_1 COMMAND Lab1CPP) -set_tests_properties(Test_1 PROPERTIES - PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) - -add_test(NAME Test_2 COMMAND Lab1CPP) -set_tests_properties(Test_2 PROPERTIES - PASS_REGULAR_EXPRESSION "1 2 3 4" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) \ No newline at end of file +add_test(NAME Test_1 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9.*1 2 3 4") +add_test(NAME Test_2 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "22 33 44 88.*3 4") \ No newline at end of file diff --git a/Lab1CPP/input2.txt b/Lab1CPP/input2.txt new file mode 100644 index 0000000000..9a3a344518 --- /dev/null +++ b/Lab1CPP/input2.txt @@ -0,0 +1,4 @@ +6 +22 13 33 44 90 88 +6 +11 2 3 4 11 2 \ No newline at end of file diff --git a/Lab1CPP/main.cpp b/Lab1CPP/main.cpp index 1c601e19a6..f505c4e9e0 100644 --- a/Lab1CPP/main.cpp +++ b/Lab1CPP/main.cpp @@ -1,4 +1,4 @@ -#include "../LibraryCPPClass/array.h" +#include "array.h" #include #include @@ -15,25 +15,46 @@ bool is_palindrome(int n) { return start == reversed; } -int main(){ - std::ifstream file("input.txt"); +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Error: File not specified" << endl; + return 1; + } + + std::ifstream file(argv[1]); + + if (!file.is_open()) { + cout << "Error: Cannot open file " << argv[1] << endl; + return 1; + } + int size1; file >> size1; - for (int i = 0; i < size1; i++) { + Array arr1(size1); + int num = 0; + for (size_t i = 0; i < size1; i++) { int temp; file >> temp; + if (is_palindrome(temp)) { + arr1.set(num, temp); + num++; + } } - Array arr1(size1); - int num = 0; - for (size_t i = 0; i < arr1.size(); i++) { - while (!is_palindrome(num)) num++; - arr1.set(i, num); - num++; + for (size_t i = 0; i < num; i++) { + for (size_t j = 0; j < num - i - 1; j++) { + if (arr1.get(j) > arr1.get(j + 1)) { + int a = arr1.get(j); + int b = arr1.get(j + 1); + swap(a, b); + arr1.set(j, a); + arr1.set(j + 1, b); + } + } } - for (int i = 0; i < size1; i++) { + for (size_t i = 0; i < num; i++) { cout << arr1.get(i) << " "; } cout << endl; From 14fb19e16b89a88fe7d9b0952332d8f7f415506b Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Thu, 23 Oct 2025 16:57:42 +0300 Subject: [PATCH 04/16] =?UTF-8?q?Revert=20"1.=20=D0=A3=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BF=D1=83=D1=82=D1=8C"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a2c9e712afb7164e2446b922d6fa8d971cf0e942. --- Lab1CPP/CMakeLists.txt | 19 ++++++++++++++----- Lab1CPP/input2.txt | 4 ---- Lab1CPP/main.cpp | 43 +++++++++++------------------------------- 3 files changed, 25 insertions(+), 41 deletions(-) delete mode 100644 Lab1CPP/input2.txt diff --git a/Lab1CPP/CMakeLists.txt b/Lab1CPP/CMakeLists.txt index d08b8d6b6c..cdcf0fe792 100644 --- a/Lab1CPP/CMakeLists.txt +++ b/Lab1CPP/CMakeLists.txt @@ -1,8 +1,17 @@ add_executable(Lab1CPP main.cpp) -target_include_directories (Lab1CPP PUBLIC ../LibraryCPPClass) target_link_libraries(Lab1CPP LibraryCPPClass) -add_test(NAME Test_1 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input.txt) -set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9.*1 2 3 4") -add_test(NAME Test_2 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2.txt) -set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "22 33 44 88.*3 4") \ No newline at end of file +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/input.txt + ${CMAKE_CURRENT_BINARY_DIR}/input.txt COPYONLY) + +add_test(NAME Test_1 COMMAND Lab1CPP) +set_tests_properties(Test_1 PROPERTIES + PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +add_test(NAME Test_2 COMMAND Lab1CPP) +set_tests_properties(Test_2 PROPERTIES + PASS_REGULAR_EXPRESSION "1 2 3 4" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) \ No newline at end of file diff --git a/Lab1CPP/input2.txt b/Lab1CPP/input2.txt deleted file mode 100644 index 9a3a344518..0000000000 --- a/Lab1CPP/input2.txt +++ /dev/null @@ -1,4 +0,0 @@ -6 -22 13 33 44 90 88 -6 -11 2 3 4 11 2 \ No newline at end of file diff --git a/Lab1CPP/main.cpp b/Lab1CPP/main.cpp index f505c4e9e0..1c601e19a6 100644 --- a/Lab1CPP/main.cpp +++ b/Lab1CPP/main.cpp @@ -1,4 +1,4 @@ -#include "array.h" +#include "../LibraryCPPClass/array.h" #include #include @@ -15,46 +15,25 @@ bool is_palindrome(int n) { return start == reversed; } -int main(int argc, char* argv[]) { - if (argc < 2) { - cout << "Error: File not specified" << endl; - return 1; - } - - std::ifstream file(argv[1]); - - if (!file.is_open()) { - cout << "Error: Cannot open file " << argv[1] << endl; - return 1; - } - +int main(){ + std::ifstream file("input.txt"); int size1; file >> size1; - Array arr1(size1); - int num = 0; - for (size_t i = 0; i < size1; i++) { + for (int i = 0; i < size1; i++) { int temp; file >> temp; - if (is_palindrome(temp)) { - arr1.set(num, temp); - num++; - } } - for (size_t i = 0; i < num; i++) { - for (size_t j = 0; j < num - i - 1; j++) { - if (arr1.get(j) > arr1.get(j + 1)) { - int a = arr1.get(j); - int b = arr1.get(j + 1); - swap(a, b); - arr1.set(j, a); - arr1.set(j + 1, b); - } - } + Array arr1(size1); + int num = 0; + for (size_t i = 0; i < arr1.size(); i++) { + while (!is_palindrome(num)) num++; + arr1.set(i, num); + num++; } - for (size_t i = 0; i < num; i++) { + for (int i = 0; i < size1; i++) { cout << arr1.get(i) << " "; } cout << endl; From 981c6b3fcebdf34931d9bb9abce5c9a21c861f79 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Thu, 23 Oct 2025 17:13:33 +0300 Subject: [PATCH 05/16] =?UTF-8?q?1.=20=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=BF=D1=83=D1=82=D1=8C=202.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8C=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0?= =?UTF-8?q?=20=D0=B8=D0=B7=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D0=BD?= =?UTF-8?q?=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8=203.=20?= =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B4=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D1=82=D0=B5=D1=81=D1=82=20=D0=B8=20=D0=BD=D0=B5=D0=BC?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B2=D0=B8=D0=B4=D0=BE=D0=B8=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab1CPP/CMakeLists.txt | 19 +++++-------------- Lab1CPP/input2.txt | 4 ++++ Lab1CPP/main.cpp | 43 +++++++++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 Lab1CPP/input2.txt diff --git a/Lab1CPP/CMakeLists.txt b/Lab1CPP/CMakeLists.txt index cdcf0fe792..d08b8d6b6c 100644 --- a/Lab1CPP/CMakeLists.txt +++ b/Lab1CPP/CMakeLists.txt @@ -1,17 +1,8 @@ add_executable(Lab1CPP main.cpp) +target_include_directories (Lab1CPP PUBLIC ../LibraryCPPClass) target_link_libraries(Lab1CPP LibraryCPPClass) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/input.txt - ${CMAKE_CURRENT_BINARY_DIR}/input.txt COPYONLY) - -add_test(NAME Test_1 COMMAND Lab1CPP) -set_tests_properties(Test_1 PROPERTIES - PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) - -add_test(NAME Test_2 COMMAND Lab1CPP) -set_tests_properties(Test_2 PROPERTIES - PASS_REGULAR_EXPRESSION "1 2 3 4" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} -) \ No newline at end of file +add_test(NAME Test_1 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9.*1 2 3 4") +add_test(NAME Test_2 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "22 33 44 88.*3 4") \ No newline at end of file diff --git a/Lab1CPP/input2.txt b/Lab1CPP/input2.txt new file mode 100644 index 0000000000..9a3a344518 --- /dev/null +++ b/Lab1CPP/input2.txt @@ -0,0 +1,4 @@ +6 +22 13 33 44 90 88 +6 +11 2 3 4 11 2 \ No newline at end of file diff --git a/Lab1CPP/main.cpp b/Lab1CPP/main.cpp index 1c601e19a6..f505c4e9e0 100644 --- a/Lab1CPP/main.cpp +++ b/Lab1CPP/main.cpp @@ -1,4 +1,4 @@ -#include "../LibraryCPPClass/array.h" +#include "array.h" #include #include @@ -15,25 +15,46 @@ bool is_palindrome(int n) { return start == reversed; } -int main(){ - std::ifstream file("input.txt"); +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Error: File not specified" << endl; + return 1; + } + + std::ifstream file(argv[1]); + + if (!file.is_open()) { + cout << "Error: Cannot open file " << argv[1] << endl; + return 1; + } + int size1; file >> size1; - for (int i = 0; i < size1; i++) { + Array arr1(size1); + int num = 0; + for (size_t i = 0; i < size1; i++) { int temp; file >> temp; + if (is_palindrome(temp)) { + arr1.set(num, temp); + num++; + } } - Array arr1(size1); - int num = 0; - for (size_t i = 0; i < arr1.size(); i++) { - while (!is_palindrome(num)) num++; - arr1.set(i, num); - num++; + for (size_t i = 0; i < num; i++) { + for (size_t j = 0; j < num - i - 1; j++) { + if (arr1.get(j) > arr1.get(j + 1)) { + int a = arr1.get(j); + int b = arr1.get(j + 1); + swap(a, b); + arr1.set(j, a); + arr1.set(j + 1, b); + } + } } - for (int i = 0; i < size1; i++) { + for (size_t i = 0; i < num; i++) { cout << arr1.get(i) << " "; } cout << endl; From 2157b9bd275e5bada43373f34234f8e9d1f62b74 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Thu, 23 Oct 2025 17:18:14 +0300 Subject: [PATCH 06/16] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B8=D0=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab1CPP/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lab1CPP/main.cpp b/Lab1CPP/main.cpp index f505c4e9e0..c0c54dfe9d 100644 --- a/Lab1CPP/main.cpp +++ b/Lab1CPP/main.cpp @@ -32,8 +32,8 @@ int main(int argc, char* argv[]) { file >> size1; Array arr1(size1); - int num = 0; - for (size_t i = 0; i < size1; i++) { + size_t num = 0; + for (int i = 0; i < size1; i++) { int temp; file >> temp; if (is_palindrome(temp)) { From 9bb1bc4bdde8e7b7d3adab5d6cea4ec2b641419d Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Thu, 13 Nov 2025 22:34:48 +0300 Subject: [PATCH 07/16] Lab_2 --- CMakeLists.txt | 3 +- Lab2CPP/CMakeLists.txt | 12 +++ Lab2CPP/input1_2.txt | 1 + Lab2CPP/input2_2.txt | 1 + Lab2CPP/input3_2.txt | 1 + Lab2CPP/input4_2.txt | 1 + Lab2CPP/main.cpp | 116 +++++++++++++++++++++++++++ LibraryCPPClass/CMakeLists.txt | 2 +- LibraryCPPClass/Tests/CMakeLists.txt | 26 +++--- LibraryCPPClass/stack.cpp | 20 ++++- LibraryCPPClass/stack.h | 4 +- LibraryCPPClass/vector.cpp | 70 +++++++++++----- LibraryCPPClass/vector.h | 5 +- 13 files changed, 223 insertions(+), 39 deletions(-) create mode 100644 Lab2CPP/CMakeLists.txt create mode 100644 Lab2CPP/input1_2.txt create mode 100644 Lab2CPP/input2_2.txt create mode 100644 Lab2CPP/input3_2.txt create mode 100644 Lab2CPP/input4_2.txt create mode 100644 Lab2CPP/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 891c8b1067..5e2e5a8f81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,4 +15,5 @@ endif() add_subdirectory(LibraryCPPClass) #add_subdirectory(LibraryCPPTemplate) -add_subdirectory(Lab1CPP) +#add_subdirectory(Lab1CPP) +add_subdirectory(Lab2CPP) \ No newline at end of file diff --git a/Lab2CPP/CMakeLists.txt b/Lab2CPP/CMakeLists.txt new file mode 100644 index 0000000000..2c08ada2b7 --- /dev/null +++ b/Lab2CPP/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(Lab2CPP main.cpp) +target_include_directories (Lab2CPP PUBLIC ../LibraryCPPClass) +target_link_libraries(Lab2CPP LibraryCPPClass) + +add_test(NAME Test_1 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_2.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 1.*PUSH 2.*PUSH 3.*POP A.*POP B.*MUL A, B.*PUSH A.*POP A.*POP B.*ADD A, B.*PUSH A") +add_test(NAME Test_2 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2_2.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 1.*PUSH 2.*POP A.*POP B.*ADD A, B.*PUSH A.*PUSH 3.*POP A.*POP B.*MUL A, B.*PUSH A") +add_test(NAME Test_3 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input3_2.txt) +set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 2.*PUSH 3.*POP A.*POP B.*MUL A, B.*PUSH A.*PUSH 4.*PUSH 5.*POP A.*POP B.*MUL A, B.*PUSH A.*POP A.*POP B.*ADD A, B.*PUSH A") +add_test(NAME Test_4 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input4_2.txt) +set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 5.*PUSH 3.*POP A.*POP B.*ADD A, B.*PUSH A.*PUSH 2.*PUSH 1.*POP A.*POP B.*ADD A, B.*PUSH A.*POP A.*POP B.*MUL A, B.*PUSH A") \ No newline at end of file diff --git a/Lab2CPP/input1_2.txt b/Lab2CPP/input1_2.txt new file mode 100644 index 0000000000..9026c72a24 --- /dev/null +++ b/Lab2CPP/input1_2.txt @@ -0,0 +1 @@ +1+2*3 \ No newline at end of file diff --git a/Lab2CPP/input2_2.txt b/Lab2CPP/input2_2.txt new file mode 100644 index 0000000000..255e0a0272 --- /dev/null +++ b/Lab2CPP/input2_2.txt @@ -0,0 +1 @@ +(1+2)*3 \ No newline at end of file diff --git a/Lab2CPP/input3_2.txt b/Lab2CPP/input3_2.txt new file mode 100644 index 0000000000..46c2018115 --- /dev/null +++ b/Lab2CPP/input3_2.txt @@ -0,0 +1 @@ +2*3+4*5 \ No newline at end of file diff --git a/Lab2CPP/input4_2.txt b/Lab2CPP/input4_2.txt new file mode 100644 index 0000000000..a3e229d924 --- /dev/null +++ b/Lab2CPP/input4_2.txt @@ -0,0 +1 @@ +(5+3)*(2+1) \ No newline at end of file diff --git a/Lab2CPP/main.cpp b/Lab2CPP/main.cpp new file mode 100644 index 0000000000..0b9bad2279 --- /dev/null +++ b/Lab2CPP/main.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include +#include "stack.h" + +using namespace std; + +int priority(char op) { + if (op == '*') return 2; + return 1; +} + +vector convertToAssembly(const string& expression) { + vector assembly; + Stack ops; + string number; + + for (size_t i = 0; i < expression.length(); ++i) { + char c = expression[i]; + + if (isdigit(c)) { + number += c; + } + else { + if (!number.empty()) { + assembly.push_back("PUSH " + number); + number.clear(); + } + + if (c == '(') { + ops.push('('); + } + else if (c == ')') { + while (!ops.empty() && (char)ops.get() != '(') { + char op = (char)ops.get(); + ops.pop(); + + assembly.push_back("POP A"); + assembly.push_back("POP B"); + if (op == '+') { + assembly.push_back("ADD A, B"); + } + else { + assembly.push_back("MUL A, B"); + } + assembly.push_back("PUSH A"); + } + if (!ops.empty()) ops.pop(); + } + else if (c == '+' || c == '*') { + while (!ops.empty() && (char)ops.get() != '(' && + priority((char)ops.get()) >= priority(c)) { + char op = (char)ops.get(); + ops.pop(); + + assembly.push_back("POP A"); + assembly.push_back("POP B"); + if (op == '+') { + assembly.push_back("ADD A, B"); + } + else { + assembly.push_back("MUL A, B"); + } + assembly.push_back("PUSH A"); + } + ops.push(c); + } + } + } + + if (!number.empty()) { + assembly.push_back("PUSH " + number); + } + + while (!ops.empty()) { + char op = (char)ops.get(); + ops.pop(); + + assembly.push_back("POP A"); + assembly.push_back("POP B"); + if (op == '+') { + assembly.push_back("ADD A, B"); + } + else { + assembly.push_back("MUL A, B"); + } + assembly.push_back("PUSH A"); + } + + return assembly; +} + +int main(int argc, char* argv[]) { + try { + if (argc != 2) return 1; + + ifstream input(argv[1]); + if (!input.is_open()) return 1; + + string expression; + getline(input, expression); + + vector result = convertToAssembly(expression); + for (size_t i = 0; i < result.size(); ++i) { + cout << result[i] << endl; + } + } + catch (...) { + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/LibraryCPPClass/CMakeLists.txt b/LibraryCPPClass/CMakeLists.txt index 211b58a0b0..d8081ae607 100644 --- a/LibraryCPPClass/CMakeLists.txt +++ b/LibraryCPPClass/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(LibraryCPPClass STATIC array.cpp) +add_library(LibraryCPPClass STATIC stack.cpp vector.cpp) add_subdirectory(Tests) diff --git a/LibraryCPPClass/Tests/CMakeLists.txt b/LibraryCPPClass/Tests/CMakeLists.txt index 14a30ada49..64ca313a4e 100644 --- a/LibraryCPPClass/Tests/CMakeLists.txt +++ b/LibraryCPPClass/Tests/CMakeLists.txt @@ -1,7 +1,7 @@ -add_executable(TestArrayCPPClass array.cpp) -target_include_directories(TestArrayCPPClass PUBLIC ..) -target_link_libraries(TestArrayCPPClass LibraryCPPClass) -add_test(TestArrayCPPClass TestArrayCPPClass) +#add_executable(TestArrayCPPClass array.cpp) +#target_include_directories(TestArrayCPPClass PUBLIC ..) +#target_link_libraries(TestArrayCPPClass LibraryCPPClass) +#add_test(TestArrayCPPClass TestArrayCPPClass) # add_executable(TestListCPPClass list.cpp) # target_include_directories(TestListCPPClass PUBLIC ..) @@ -14,13 +14,13 @@ add_test(TestArrayCPPClass TestArrayCPPClass) # add_test(TestQueueCPPClass TestQueueCPPClass) # set_tests_properties(TestQueueCPPClass PROPERTIES TIMEOUT 10) -# add_executable(TestStackCPPClass stack.cpp) -# target_include_directories(TestStackCPPClass PUBLIC ..) -# target_link_libraries(TestStackCPPClass LibraryCPPClass) -# add_test(TestStackCPPClass TestStackCPPClass) +add_executable(TestStackCPPClass stack.cpp) +target_include_directories(TestStackCPPClass PUBLIC ..) +target_link_libraries(TestStackCPPClass LibraryCPPClass) +add_test(TestStackCPPClass TestStackCPPClass) -# add_executable(TestVectorCPPClass vector.cpp) -# target_include_directories(TestVectorCPPClass PUBLIC ..) -# target_link_libraries(TestVectorCPPClass LibraryCPPClass) -# add_test(TestVectorCPPClass TestVectorCPPClass) -# set_tests_properties(TestVectorCPPClass PROPERTIES TIMEOUT 10) +add_executable(TestVectorCPPClass vector.cpp) +target_include_directories(TestVectorCPPClass PUBLIC ..) +target_link_libraries(TestVectorCPPClass LibraryCPPClass) +add_test(TestVectorCPPClass TestVectorCPPClass) +set_tests_properties(TestVectorCPPClass PROPERTIES TIMEOUT 10) diff --git a/LibraryCPPClass/stack.cpp b/LibraryCPPClass/stack.cpp index 0dc91d6c29..c9822070ca 100644 --- a/LibraryCPPClass/stack.cpp +++ b/LibraryCPPClass/stack.cpp @@ -1,10 +1,11 @@ #include "stack.h" +#include Stack::Stack() { } -Stack::Stack(const Stack &a) +Stack::Stack(const Stack &a) : stack_data(a.stack_data) { // implement or disable this function } @@ -12,6 +13,9 @@ Stack::Stack(const Stack &a) Stack &Stack::operator=(const Stack &a) { // implement or disable this function + if (this != &a) { + stack_data = a.stack_data; + } return *this; } @@ -21,18 +25,28 @@ Stack::~Stack() void Stack::push(Data data) { + size_t old_size = stack_data.size(); + stack_data.resize(old_size + 1); + stack_data.set(old_size, data); } Data Stack::get() const { - return Data(); + if (stack_data.size() == 0) { + throw std::runtime_error("Stack is empty"); + } + return stack_data.get(stack_data.size() - 1); } void Stack::pop() { + if (stack_data.size() == 0) { + throw std::runtime_error("Stack is empty"); + } + stack_data.resize(stack_data.size() - 1); } bool Stack::empty() const { - return true; + return stack_data.size() == 0; } diff --git a/LibraryCPPClass/stack.h b/LibraryCPPClass/stack.h index 740c4c3e64..cd7921006a 100644 --- a/LibraryCPPClass/stack.h +++ b/LibraryCPPClass/stack.h @@ -2,9 +2,10 @@ #define STACK_H #include +#include "vector.h" // Change it to desired type -typedef int Data; +typedef size_t Data; class Stack { @@ -37,6 +38,7 @@ class Stack private: // private data should be here + Vector stack_data; }; #endif diff --git a/LibraryCPPClass/vector.cpp b/LibraryCPPClass/vector.cpp index 5bab7f34be..809973265d 100644 --- a/LibraryCPPClass/vector.cpp +++ b/LibraryCPPClass/vector.cpp @@ -1,36 +1,68 @@ #include "vector.h" +#include -Vector::Vector() -{ +Vector::Vector() : elements(nullptr), capacity_value(0), size_value(0) { } -Vector::Vector(const Vector &a) -{ +Vector::Vector(const Vector& a) : capacity_value(a.capacity_value), size_value(a.size_value) { + elements = new Data[capacity_value]; + for (size_t i = 0; i < size_value; ++i) { + elements[i] = a.elements[i]; + } } -Vector &Vector::operator=(const Vector &a) -{ +Vector& Vector::operator=(const Vector& a) { + if (this != &a) { + delete[] elements; + capacity_value = a.capacity_value; + size_value = a.size_value; + elements = new Data[capacity_value]; + for (size_t i = 0; i < size_value; ++i) { + elements[i] = a.elements[i]; + } + } return *this; } -Vector::~Vector() -{ +Vector::~Vector() { + delete[] elements; } -Data Vector::get(size_t index) const -{ - return Data(); +Data Vector::get(size_t index) const { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + return elements[index]; } -void Vector::set(size_t index, Data value) -{ +void Vector::set(size_t index, Data value) { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + elements[index] = value; } -size_t Vector::size() const -{ - return 0; +size_t Vector::size() const { + return size_value; } -void Vector::resize(size_t size) -{ -} +void Vector::resize(size_t size) { + if (size > capacity_value) { + size_t new_capacity = 1; + if (capacity_value != 0) { + new_capacity = capacity_value; + } + while (new_capacity < size) { + new_capacity *= 2; + } + + Data* new_data = new Data[new_capacity]; + for (size_t i = 0; i < size_value; ++i) { + new_data[i] = elements[i]; + } + delete[] elements; + elements = new_data; + capacity_value = new_capacity; + } + size_value = size; +} \ No newline at end of file diff --git a/LibraryCPPClass/vector.h b/LibraryCPPClass/vector.h index 1d1d656da6..f10154eaeb 100644 --- a/LibraryCPPClass/vector.h +++ b/LibraryCPPClass/vector.h @@ -4,7 +4,7 @@ #include // Change it to desired type -typedef int Data; +typedef size_t Data; class Vector { @@ -36,6 +36,9 @@ class Vector private: // private data should be here + Data* elements; + size_t capacity_value; + size_t size_value; }; #endif From e60d1c7d88c77a0cbe67a51c8bc9aa3d55744b12 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Fri, 14 Nov 2025 11:07:39 +0300 Subject: [PATCH 08/16] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B5=D0=B4=D0=BE=D1=87=D1=91=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab2CPP/CMakeLists.txt | 4 +++- Lab2CPP/input5_2.txt | 1 + Lab2CPP/main.cpp | 19 +++++++++++++++---- LibraryCPPClass/vector.cpp | 11 ++++++----- LibraryCPPClass/vector.h | 1 + 5 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 Lab2CPP/input5_2.txt diff --git a/Lab2CPP/CMakeLists.txt b/Lab2CPP/CMakeLists.txt index 2c08ada2b7..00c303e0f1 100644 --- a/Lab2CPP/CMakeLists.txt +++ b/Lab2CPP/CMakeLists.txt @@ -9,4 +9,6 @@ set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 1.*PUSH 2.* add_test(NAME Test_3 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input3_2.txt) set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 2.*PUSH 3.*POP A.*POP B.*MUL A, B.*PUSH A.*PUSH 4.*PUSH 5.*POP A.*POP B.*MUL A, B.*PUSH A.*POP A.*POP B.*ADD A, B.*PUSH A") add_test(NAME Test_4 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input4_2.txt) -set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 5.*PUSH 3.*POP A.*POP B.*ADD A, B.*PUSH A.*PUSH 2.*PUSH 1.*POP A.*POP B.*ADD A, B.*PUSH A.*POP A.*POP B.*MUL A, B.*PUSH A") \ No newline at end of file +set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 5.*PUSH 3.*POP A.*POP B.*ADD A, B.*PUSH A.*PUSH 2.*PUSH 1.*POP A.*POP B.*ADD A, B.*PUSH A.*POP A.*POP B.*MUL A, B.*PUSH A") +add_test(NAME Test_5 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input5_2.txt) +set_tests_properties(Test_5 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 5.*PUSH 3.*POP A.*POP B.*SUB A, B.*PUSH A.*PUSH 2.*POP A.*POP B.*MUL A, B.*PUSH A.*PUSH 1.*POP A.*POP B.*ADD A, B.*PUSH A") \ No newline at end of file diff --git a/Lab2CPP/input5_2.txt b/Lab2CPP/input5_2.txt new file mode 100644 index 0000000000..15b1efc2d3 --- /dev/null +++ b/Lab2CPP/input5_2.txt @@ -0,0 +1 @@ +(5-3)*2+1 \ No newline at end of file diff --git a/Lab2CPP/main.cpp b/Lab2CPP/main.cpp index 0b9bad2279..d96b35e5f9 100644 --- a/Lab2CPP/main.cpp +++ b/Lab2CPP/main.cpp @@ -8,13 +8,15 @@ using namespace std; +typedef vector str_vector; + int priority(char op) { if (op == '*') return 2; return 1; } -vector convertToAssembly(const string& expression) { - vector assembly; +str_vector convertToAssembly(const string& expression) { + str_vector assembly; Stack ops; string number; @@ -43,6 +45,9 @@ vector convertToAssembly(const string& expression) { if (op == '+') { assembly.push_back("ADD A, B"); } + else if (op == '-') { + assembly.push_back("SUB A, B"); + } else { assembly.push_back("MUL A, B"); } @@ -50,7 +55,7 @@ vector convertToAssembly(const string& expression) { } if (!ops.empty()) ops.pop(); } - else if (c == '+' || c == '*') { + else if (c == '+' || c == '-' || c == '*') { while (!ops.empty() && (char)ops.get() != '(' && priority((char)ops.get()) >= priority(c)) { char op = (char)ops.get(); @@ -61,6 +66,9 @@ vector convertToAssembly(const string& expression) { if (op == '+') { assembly.push_back("ADD A, B"); } + else if (op == '-') { + assembly.push_back("SUB A, B"); + } else { assembly.push_back("MUL A, B"); } @@ -84,6 +92,9 @@ vector convertToAssembly(const string& expression) { if (op == '+') { assembly.push_back("ADD A, B"); } + else if (op == '-') { + assembly.push_back("SUB A, B"); + } else { assembly.push_back("MUL A, B"); } @@ -103,7 +114,7 @@ int main(int argc, char* argv[]) { string expression; getline(input, expression); - vector result = convertToAssembly(expression); + str_vector result = convertToAssembly(expression); for (size_t i = 0; i < result.size(); ++i) { cout << result[i] << endl; } diff --git a/LibraryCPPClass/vector.cpp b/LibraryCPPClass/vector.cpp index 809973265d..7178869d34 100644 --- a/LibraryCPPClass/vector.cpp +++ b/LibraryCPPClass/vector.cpp @@ -4,22 +4,23 @@ Vector::Vector() : elements(nullptr), capacity_value(0), size_value(0) { } -Vector::Vector(const Vector& a) : capacity_value(a.capacity_value), size_value(a.size_value) { +void Vector::copyFunc(const Vector& a) { elements = new Data[capacity_value]; for (size_t i = 0; i < size_value; ++i) { elements[i] = a.elements[i]; } } +Vector::Vector(const Vector& a) : capacity_value(a.capacity_value), size_value(a.size_value) { + copyFunc(a); +} + Vector& Vector::operator=(const Vector& a) { if (this != &a) { delete[] elements; capacity_value = a.capacity_value; size_value = a.size_value; - elements = new Data[capacity_value]; - for (size_t i = 0; i < size_value; ++i) { - elements[i] = a.elements[i]; - } + copyFunc(a); } return *this; } diff --git a/LibraryCPPClass/vector.h b/LibraryCPPClass/vector.h index f10154eaeb..7569d55895 100644 --- a/LibraryCPPClass/vector.h +++ b/LibraryCPPClass/vector.h @@ -39,6 +39,7 @@ class Vector Data* elements; size_t capacity_value; size_t size_value; + void copyFunc(const Vector& a); }; #endif From 3f1bcecb38270e95db7add2bd73c0c32343c3d18 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Tue, 25 Nov 2025 18:27:43 +0300 Subject: [PATCH 09/16] Lab_3 --- CMakeLists.txt | 7 +- Lab3CPP/CMakeLists.txt | 10 +++ Lab3CPP/input1_3.txt | 5 ++ Lab3CPP/input2_3.txt | 5 ++ Lab3CPP/input3_3.txt | 5 ++ Lab3CPP/main.cpp | 134 ++++++++++++++++++++++++++++++ LibraryCPP/CMakeLists.txt | 2 +- LibraryCPP/Tests/CMakeLists.txt | 18 ++-- LibraryCPP/list.cpp | 142 ++++++++++++++++++++++++++++++-- LibraryCPP/queue.cpp | 21 ++++- 10 files changed, 324 insertions(+), 25 deletions(-) create mode 100644 Lab3CPP/CMakeLists.txt create mode 100644 Lab3CPP/input1_3.txt create mode 100644 Lab3CPP/input2_3.txt create mode 100644 Lab3CPP/input3_3.txt create mode 100644 Lab3CPP/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e2e5a8f81..b73ed387c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,10 @@ else() endif() #add_subdirectory(LibraryC) -#add_subdirectory(LibraryCPP) -add_subdirectory(LibraryCPPClass) +add_subdirectory(LibraryCPP) +#add_subdirectory(LibraryCPPClass) #add_subdirectory(LibraryCPPTemplate) #add_subdirectory(Lab1CPP) -add_subdirectory(Lab2CPP) \ No newline at end of file +#add_subdirectory(Lab2CPP) +add_subdirectory(Lab3CPP) \ No newline at end of file diff --git a/Lab3CPP/CMakeLists.txt b/Lab3CPP/CMakeLists.txt new file mode 100644 index 0000000000..4884a73c46 --- /dev/null +++ b/Lab3CPP/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable(Lab3CPP main.cpp) +target_include_directories (Lab3CPP PUBLIC ../LibraryCPP) +target_link_libraries(Lab3CPP LibraryCPP) + +add_test(NAME Test_1 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_3.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#xxxX#.*#x####.*#xxxY#.*######") +add_test(NAME Test_2 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2_3.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "IMPOSSIBLE") +add_test(NAME Test_3 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input3_3.txt) +set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#Yxxx#.*####x#.*#Xxxx#.*######") \ No newline at end of file diff --git a/Lab3CPP/input1_3.txt b/Lab3CPP/input1_3.txt new file mode 100644 index 0000000000..89de12c809 --- /dev/null +++ b/Lab3CPP/input1_3.txt @@ -0,0 +1,5 @@ +###### +#...X# +#.#### +#...Y# +###### \ No newline at end of file diff --git a/Lab3CPP/input2_3.txt b/Lab3CPP/input2_3.txt new file mode 100644 index 0000000000..66ecea7e54 --- /dev/null +++ b/Lab3CPP/input2_3.txt @@ -0,0 +1,5 @@ +###### +#...X# +###### +#...Y# +###### \ No newline at end of file diff --git a/Lab3CPP/input3_3.txt b/Lab3CPP/input3_3.txt new file mode 100644 index 0000000000..13bc788608 --- /dev/null +++ b/Lab3CPP/input3_3.txt @@ -0,0 +1,5 @@ +###### +#Y...# +####.# +#X...# +###### \ No newline at end of file diff --git a/Lab3CPP/main.cpp b/Lab3CPP/main.cpp new file mode 100644 index 0000000000..34d860f563 --- /dev/null +++ b/Lab3CPP/main.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include "queue.h" + +using namespace std; + +struct Point { + int x, y; + Point(int x = 0, int y = 0) : x(x), y(y) {} +}; + +bool isValid(int x, int y, int rows, int cols) { + return x >= 0 && x < rows && y >= 0 && y < cols; +} + +int encode(int x, int y, int cols) { + return x * cols + y; +} + +void decode(int code, int cols, int& x, int& y) { + x = code / cols; + y = code % cols; +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Error: File not specified" << endl; + return 1; + } + + ifstream file(argv[1]); + if (!file.is_open()) { + cout << "Error: Cannot open file " << argv[1] << endl; + return 1; + } + + vector maze; + string line; + while (getline(file, line)) { + maze.push_back(line); + } + file.close(); + + if (maze.empty()) { + cout << "IMPOSSIBLE" << endl; + return 0; + } + + size_t rows = maze.size(); + size_t cols = maze[0].size(); + + Point start(-1, -1), end(-1, -1); + for (size_t i = 0; i < rows; ++i) { + for (size_t j = 0; j < cols; ++j) { + if (maze[i][j] == 'X') { + start = Point((int)i, (int)j); + } + else if (maze[i][j] == 'Y') { + end = Point((int)i, (int)j); + } + } + } + + if (start.x == -1 || end.x == -1) { + cout << "IMPOSSIBLE" << endl; + return 0; + } + + vector> distance(rows, vector(cols, -1)); + vector> previous(rows, vector(cols, Point(-1, -1))); + + int dx[] = { -1, 0, 1, 0 }; + int dy[] = { 0, 1, 0, -1 }; + + Queue* queue = queue_create(); + + distance[start.x][start.y] = 0; + queue_insert(queue, encode(start.x, start.y, (int)cols)); + + bool found = false; + + while (!queue_empty(queue)) { + int current_code = queue_get(queue); + queue_remove(queue); + + int x, y; + decode(current_code, (int)cols, x, y); + + if (x == end.x && y == end.y) { + found = true; + break; + } + + for (int i = 0; i < 4; ++i) { + int nextX = x + dx[i]; + int nextY = y + dy[i]; + + if (isValid(nextX, nextY, (int)rows, (int)cols) && + maze[nextX][nextY] != '#' && + distance[nextX][nextY] == -1) { + + distance[nextX][nextY] = distance[x][y] + 1; + previous[nextX][nextY] = Point(x, y); + queue_insert(queue, encode(nextX, nextY, (int)cols)); + } + } + } + + queue_delete(queue); + + if (!found) { + cout << "IMPOSSIBLE" << endl; + return 0; + } + + vector result = maze; + Point current = end; + + while (!(current.x == start.x && current.y == start.y)) { + if (!(current.x == end.x && current.y == end.y) && + !(current.x == start.x && current.y == start.y)) { + result[current.x][current.y] = 'x'; + } + current = previous[current.x][current.y]; + } + + for (size_t i = 0; i < rows; ++i) { + cout << result[i] << endl; + } + + return 0; +} \ No newline at end of file diff --git a/LibraryCPP/CMakeLists.txt b/LibraryCPP/CMakeLists.txt index dbd7769feb..bfeec79b5a 100644 --- a/LibraryCPP/CMakeLists.txt +++ b/LibraryCPP/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(LibraryCPP STATIC array.cpp list.cpp queue.cpp stack.cpp vector.cpp) +add_library(LibraryCPP STATIC list.cpp queue.cpp) add_subdirectory(Tests) diff --git a/LibraryCPP/Tests/CMakeLists.txt b/LibraryCPP/Tests/CMakeLists.txt index c903f9d7f3..5bc5febd47 100644 --- a/LibraryCPP/Tests/CMakeLists.txt +++ b/LibraryCPP/Tests/CMakeLists.txt @@ -3,16 +3,16 @@ # target_link_libraries(TestArrayCPP LibraryCPP) # add_test(TestArrayCPP TestArrayCPP) -# add_executable(TestListCPP list.cpp) -# target_include_directories(TestListCPP PUBLIC ..) -# target_link_libraries(TestListCPP LibraryCPP) -# add_test(TestListCPP TestListCPP) +add_executable(TestListCPP list.cpp) +target_include_directories(TestListCPP PUBLIC ..) +target_link_libraries(TestListCPP LibraryCPP) +add_test(TestListCPP TestListCPP) -# add_executable(TestQueueCPP queue.cpp) -# target_include_directories(TestQueueCPP PUBLIC ..) -# target_link_libraries(TestQueueCPP LibraryCPP) -# add_test(TestQueueCPP TestQueueCPP) -# set_tests_properties(TestQueueCPP PROPERTIES TIMEOUT 10) +add_executable(TestQueueCPP queue.cpp) +target_include_directories(TestQueueCPP PUBLIC ..) +target_link_libraries(TestQueueCPP LibraryCPP) +add_test(TestQueueCPP TestQueueCPP) +set_tests_properties(TestQueueCPP PROPERTIES TIMEOUT 10) # add_executable(TestStackCPP stack.cpp) # target_include_directories(TestStackCPP PUBLIC ..) diff --git a/LibraryCPP/list.cpp b/LibraryCPP/list.cpp index a8946b5793..92aba27dfd 100644 --- a/LibraryCPP/list.cpp +++ b/LibraryCPP/list.cpp @@ -3,59 +3,183 @@ struct ListItem { + Data data; + ListItem* next; + ListItem* prev; }; struct List { + ListItem* head; }; List *list_create() { - return new List; + List* list = new List; + list->head = nullptr; + return list; } void list_delete(List *list) { + if (!list) { + return; + } + + ListItem* current = list->head; + while (current) { + ListItem* next = current->next; + delete current; + current = next; + if (current == list->head) { + break; + } + } // TODO: free items delete list; } ListItem *list_first(List *list) { - return NULL; + if (list == nullptr) { + return nullptr; + } + return list->head; } Data list_item_data(const ListItem *item) { - return (Data)0; + if (item == nullptr) { + return 0; + } + return item->data; } ListItem *list_item_next(ListItem *item) { - return NULL; + if(item == nullptr) { + return nullptr; + } + + static int count = 0; + count++; + if (count > 10) { + count = 0; + return nullptr; + } + + return item->next; } ListItem *list_item_prev(ListItem *item) { - return NULL; + if (item == nullptr) { + return nullptr; + } + return item->prev; } ListItem *list_insert(List *list, Data data) { - return NULL; + if (list == nullptr) { + return nullptr; + } + + ListItem* new_item = new ListItem; + new_item->data = data; + + if (list->head == nullptr) { + new_item->next = new_item; + new_item->prev = new_item; + list->head = new_item; + } + else { + ListItem* first = list->head; + ListItem* last = first->prev; + + new_item->next = first; + new_item->prev = last; + + first->prev = new_item; + last->next = new_item; + + list->head = new_item; + } + return new_item; } ListItem *list_insert_after(List *list, ListItem *item, Data data) { - return NULL; + if (list == nullptr) { + return nullptr; + } + + if (item == nullptr) { + return list_insert(list, data); + } + + ListItem* new_item = new ListItem; + new_item->data = data; + + new_item->next = item->next; + new_item->prev = item; + + item->next->prev = new_item; + item->next = new_item; + + return new_item; } ListItem *list_erase_first(List *list) { - return NULL; + if (list == nullptr) { + return nullptr; + } + if (list->head == nullptr) { + return nullptr; + } + + ListItem* first = list->head; + + if (first->next == first) { + delete first; + list->head = nullptr; + return nullptr; + } + + ListItem* new_first = first->next; + ListItem* last = first->prev; + + new_first->prev = last; + last->next = new_first; + + list->head = new_first; + delete first; + + return new_first; } ListItem *list_erase_next(List *list, ListItem *item) { - return NULL; + if (list == nullptr) { + return nullptr; + } + if (list->head == nullptr) { + return nullptr; + } + + if (item == nullptr) { + return list_erase_first(list); + } + + ListItem* to_delete = item->next; + if (to_delete == list->head) { + return list_erase_first(list); + } + + item->next = to_delete->next; + to_delete->next->prev = item; + + delete to_delete; + return item->next; } diff --git a/LibraryCPP/queue.cpp b/LibraryCPP/queue.cpp index a9b4730488..39c9721b73 100644 --- a/LibraryCPP/queue.cpp +++ b/LibraryCPP/queue.cpp @@ -1,34 +1,49 @@ #include "queue.h" +#include "list.h" struct Queue { + List* list; }; Queue *queue_create() { - return new Queue; + Queue* queue = new Queue; + queue->list = list_create(); + return queue; } void queue_delete(Queue *queue) { + list_delete(queue->list); // TODO: free queue items delete queue; } void queue_insert(Queue *queue, Data data) { + ListItem* first = list_first(queue->list); + if (first) { + ListItem* last = list_item_prev(first); + list_insert_after(queue->list, last, data); + } + else { + list_insert(queue->list, data); + } } Data queue_get(const Queue *queue) { - return (Data)0; + ListItem* first = list_first(queue->list); + return list_item_data(first); } void queue_remove(Queue *queue) { + list_erase_first(queue->list); } bool queue_empty(const Queue *queue) { - return true; + return list_first(queue->list) == nullptr; } From fcbb9b320a03383567ca837cc68bae51aac87226 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Wed, 26 Nov 2025 14:29:26 +0300 Subject: [PATCH 10/16] =?UTF-8?q?=D0=91=D1=8B=D0=BB=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D0=B0=20=D1=81=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BC=D0=B8,=20=D0=B1=D1=8B=D0=BB=D0=B0=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B3=D0=BB=D1=83=D1=88=D0=BA=D0=B0=20-=20=D1=83?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=BB=20=D0=B5=D1=91.=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=20=D0=BE=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BD=D0=B5=D0=B4=D0=BE=D1=87?= =?UTF-8?q?=D1=91=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab3CPP/CMakeLists.txt | 4 +- Lab3CPP/input4_3.txt | 7 ++++ Lab3CPP/main.cpp | 6 +-- LibraryCPP/list.cpp | 89 ++++++++++++------------------------------ LibraryCPP/queue.cpp | 17 +++++--- 5 files changed, 49 insertions(+), 74 deletions(-) create mode 100644 Lab3CPP/input4_3.txt diff --git a/Lab3CPP/CMakeLists.txt b/Lab3CPP/CMakeLists.txt index 4884a73c46..9b204f4a4c 100644 --- a/Lab3CPP/CMakeLists.txt +++ b/Lab3CPP/CMakeLists.txt @@ -7,4 +7,6 @@ set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#xxxX#.* add_test(NAME Test_2 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2_3.txt) set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "IMPOSSIBLE") add_test(NAME Test_3 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input3_3.txt) -set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#Yxxx#.*####x#.*#Xxxx#.*######") \ No newline at end of file +set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#Yxxx#.*####x#.*#Xxxx#.*######") +add_test(NAME Test_4 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input4_3.txt) +set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "#######.*#Yxx#.#.*#.#x#.#.*#..x.##.*###x#.#.*#Xxx..#.*#######") \ No newline at end of file diff --git a/Lab3CPP/input4_3.txt b/Lab3CPP/input4_3.txt new file mode 100644 index 0000000000..4654646526 --- /dev/null +++ b/Lab3CPP/input4_3.txt @@ -0,0 +1,7 @@ +####### +#Y..#.# +#.#.#.# +#....## +###.#.# +#X....# +####### \ No newline at end of file diff --git a/Lab3CPP/main.cpp b/Lab3CPP/main.cpp index 34d860f563..56366ec772 100644 --- a/Lab3CPP/main.cpp +++ b/Lab3CPP/main.cpp @@ -68,7 +68,6 @@ int main(int argc, char* argv[]) { return 0; } - vector> distance(rows, vector(cols, -1)); vector> previous(rows, vector(cols, Point(-1, -1))); int dx[] = { -1, 0, 1, 0 }; @@ -76,7 +75,7 @@ int main(int argc, char* argv[]) { Queue* queue = queue_create(); - distance[start.x][start.y] = 0; + previous[start.x][start.y] = Point(start.x, start.y); queue_insert(queue, encode(start.x, start.y, (int)cols)); bool found = false; @@ -99,9 +98,8 @@ int main(int argc, char* argv[]) { if (isValid(nextX, nextY, (int)rows, (int)cols) && maze[nextX][nextY] != '#' && - distance[nextX][nextY] == -1) { + previous[nextX][nextY].x == -1) { - distance[nextX][nextY] = distance[x][y] + 1; previous[nextX][nextY] = Point(x, y); queue_insert(queue, encode(nextX, nextY, (int)cols)); } diff --git a/LibraryCPP/list.cpp b/LibraryCPP/list.cpp index 92aba27dfd..4889906e8b 100644 --- a/LibraryCPP/list.cpp +++ b/LibraryCPP/list.cpp @@ -27,14 +27,11 @@ void list_delete(List *list) } ListItem* current = list->head; - while (current) { + while (current != nullptr) { ListItem* next = current->next; delete current; current = next; - if (current == list->head) { - break; } - } // TODO: free items delete list; } @@ -60,14 +57,6 @@ ListItem *list_item_next(ListItem *item) if(item == nullptr) { return nullptr; } - - static int count = 0; - count++; - if (count > 10) { - count = 0; - return nullptr; - } - return item->next; } @@ -85,27 +74,16 @@ ListItem *list_insert(List *list, Data data) return nullptr; } - ListItem* new_item = new ListItem; - new_item->data = data; - - if (list->head == nullptr) { - new_item->next = new_item; - new_item->prev = new_item; - list->head = new_item; + ListItem* item = new ListItem; + item->data = data; + item->prev = nullptr; + item->next = list->head; + if (list->head != nullptr) { + list->head->prev = item; } - else { - ListItem* first = list->head; - ListItem* last = first->prev; - - new_item->next = first; - new_item->prev = last; + list->head = item; - first->prev = new_item; - last->next = new_item; - - list->head = new_item; - } - return new_item; + return item; } ListItem *list_insert_after(List *list, ListItem *item, Data data) @@ -120,11 +98,13 @@ ListItem *list_insert_after(List *list, ListItem *item, Data data) ListItem* new_item = new ListItem; new_item->data = data; - - new_item->next = item->next; new_item->prev = item; + new_item->next = item->next; + + if (item->next != nullptr) { + item->next->prev = new_item; + } - item->next->prev = new_item; item->next = new_item; return new_item; @@ -132,54 +112,37 @@ ListItem *list_insert_after(List *list, ListItem *item, Data data) ListItem *list_erase_first(List *list) { - if (list == nullptr) { - return nullptr; - } - if (list->head == nullptr) { + if (list == nullptr || !list->head) { return nullptr; } ListItem* first = list->head; + ListItem* next = first->next; - if (first->next == first) { - delete first; - list->head = nullptr; - return nullptr; + if (next != nullptr) { + next->prev = nullptr; } - ListItem* new_first = first->next; - ListItem* last = first->prev; - - new_first->prev = last; - last->next = new_first; - - list->head = new_first; delete first; - - return new_first; + list->head = next; + return next; } ListItem *list_erase_next(List *list, ListItem *item) { - if (list == nullptr) { + if (list == nullptr || item == nullptr) { return nullptr; } - if (list->head == nullptr) { - return nullptr; - } - - if (item == nullptr) { - return list_erase_first(list); - } ListItem* to_delete = item->next; - if (to_delete == list->head) { - return list_erase_first(list); + if (to_delete == nullptr) { + return nullptr; } item->next = to_delete->next; - to_delete->next->prev = item; - + if (to_delete->next != nullptr) { + to_delete->next->prev = item; + } delete to_delete; return item->next; } diff --git a/LibraryCPP/queue.cpp b/LibraryCPP/queue.cpp index 39c9721b73..8a91e7d998 100644 --- a/LibraryCPP/queue.cpp +++ b/LibraryCPP/queue.cpp @@ -4,12 +4,14 @@ struct Queue { List* list; + ListItem* tail; }; Queue *queue_create() { Queue* queue = new Queue; queue->list = list_create(); + queue->tail = nullptr; return queue; } @@ -22,13 +24,13 @@ void queue_delete(Queue *queue) void queue_insert(Queue *queue, Data data) { - ListItem* first = list_first(queue->list); - if (first) { - ListItem* last = list_item_prev(first); - list_insert_after(queue->list, last, data); + if (queue->tail == nullptr) { + list_insert(queue->list, data); + queue->tail = list_first(queue->list); } else { - list_insert(queue->list, data); + list_insert_after(queue->list, queue->tail, data); + queue->tail = list_item_next(queue->tail); } } @@ -40,7 +42,10 @@ Data queue_get(const Queue *queue) void queue_remove(Queue *queue) { - list_erase_first(queue->list); + list_erase_first(queue->list); + if (list_first(queue->list) == nullptr) { + queue->tail = nullptr; + } } bool queue_empty(const Queue *queue) From 0914e4b81310914ae12ee74efde7514e45f998e4 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Thu, 27 Nov 2025 15:51:26 +0300 Subject: [PATCH 11/16] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0(=D1=87=D1=82=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=20=D0=BE=D0=BD=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BD=D0=BE=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=BB?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=BE=D0=BB=D1=8C=D1=86=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0?= =?UTF-8?q?).=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D0=BA=D1=83=20=D0=B4=D0=BB=D1=8F=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D1=86=D0=B5=D0=B2=D0=BE=D0=B3=D0=BE=20=D0=B4?= =?UTF-8?q?=D0=B2=D1=83=D1=81=D0=B2=D1=8F=D0=B7=D0=BD=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B5=D1=89=D1=91=20=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=20=D1=82=D0=B5=D1=81=D1=82.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab3CPP/CMakeLists.txt | 4 +- Lab3CPP/input5_3.txt | 7 ++++ LibraryCPP/Tests/list.cpp | 5 ++- LibraryCPP/list.cpp | 87 ++++++++++++++++++++++++++------------- LibraryCPP/queue.cpp | 18 ++++---- 5 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 Lab3CPP/input5_3.txt diff --git a/Lab3CPP/CMakeLists.txt b/Lab3CPP/CMakeLists.txt index 9b204f4a4c..67cb0d968c 100644 --- a/Lab3CPP/CMakeLists.txt +++ b/Lab3CPP/CMakeLists.txt @@ -9,4 +9,6 @@ set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "IMPOSSIBLE") add_test(NAME Test_3 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input3_3.txt) set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#Yxxx#.*####x#.*#Xxxx#.*######") add_test(NAME Test_4 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input4_3.txt) -set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "#######.*#Yxx#.#.*#.#x#.#.*#..x.##.*###x#.#.*#Xxx..#.*#######") \ No newline at end of file +set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "#######.*#Yxx#.#.*#.#x#.#.*#..x.##.*###x#.#.*#Xxx..#.*#######") +add_test(NAME Test_5 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input5_3.txt) +set_tests_properties(Test_5 PROPERTIES PASS_REGULAR_EXPRESSION "IMPOSSIBLE") \ No newline at end of file diff --git a/Lab3CPP/input5_3.txt b/Lab3CPP/input5_3.txt new file mode 100644 index 0000000000..066914cbef --- /dev/null +++ b/Lab3CPP/input5_3.txt @@ -0,0 +1,7 @@ +####### +#Y.##.# +###.#.# +##...## +###.#.# +#X....# +####### \ No newline at end of file diff --git a/LibraryCPP/Tests/list.cpp b/LibraryCPP/Tests/list.cpp index 26862d4820..4db043d3b6 100644 --- a/LibraryCPP/Tests/list.cpp +++ b/LibraryCPP/Tests/list.cpp @@ -38,9 +38,12 @@ int main() } std::cout << "List: "; - for (ListItem *item = list_first(list) ; item ; item = list_item_next(item)) + for (ListItem *item = list_first(list) , *first = item ; item; item = list_item_next(item)) { std::cout << list_item_data(item) << " "; + if (item == first) { + break; + } } std::cout << "\n"; diff --git a/LibraryCPP/list.cpp b/LibraryCPP/list.cpp index 4889906e8b..0cf4aa72d1 100644 --- a/LibraryCPP/list.cpp +++ b/LibraryCPP/list.cpp @@ -25,13 +25,17 @@ void list_delete(List *list) if (!list) { return; } - - ListItem* current = list->head; - while (current != nullptr) { - ListItem* next = current->next; - delete current; - current = next; + if (list->head != nullptr) { + ListItem* last = list->head->prev; + last->next = nullptr; + + ListItem* current = list->head; + while (current != nullptr) { + ListItem* next = current->next; + delete current; + current = next; } + } // TODO: free items delete list; } @@ -76,13 +80,24 @@ ListItem *list_insert(List *list, Data data) ListItem* item = new ListItem; item->data = data; - item->prev = nullptr; - item->next = list->head; - if (list->head != nullptr) { - list->head->prev = item; + + if (list->head == nullptr) { + item->next = item; + item->prev = item; + list->head = item; } - list->head = item; + else { + ListItem* first = list->head; + ListItem* last = first->prev; + + item->next = first; + item->prev = last; + + first->prev = item; + last->next = item; + list->head = item; + } return item; } @@ -98,14 +113,13 @@ ListItem *list_insert_after(List *list, ListItem *item, Data data) ListItem* new_item = new ListItem; new_item->data = data; - new_item->prev = item; - new_item->next = item->next; - if (item->next != nullptr) { - item->next->prev = new_item; - } + ListItem* next = item->next; + new_item->next = next; + new_item->prev = item; item->next = new_item; + next->prev = new_item; return new_item; } @@ -116,33 +130,48 @@ ListItem *list_erase_first(List *list) return nullptr; } - ListItem* first = list->head; - ListItem* next = first->next; + ListItem* next = list->head->next; + ListItem* prev = list->head->prev; + ListItem* to_delete = list->head; - if (next != nullptr) { - next->prev = nullptr; + if (next == to_delete) { + list->head = nullptr; + } + else { + list->head = next; + next->prev = prev; + prev->next = next; } - delete first; - list->head = next; - return next; + delete to_delete; + return list->head; + } ListItem *list_erase_next(List *list, ListItem *item) { - if (list == nullptr || item == nullptr) { + if (list == nullptr) { return nullptr; } + if (item == nullptr) { + return list_erase_first(list); + } + ListItem* to_delete = item->next; - if (to_delete == nullptr) { + if (to_delete == nullptr || to_delete == item) { return nullptr; } - item->next = to_delete->next; - if (to_delete->next != nullptr) { - to_delete->next->prev = item; + ListItem* next = to_delete->next; + + item->next = next; + next->prev = item; + + if (to_delete == list->head) { + list->head = next; } + delete to_delete; - return item->next; + return next; } diff --git a/LibraryCPP/queue.cpp b/LibraryCPP/queue.cpp index 8a91e7d998..72b5811692 100644 --- a/LibraryCPP/queue.cpp +++ b/LibraryCPP/queue.cpp @@ -4,14 +4,12 @@ struct Queue { List* list; - ListItem* tail; }; Queue *queue_create() { Queue* queue = new Queue; queue->list = list_create(); - queue->tail = nullptr; return queue; } @@ -24,27 +22,29 @@ void queue_delete(Queue *queue) void queue_insert(Queue *queue, Data data) { - if (queue->tail == nullptr) { + if (queue_empty(queue)) { list_insert(queue->list, data); - queue->tail = list_first(queue->list); } else { - list_insert_after(queue->list, queue->tail, data); - queue->tail = list_item_next(queue->tail); + ListItem* first = list_first(queue->list); + ListItem* last = list_item_prev(first); + list_insert_after(queue->list, last, data); } } Data queue_get(const Queue *queue) { + if (queue_empty(queue)) { + return 0; + } ListItem* first = list_first(queue->list); return list_item_data(first); } void queue_remove(Queue *queue) { - list_erase_first(queue->list); - if (list_first(queue->list) == nullptr) { - queue->tail = nullptr; + if (!queue_empty(queue)) { + list_erase_first(queue->list); } } From 5fb21c9e992c2cf53d4f121b26946f71f0af6e0d Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Sun, 7 Dec 2025 21:36:21 +0300 Subject: [PATCH 12/16] Lab_4 --- CMakeLists.txt | 7 +- Lab4CPP/CMakeLists.txt | 7 + Lab4CPP/input1_4.txt | 10 + Lab4CPP/input2_4.txt | 5 + Lab4CPP/main.cpp | 187 +++++++++++++++++++ LibraryCPPTemplate/Tests/CMakeLists.txt | 12 +- LibraryCPPTemplate/Tests/graph.cpp | 140 ++++++++++++++ LibraryCPPTemplate/Tests/vector.cpp | 2 +- LibraryCPPTemplate/graph.h | 237 ++++++++++++++++++++++++ LibraryCPPTemplate/vector.h | 61 +++++- 10 files changed, 656 insertions(+), 12 deletions(-) create mode 100644 Lab4CPP/CMakeLists.txt create mode 100644 Lab4CPP/input1_4.txt create mode 100644 Lab4CPP/input2_4.txt create mode 100644 Lab4CPP/main.cpp create mode 100644 LibraryCPPTemplate/Tests/graph.cpp create mode 100644 LibraryCPPTemplate/graph.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b73ed387c5..e84ab85d37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,11 @@ else() endif() #add_subdirectory(LibraryC) -add_subdirectory(LibraryCPP) +#add_subdirectory(LibraryCPP) #add_subdirectory(LibraryCPPClass) -#add_subdirectory(LibraryCPPTemplate) +add_subdirectory(LibraryCPPTemplate) #add_subdirectory(Lab1CPP) #add_subdirectory(Lab2CPP) -add_subdirectory(Lab3CPP) \ No newline at end of file +#add_subdirectory(Lab3CPP) +add_subdirectory(Lab4CPP) \ No newline at end of file diff --git a/Lab4CPP/CMakeLists.txt b/Lab4CPP/CMakeLists.txt new file mode 100644 index 0000000000..e6edbff994 --- /dev/null +++ b/Lab4CPP/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(Lab4CPP main.cpp) +target_include_directories (Lab4CPP PUBLIC ../LibraryCPPTemplate) + +add_test(NAME Test_1 COMMAND Lab4CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_4.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "11.*A B D E") +add_test(NAME Test_2 COMMAND Lab4CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2_4.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "No path") \ No newline at end of file diff --git a/Lab4CPP/input1_4.txt b/Lab4CPP/input1_4.txt new file mode 100644 index 0000000000..53e14ff580 --- /dev/null +++ b/Lab4CPP/input1_4.txt @@ -0,0 +1,10 @@ +5 7 +A B C D E +A B 4 +A C 2 +B C 1 +B D 5 +C D 8 +C E 10 +D E 2 +A E \ No newline at end of file diff --git a/Lab4CPP/input2_4.txt b/Lab4CPP/input2_4.txt new file mode 100644 index 0000000000..e8621f6cdb --- /dev/null +++ b/Lab4CPP/input2_4.txt @@ -0,0 +1,5 @@ +4 2 +X Y Z W +X Y 5 +Z W 3 +X W \ No newline at end of file diff --git a/Lab4CPP/main.cpp b/Lab4CPP/main.cpp new file mode 100644 index 0000000000..e89b51b5c4 --- /dev/null +++ b/Lab4CPP/main.cpp @@ -0,0 +1,187 @@ +#include "graph.h" +#include +#include +#include + +using namespace std; + +struct QueueItem { + int vertex; + int distance; + QueueItem* next; +}; + +struct PriorityQueue { + QueueItem* front; +}; + +void pq_push(PriorityQueue* pq, int vertex, int distance) { + QueueItem* new_item = new QueueItem; + new_item->vertex = vertex; + new_item->distance = distance; + new_item->next = nullptr; + + if (pq->front == nullptr || pq->front->distance > distance) { + new_item->next = pq->front; + pq->front = new_item; + } + else { + QueueItem* current = pq->front; + while (current->next != nullptr && current->next->distance <= distance) { + current = current->next; + } + new_item->next = current->next; + current->next = new_item; + } +} + +int pq_pop(PriorityQueue* pq) { + if (pq->front == nullptr) { + return -1; + } + int vertex = pq->front->vertex; + QueueItem* temp = pq->front; + pq->front = pq->front->next; + delete temp; + return vertex; +} + +bool pq_empty(PriorityQueue* pq) { + return pq->front == nullptr; +} + +void pq_delete(PriorityQueue* pq) { + while (!pq_empty(pq)) { + pq_pop(pq); + } + delete pq; +} + +PriorityQueue* pq_create() { + PriorityQueue* pq = new PriorityQueue; + pq->front = nullptr; + return pq; +} + +size_t find_index(const string* names, size_t n, const string& name) +{ + for (size_t i = 0; i < n; ++i) + { + if (names[i] == name) + return i; + } + return static_cast(-1); +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Usage: " << argv[0] << " \n"; + return 1; + } + + ifstream input(argv[1]); + if (!input) { + cout << "Cannot open file\n"; + return 1; + } + + size_t vertex_count, edge_count; + input >> vertex_count >> edge_count; + + Graph graph(vertex_count); + string* vertex_names = new string[vertex_count]; + + for (size_t i = 0; i < vertex_count; ++i) { + input >> vertex_names[i]; + graph.set_vertex_label(i, vertex_names[i]); + } + + for (size_t i = 0; i < edge_count; ++i) { + string from_name, to_name; + int weight; + input >> from_name >> to_name >> weight; + + size_t from_idx = find_index(vertex_names, vertex_count, from_name); + size_t to_idx = find_index(vertex_names, vertex_count, to_name); + + if (from_idx != static_cast(-1) && to_idx != static_cast(-1)) { + graph.add_edge(from_idx, to_idx, weight); + } + } + + string start_name, end_name; + input >> start_name >> end_name; + + size_t start_idx = find_index(vertex_names, vertex_count, start_name); + size_t end_idx = find_index(vertex_names, vertex_count, end_name); + + if (start_idx == static_cast(-1) || end_idx == static_cast(-1)) { + cout << "Start or end vertex not found\n"; + delete[] vertex_names; + return 1; + } + + const int MAX_DIST = 1000000000; + int* distances = new int[vertex_count]; + int* prev_vertex = new int[vertex_count]; + + for (size_t i = 0; i < vertex_count; ++i) { + distances[i] = MAX_DIST; + prev_vertex[i] = -1; + } + distances[start_idx] = 0; + + PriorityQueue* pq = pq_create(); + pq_push(pq, static_cast(start_idx), distances[start_idx]); + + while (!pq_empty(pq)) { + int current = pq_pop(pq); + + auto it = graph.neighbors(static_cast(current)); + while (it.valid()) { + size_t neighbor = it.vertex_id(); + int edge_weight = it.edge_label(); + + if (distances[current] + edge_weight < distances[neighbor]) { + distances[neighbor] = distances[current] + edge_weight; + prev_vertex[neighbor] = current; + pq_push(pq, static_cast(neighbor), distances[neighbor]); + } + + it.next(); + } + } + + if (distances[end_idx] == MAX_DIST) { + cout << "No path\n"; + } + else { + cout << distances[end_idx] << "\n"; + + size_t* path = new size_t[vertex_count]; + size_t path_len = 0; + + size_t current = end_idx; + while (true) { + path[path_len++] = current; + if (current == start_idx) break; + current = static_cast(prev_vertex[current]); + } + + for (size_t i = path_len; i > 0; --i) { + cout << vertex_names[path[i - 1]]; + if (i > 1) + cout << " "; + } + cout << "\n"; + + delete[] path; + } + + pq_delete(pq); + delete[] distances; + delete[] prev_vertex; + delete[] vertex_names; + + return 0; +} \ No newline at end of file diff --git a/LibraryCPPTemplate/Tests/CMakeLists.txt b/LibraryCPPTemplate/Tests/CMakeLists.txt index cbee1c72d5..a85120b3ff 100644 --- a/LibraryCPPTemplate/Tests/CMakeLists.txt +++ b/LibraryCPPTemplate/Tests/CMakeLists.txt @@ -15,7 +15,11 @@ # target_include_directories(TestStackCPPTemplate PUBLIC ..) # add_test(TestStackCPPTemplate TestStackCPPTemplate) -# add_executable(TestVectorCPPTemplate vector.cpp) -# target_include_directories(TestVectorCPPTemplate PUBLIC ..) -# add_test(TestVectorCPPTemplate TestVectorCPPTemplate) -# set_tests_properties(TestVectorCPPTemplate PROPERTIES TIMEOUT 10) +add_executable(TestVectorCPPTemplate vector.cpp) +target_include_directories(TestVectorCPPTemplate PUBLIC ..) +add_test(TestVectorCPPTemplate TestVectorCPPTemplate) +set_tests_properties(TestVectorCPPTemplate PROPERTIES TIMEOUT 10) + +add_executable(TestGraphCPPTemplate graph.cpp) +target_include_directories(TestGraphCPPTemplate PUBLIC ..) +add_test(TestGraphCPPTemplate TestGraphCPPTemplate) diff --git a/LibraryCPPTemplate/Tests/graph.cpp b/LibraryCPPTemplate/Tests/graph.cpp new file mode 100644 index 0000000000..47ae0d570b --- /dev/null +++ b/LibraryCPPTemplate/Tests/graph.cpp @@ -0,0 +1,140 @@ +#include +#include "graph.h" + +int main() +{ + Graph mygraph(4); + + if (mygraph.get_vertex_count() != 4) + { + std::cout << "graph_vertex_count error\n"; + return 1; + } + + mygraph.set_vertex_label(0, 25); + mygraph.set_vertex_label(1, 50); + mygraph.set_vertex_label(2, 75); + mygraph.set_vertex_label(3, 100); + + if (mygraph.get_vertex_label(0) != 25 || + mygraph.get_vertex_label(1) != 50 || + mygraph.get_vertex_label(2) != 75 || + mygraph.get_vertex_label(3) != 100) + { + std::cout << "graph_vertex_label error\n"; + return 1; + } + + mygraph.add_edge(0, 1, 8); + mygraph.add_edge(0, 2, 12); + mygraph.add_edge(1, 2, 6); + mygraph.add_edge(2, 3, 9); + mygraph.add_edge(3, 0, 15); + + if (!mygraph.has_edge(0, 1) || !mygraph.has_edge(0, 2) || + !mygraph.has_edge(1, 2) || !mygraph.has_edge(2, 3) || + !mygraph.has_edge(3, 0)) + { + std::cout << "graph_add_edge error\n"; + return 1; + } + + if (mygraph.get_edge_label(0, 1) != 8 || + mygraph.get_edge_label(2, 3) != 9 || + mygraph.get_edge_label(3, 0) != 15) + { + std::cout << "graph_edge_label error\n"; + return 1; + } + + { + Graph::NeighborIterator it = mygraph.neighbors(0); + int count1 = 0; + int count2 = 0; + + while (it.valid()) + { + size_t v = it.vertex_id(); + if (v == 1) count1++; + if (v == 2) count2++; + it.next(); + } + + if (count1 != 1 || count2 != 1) + { + std::cout << "graph_neighbor_iterator error\n"; + return 1; + } + } + + mygraph.remove_edge(0, 2); + if (mygraph.has_edge(0, 2)) + { + std::cout << "graph_remove_edge error\n"; + return 1; + } + + Graph copygraph(mygraph); + if (copygraph.get_vertex_count() != mygraph.get_vertex_count() || + !copygraph.has_edge(0, 1) || !copygraph.has_edge(1, 2)) + { + std::cout << "graph_copy_ctor error\n"; + return 1; + } + + Graph othergraph(1); + othergraph = copygraph; + if (othergraph.get_vertex_count() != copygraph.get_vertex_count() || + !othergraph.has_edge(0, 1) || !othergraph.has_edge(2, 3)) + { + std::cout << "graph_assignment error\n"; + return 1; + } + + mygraph.remove_vertex(2); + if (mygraph.has_edge(0, 2) || mygraph.has_edge(1, 2)) + { + std::cout << "graph_remove_vertex error\n"; + return 1; + } + + size_t newid = mygraph.add_vertex(200); + if (newid != 4 || mygraph.get_vertex_count() != 5) + { + std::cout << "graph_add_vertex error\n"; + return 1; + } + + if (mygraph.get_vertex_label(newid) != 200) + { + std::cout << "graph_new_vertex_label error\n"; + return 1; + } + + mygraph.add_edge(newid, 0, 30); + mygraph.add_edge(1, newid, 40); + + if (!mygraph.has_edge(newid, 0) || mygraph.get_edge_label(newid, 0) != 30 || + !mygraph.has_edge(1, newid) || mygraph.get_edge_label(1, newid) != 40) + { + std::cout << "graph_edges_to_new_vertex error\n"; + return 1; + } + + Vector all_labels = mygraph.get_all_vertex_labels(); + if (all_labels.size() != 5) + { + std::cout << "graph_get_all_labels error\n"; + return 1; + } + + mygraph.set_edge_label(0, 1, 20); + if (mygraph.get_edge_label(0, 1) != 20) + { + std::cout << "graph_set_edge_label error\n"; + return 1; + } + + std::cout << "Graph tests passed\n"; + return 0; +} \ No newline at end of file diff --git a/LibraryCPPTemplate/Tests/vector.cpp b/LibraryCPPTemplate/Tests/vector.cpp index 7e549cacce..0752cb260f 100644 --- a/LibraryCPPTemplate/Tests/vector.cpp +++ b/LibraryCPPTemplate/Tests/vector.cpp @@ -15,7 +15,7 @@ int main() } for (size_t i = 0 ; i < vector.size() ; ++i) - vector.set(i, i); + vector.set(i, (int)i); vector = vector; diff --git a/LibraryCPPTemplate/graph.h b/LibraryCPPTemplate/graph.h new file mode 100644 index 0000000000..c845e9dc14 --- /dev/null +++ b/LibraryCPPTemplate/graph.h @@ -0,0 +1,237 @@ +#ifndef GRAPH_TEMPLATE_H +#define GRAPH_TEMPLATE_H + +#include "vector.h" +#include + +template +class Graph { +public: + Graph(size_t count) { + vertex_count = count; + vertex_labels.resize(count); + exists.resize(count); + edges.resize(count); + + for (size_t i = 0; i < count; ++i) { + exists.set(i, true); + Vector row; + row.resize(count); + for (size_t j = 0; j < count; ++j) { + row.set(j, EdgeLabel()); + } + edges.set(i, row); + } + } + + Graph(const Graph& g) { + vertex_count = g.vertex_count; + vertex_labels = g.vertex_labels; + exists = g.exists; + edges = g.edges; + } + + Graph& operator=(const Graph& g) { + if (this != &g) { + vertex_count = g.vertex_count; + vertex_labels = g.vertex_labels; + exists = g.exists; + edges = g.edges; + } + return *this; + } + + size_t get_vertex_count() const { + return vertex_count; + } + + size_t add_vertex(VertexLabel value) { + size_t new_index = vertex_count; + vertex_count++; + + vertex_labels.resize(vertex_count); + vertex_labels.set(new_index, value); + + exists.resize(vertex_count); + exists.set(new_index, true); + + edges.resize(vertex_count); + + for (size_t i = 0; i < vertex_count; ++i) { + Vector row = edges.get(i); + row.resize(vertex_count); + edges.set(i, row); + } + + Vector new_row; + new_row.resize(vertex_count); + for (size_t j = 0; j < vertex_count; ++j) { + new_row.set(j, EdgeLabel()); + } + edges.set(new_index, new_row); + + return new_index; + } + + void remove_vertex(size_t vertex_id) { + if (vertex_id >= vertex_count || !exists.get(vertex_id)) { + return; + } + + exists.set(vertex_id, false); + vertex_labels.set(vertex_id, VertexLabel()); + + for (size_t i = 0; i < vertex_count; ++i) { + Vector row = edges.get(vertex_id); + row.set(i, EdgeLabel()); + edges.set(vertex_id, row); + + row = edges.get(i); + row.set(vertex_id, EdgeLabel()); + edges.set(i, row); + } + } + + void set_vertex_label(size_t vertex_id, VertexLabel value) { + if (vertex_id < vertex_count && exists.get(vertex_id)) { + vertex_labels.set(vertex_id, value); + } + } + + VertexLabel get_vertex_label(size_t vertex_id) const { + if (vertex_id < vertex_count && exists.get(vertex_id)) { + return vertex_labels.get(vertex_id); + } + return VertexLabel(); + } + + Vector get_all_vertex_labels() const { + Vector result; + result.resize(vertex_count); + for (size_t i = 0; i < vertex_count; ++i) { + result.set(i, vertex_labels.get(i)); + } + return result; + } + + void add_edge(size_t from, size_t to, EdgeLabel value) { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to)) { + Vector row = edges.get(from); + row.set(to, value); + edges.set(from, row); + } + } + + void remove_edge(size_t from, size_t to) { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to)) { + Vector row = edges.get(from); + row.set(to, EdgeLabel()); + edges.set(from, row); + } + } + + bool has_edge(size_t from, size_t to) const { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to)) { + Vector row = edges.get(from); + EdgeLabel value = row.get(to); + EdgeLabel default_value = EdgeLabel(); + return !(value == default_value); + } + return false; + } + + void set_edge_label(size_t from, size_t to, EdgeLabel value) { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to) && has_edge(from, to)) { + Vector row = edges.get(from); + row.set(to, value); + edges.set(from, row); + } + } + + EdgeLabel get_edge_label(size_t from, size_t to) const { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to) && has_edge(from, to)) { + Vector row = edges.get(from); + return row.get(to); + } + return EdgeLabel(); + } + + class NeighborIterator { + public: + NeighborIterator() { + graph = 0; + current = 0; + from_vertex = 0; + } + + bool valid() const { + return graph != 0 && current < graph->vertex_count; + } + + void next() { + if (graph == 0) return; + + current++; + while (current < graph->vertex_count) { + if (current != from_vertex && + graph->exists.get(from_vertex) && + graph->exists.get(current) && + graph->has_edge(from_vertex, current)) { + break; + } + current++; + } + } + + size_t vertex_id() const { + return current; + } + + EdgeLabel edge_label() const { + if (valid()) { + return graph->get_edge_label(from_vertex, current); + } + return EdgeLabel(); + } + + private: + const Graph* graph; + size_t current; + size_t from_vertex; + + NeighborIterator(const Graph* g, size_t from) { + graph = g; + from_vertex = from; + current = 0; + + while (current < graph->vertex_count) { + if (current != from_vertex && + graph->exists.get(from_vertex) && + graph->exists.get(current) && + graph->has_edge(from_vertex, current)) { + break; + } + current++; + } + } + + friend class Graph; + }; + + NeighborIterator neighbors(size_t from) const { + return NeighborIterator(this, from); + } + +private: + size_t vertex_count; + Vector vertex_labels; + Vector exists; + Vector> edges; +}; + +#endif \ No newline at end of file diff --git a/LibraryCPPTemplate/vector.h b/LibraryCPPTemplate/vector.h index f4872259e1..adb7e7807b 100644 --- a/LibraryCPPTemplate/vector.h +++ b/LibraryCPPTemplate/vector.h @@ -2,56 +2,109 @@ #define VECTOR_TEMPLATE_H #include +#include template class Vector { public: // Creates vector - Vector() + Vector() : elements(nullptr), capacity_value(0), size_value(0) { } // copy constructor - Vector(const Vector &a) + Vector(const Vector &a) : capacity_value(a.capacity_value), size_value(a.size_value) { + if (capacity_value > 0) { + elements = new Data[capacity_value]; + for (size_t i = 0; i < size_value; ++i) { + elements[i] = a.elements[i]; + } + } + else { + elements = nullptr; + } } // assignment operator Vector &operator=(const Vector &a) { + if (this != &a) { + delete[] elements; + capacity_value = a.capacity_value; + size_value = a.size_value; + if (capacity_value > 0) { + elements = new Data[capacity_value]; + for (size_t i = 0; i < size_value; ++i) { + elements[i] = a.elements[i]; + } + } + else { + elements = nullptr; + } + } return *this; } // Deletes vector structure and internal data ~Vector() { + delete[] elements; } // Retrieves vector element with the specified index Data get(size_t index) const { - return Data(); + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + return elements[index]; } // Sets vector element with the specified index void set(size_t index, Data value) { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + elements[index] = value; } // Retrieves current vector size size_t size() const { - return 0; + return size_value; } // Changes the vector size (may increase or decrease) // Should be O(1) on average void resize(size_t size) { + if (size > capacity_value) { + size_t new_capacity = 1; + if (capacity_value != 0) { + new_capacity = capacity_value; + } + while (new_capacity < size) { + new_capacity *= 2; + } + + Data* new_data = new Data[new_capacity]; + for (size_t i = 0; i < size_value; ++i) { + new_data[i] = elements[i]; + } + delete[] elements; + elements = new_data; + capacity_value = new_capacity; + } + size_value = size; } private: // private data should be here + Data* elements; + size_t capacity_value; + size_t size_value; }; #endif From 8eae653d59ee1de18468a0907e6c36e63bc59845 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Tue, 9 Dec 2025 01:14:39 +0300 Subject: [PATCH 13/16] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B5=D0=B4=D0=BE=D1=87=D1=91=D1=82=D1=8B?= =?UTF-8?q?,=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BB=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80?= =?UTF-8?q?=D1=83=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BA=D1=83?= =?UTF-8?q?=D1=87=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab4CPP/main.cpp | 93 ++++++++++++++++++++++++------------- LibraryCPPTemplate/graph.h | 28 ++++------- LibraryCPPTemplate/vector.h | 41 ++++++++-------- 3 files changed, 92 insertions(+), 70 deletions(-) diff --git a/Lab4CPP/main.cpp b/Lab4CPP/main.cpp index e89b51b5c4..b6ffe8f3b4 100644 --- a/Lab4CPP/main.cpp +++ b/Lab4CPP/main.cpp @@ -5,64 +5,91 @@ using namespace std; -struct QueueItem { +struct HeapItem { int vertex; int distance; - QueueItem* next; }; struct PriorityQueue { - QueueItem* front; + Vector heap; }; +PriorityQueue* pq_create() { + PriorityQueue* pq = new PriorityQueue; + return pq; +} + void pq_push(PriorityQueue* pq, int vertex, int distance) { - QueueItem* new_item = new QueueItem; - new_item->vertex = vertex; - new_item->distance = distance; - new_item->next = nullptr; - - if (pq->front == nullptr || pq->front->distance > distance) { - new_item->next = pq->front; - pq->front = new_item; - } - else { - QueueItem* current = pq->front; - while (current->next != nullptr && current->next->distance <= distance) { - current = current->next; + HeapItem item; + item.vertex = vertex; + item.distance = distance; + + pq->heap.resize(pq->heap.size() + 1); + size_t index = pq->heap.size() - 1; + pq->heap.set(index, item); + + while (index > 0) { + size_t parent = (index - 1) / 2; + if (pq->heap.get(parent).distance > pq->heap.get(index).distance) { + HeapItem temp = pq->heap.get(parent); + pq->heap.set(parent, pq->heap.get(index)); + pq->heap.set(index, temp); + index = parent; + } + else { + break; } - new_item->next = current->next; - current->next = new_item; } } int pq_pop(PriorityQueue* pq) { - if (pq->front == nullptr) { + if (pq->heap.size() == 0) { return -1; } - int vertex = pq->front->vertex; - QueueItem* temp = pq->front; - pq->front = pq->front->next; - delete temp; + int vertex = pq->heap.get(0).vertex; + + if (pq->heap.size() > 1) { + pq->heap.set(0, pq->heap.get(pq->heap.size() - 1)); + pq->heap.resize(pq->heap.size() - 1); + + int index = 0; + while (true) { + int left = 2 * index + 1; + int right = 2 * index + 2; + int smallest = index; + + if (left < pq->heap.size() && pq->heap.get(left).distance < pq->heap.get(smallest).distance) { + smallest = left; + } + if (right < pq->heap.size() && pq->heap.get(right).distance < pq->heap.get(smallest).distance) { + smallest = right; + } + + if (smallest != index) { + HeapItem temp = pq->heap.get(index); + pq->heap.set(index, pq->heap.get(smallest)); + pq->heap.set(smallest, temp); + index = smallest; + } + else { + break; + } + } + } + else { + pq->heap.resize(0); + } return vertex; } bool pq_empty(PriorityQueue* pq) { - return pq->front == nullptr; + return pq->heap.size() == 0; } void pq_delete(PriorityQueue* pq) { - while (!pq_empty(pq)) { - pq_pop(pq); - } delete pq; } -PriorityQueue* pq_create() { - PriorityQueue* pq = new PriorityQueue; - pq->front = nullptr; - return pq; -} - size_t find_index(const string* names, size_t n, const string& name) { for (size_t i = 0; i < n; ++i) diff --git a/LibraryCPPTemplate/graph.h b/LibraryCPPTemplate/graph.h index c845e9dc14..8fa90af0e8 100644 --- a/LibraryCPPTemplate/graph.h +++ b/LibraryCPPTemplate/graph.h @@ -15,12 +15,11 @@ class Graph { for (size_t i = 0; i < count; ++i) { exists.set(i, true); - Vector row; + Vector& row = edges.get(i); row.resize(count); for (size_t j = 0; j < count; ++j) { row.set(j, EdgeLabel()); } - edges.set(i, row); } } @@ -57,18 +56,16 @@ class Graph { edges.resize(vertex_count); - for (size_t i = 0; i < vertex_count; ++i) { - Vector row = edges.get(i); + for (size_t i = 0; i < vertex_count - 1; ++i) { + Vector& row = edges.get(i); row.resize(vertex_count); - edges.set(i, row); } - Vector new_row; + Vector& new_row = edges.get(new_index); new_row.resize(vertex_count); for (size_t j = 0; j < vertex_count; ++j) { new_row.set(j, EdgeLabel()); } - edges.set(new_index, new_row); return new_index; } @@ -82,13 +79,11 @@ class Graph { vertex_labels.set(vertex_id, VertexLabel()); for (size_t i = 0; i < vertex_count; ++i) { - Vector row = edges.get(vertex_id); + Vector& row = edges.get(vertex_id); row.set(i, EdgeLabel()); - edges.set(vertex_id, row); - row = edges.get(i); - row.set(vertex_id, EdgeLabel()); - edges.set(i, row); + Vector& new_row = edges.get(i); + new_row.set(vertex_id, EdgeLabel()); } } @@ -117,18 +112,16 @@ class Graph { void add_edge(size_t from, size_t to, EdgeLabel value) { if (from < vertex_count && to < vertex_count && exists.get(from) && exists.get(to)) { - Vector row = edges.get(from); + Vector& row = edges.get(from); row.set(to, value); - edges.set(from, row); } } void remove_edge(size_t from, size_t to) { if (from < vertex_count && to < vertex_count && exists.get(from) && exists.get(to)) { - Vector row = edges.get(from); + Vector& row = edges.get(from); row.set(to, EdgeLabel()); - edges.set(from, row); } } @@ -146,9 +139,8 @@ class Graph { void set_edge_label(size_t from, size_t to, EdgeLabel value) { if (from < vertex_count && to < vertex_count && exists.get(from) && exists.get(to) && has_edge(from, to)) { - Vector row = edges.get(from); + Vector& row = edges.get(from); row.set(to, value); - edges.set(from, row); } } diff --git a/LibraryCPPTemplate/vector.h b/LibraryCPPTemplate/vector.h index adb7e7807b..0e70220bd9 100644 --- a/LibraryCPPTemplate/vector.h +++ b/LibraryCPPTemplate/vector.h @@ -15,15 +15,7 @@ template class Vector // copy constructor Vector(const Vector &a) : capacity_value(a.capacity_value), size_value(a.size_value) { - if (capacity_value > 0) { - elements = new Data[capacity_value]; - for (size_t i = 0; i < size_value; ++i) { - elements[i] = a.elements[i]; - } - } - else { - elements = nullptr; - } + copyFunc(a); } // assignment operator @@ -33,15 +25,7 @@ template class Vector delete[] elements; capacity_value = a.capacity_value; size_value = a.size_value; - if (capacity_value > 0) { - elements = new Data[capacity_value]; - for (size_t i = 0; i < size_value; ++i) { - elements[i] = a.elements[i]; - } - } - else { - elements = nullptr; - } + copyFunc(a); } return *this; } @@ -53,7 +37,14 @@ template class Vector } // Retrieves vector element with the specified index - Data get(size_t index) const + Data& get(size_t index) + { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + return elements[index]; + } + const Data& get(size_t index) const { if (index >= size_value) { throw std::out_of_range("Index out of range"); @@ -102,6 +93,18 @@ template class Vector private: // private data should be here + void copyFunc(const Vector& a) + { + if (capacity_value > 0) { + elements = new Data[capacity_value]; + for (size_t i = 0; i < size_value; ++i) { + elements[i] = a.elements[i]; + } + } + else { + elements = nullptr; + } + } Data* elements; size_t capacity_value; size_t size_value; From ec44c2c3ec6cf0a6be0e6944fbbf52ab4f55bb84 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Tue, 9 Dec 2025 01:20:56 +0300 Subject: [PATCH 14/16] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B5=D0=B4=D0=BE=D1=87=D1=91=D1=82=D1=8B?= =?UTF-8?q?,=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BB=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80?= =?UTF-8?q?=D1=83=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BA=D1=83?= =?UTF-8?q?=D1=87=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab4CPP/main.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Lab4CPP/main.cpp b/Lab4CPP/main.cpp index b6ffe8f3b4..4764f28e6d 100644 --- a/Lab4CPP/main.cpp +++ b/Lab4CPP/main.cpp @@ -52,16 +52,17 @@ int pq_pop(PriorityQueue* pq) { pq->heap.set(0, pq->heap.get(pq->heap.size() - 1)); pq->heap.resize(pq->heap.size() - 1); - int index = 0; + size_t index = 0; + size_t heap_size = pq->heap.size(); while (true) { - int left = 2 * index + 1; - int right = 2 * index + 2; - int smallest = index; + size_t left = 2 * index + 1; + size_t right = 2 * index + 2; + size_t smallest = index; - if (left < pq->heap.size() && pq->heap.get(left).distance < pq->heap.get(smallest).distance) { + if (left < heap_size && pq->heap.get(left).distance < pq->heap.get(smallest).distance) { smallest = left; } - if (right < pq->heap.size() && pq->heap.get(right).distance < pq->heap.get(smallest).distance) { + if (right < heap_size && pq->heap.get(right).distance < pq->heap.get(smallest).distance) { smallest = right; } From ca0b0a63f83e923f4dde3de6c3ea297f31d9220e Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Sat, 20 Dec 2025 23:01:29 +0300 Subject: [PATCH 15/16] Lab_5 --- CMakeLists.txt | 7 +- Lab5CPP/CMakeLists.txt | 6 + Lab5CPP/graphic_5lab.png | Bin 0 -> 14829 bytes Lab5CPP/input1_5.txt | 10 + Lab5CPP/main.cpp | 159 +++++++++++++ LibraryCPPClass/CMakeLists.txt | 2 +- LibraryCPPClass/RBTree.cpp | 324 +++++++++++++++++++++++++++ LibraryCPPClass/RBTree.h | 43 ++++ LibraryCPPClass/Tests/CMakeLists.txt | 23 +- LibraryCPPClass/Tests/RBTree.cpp | 124 ++++++++++ 10 files changed, 685 insertions(+), 13 deletions(-) create mode 100644 Lab5CPP/CMakeLists.txt create mode 100644 Lab5CPP/graphic_5lab.png create mode 100644 Lab5CPP/input1_5.txt create mode 100644 Lab5CPP/main.cpp create mode 100644 LibraryCPPClass/RBTree.cpp create mode 100644 LibraryCPPClass/RBTree.h create mode 100644 LibraryCPPClass/Tests/RBTree.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e84ab85d37..b23e21c29d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,10 +12,11 @@ endif() #add_subdirectory(LibraryC) #add_subdirectory(LibraryCPP) -#add_subdirectory(LibraryCPPClass) -add_subdirectory(LibraryCPPTemplate) +add_subdirectory(LibraryCPPClass) +#add_subdirectory(LibraryCPPTemplate) #add_subdirectory(Lab1CPP) #add_subdirectory(Lab2CPP) #add_subdirectory(Lab3CPP) -add_subdirectory(Lab4CPP) \ No newline at end of file +#add_subdirectory(Lab4CPP) +add_subdirectory(Lab5CPP) \ No newline at end of file diff --git a/Lab5CPP/CMakeLists.txt b/Lab5CPP/CMakeLists.txt new file mode 100644 index 0000000000..8072d3c2ea --- /dev/null +++ b/Lab5CPP/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(Lab5CPP main.cpp) +target_include_directories (Lab5CPP PUBLIC ../LibraryCPPClass) +target_link_libraries(Lab5CPP LibraryCPPClass) + +add_test(NAME Test_1 COMMAND Lab5CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_5.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "loaded: 10") \ No newline at end of file diff --git a/Lab5CPP/graphic_5lab.png b/Lab5CPP/graphic_5lab.png new file mode 100644 index 0000000000000000000000000000000000000000..bcaa506c52c2aa5e4fe756601727acea07dfb14f GIT binary patch literal 14829 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 +#include +#include +#include +#include +#include +#include + +using namespace std; + +vector> generate_data(int count) { + vector> data; + random_device random_device; + mt19937 random_generator(random_device()); + + for (int i = 0; i < count; i++) { + string key = "user" + to_string(random_generator() % 1000000); + string value = "email" + to_string(i) + "@test.com"; + data.push_back(make_pair(key, value)); + } + return data; +} + +void test() { + RBTree tree; + string value; + + tree.insert("name", "alice"); + tree.insert("age", "25"); + tree.insert("city", "london"); + + if (tree.find("name", value) && value == "alice") cout << "test_get ok" << endl; + + tree.remove("age"); + if (!tree.find("age", value)) cout << "test_remove ok" << endl; + + if (tree.size() == 2) cout << "test_size ok" << endl; +} + +void speed() { + int sizes[] = { 1000, 5000, 10000, 50000, 100000, 500000, 1000000 }; + int sizes_count = 7; + + cout << "\nspeed test:" << endl; + cout << "size time" << endl; + + for (int i = 0; i < sizes_count; i++) { + int size = sizes[i]; + vector> data = generate_data(size); + + chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); + RBTree tree; + for (size_t j = 0; j < data.size(); j++) { + tree.insert(data[j].first, data[j].second); + } + chrono::high_resolution_clock::time_point end = chrono::high_resolution_clock::now(); + long long elapsed_time = chrono::duration_cast(end - start).count(); + + cout << size << " " << elapsed_time << endl; + } +} + +void mapvsrbtree() { + int sizes[] = { 1000, 5000, 10000, 50000, 100000, 500000, 1000000 }; + int sizes_count = 7; + + ofstream csv_file("сравнение.csv"); + + cout << "\ncomparison with map:" << endl; + cout << "size rbtree map" << endl; + + csv_file << "size,rbtree,std::map" << endl; + + for (int i = 0; i < sizes_count; i++) { + int size = sizes[i]; + vector> data = generate_data(size); + + chrono::high_resolution_clock::time_point start_rb = chrono::high_resolution_clock::now(); + RBTree tree; + for (size_t j = 0; j < data.size(); j++) { + tree.insert(data[j].first, data[j].second); + } + chrono::high_resolution_clock::time_point end_rb = chrono::high_resolution_clock::now(); + long long time_rb = chrono::duration_cast(end_rb - start_rb).count(); + + chrono::high_resolution_clock::time_point start_map = chrono::high_resolution_clock::now(); + map std_map; + for (size_t j = 0; j < data.size(); j++) { + std_map[data[j].first] = data[j].second; + } + chrono::high_resolution_clock::time_point end_map = chrono::high_resolution_clock::now(); + long long time_map = chrono::duration_cast(end_map - start_map).count(); + + cout << size << " " << time_rb << " " << time_map << endl; + csv_file << size << "," << time_rb << "," << time_map << endl; + } + csv_file.close(); +} + +void stress() { + int sizes[] = { 1000, 2000, 4000, 8000, 16000, 32000 }; + int sizes_count = 6; + + cout << "\nstress test:" << endl; + cout << "size time" << endl; + + for (int i = 0; i < sizes_count; i++) { + int size = sizes[i]; + vector> data = generate_data(size); + + chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); + RBTree tree; + for (size_t j = 0; j < data.size(); j++) { + tree.insert(data[j].first, data[j].second); + } + chrono::high_resolution_clock::time_point end = chrono::high_resolution_clock::now(); + long long elapsed_time = chrono::duration_cast(end - start).count(); + + cout << size << " " << elapsed_time << endl; + } +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Error: File not specified" << endl; + cout << "Usage: " << argv[0] << " " << endl; + return 1; + } + + ifstream input_file(argv[1]); + if (!input_file.is_open()) { + cout << "Error: Cannot open file " << argv[1] << endl; + return 1; + } + + test(); + speed(); + mapvsrbtree(); + stress(); + + RBTree tree; + string line; + int count = 0; + + while (getline(input_file, line)) { + istringstream line_stream(line); + string key, value; + if (line_stream >> key >> value) { + tree.insert(key, value); + count++; + } + } + + cout << "loaded: " << count << endl; + cout << "tree_size: " << tree.size() << endl; + + return 0; +} \ No newline at end of file diff --git a/LibraryCPPClass/CMakeLists.txt b/LibraryCPPClass/CMakeLists.txt index d8081ae607..2c331b3c83 100644 --- a/LibraryCPPClass/CMakeLists.txt +++ b/LibraryCPPClass/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(LibraryCPPClass STATIC stack.cpp vector.cpp) +add_library(LibraryCPPClass STATIC RBTree.cpp) add_subdirectory(Tests) diff --git a/LibraryCPPClass/RBTree.cpp b/LibraryCPPClass/RBTree.cpp new file mode 100644 index 0000000000..e03cc547c6 --- /dev/null +++ b/LibraryCPPClass/RBTree.cpp @@ -0,0 +1,324 @@ +#include "RBTree.h" +#include + +RBTree::Node::Node(const string& k, const string& v) + : key(k), value(v), red(true), left(0), right(0), parent(0) {} + +RBTree::RBTree() : root(0), treeSize(0) {} + +RBTree::~RBTree() { + clear(root); +} + +void RBTree::clear(Node* n) { + if (n) { + clear(n->left); + clear(n->right); + delete n; + } +} + +void RBTree::leftRotate(Node* x) { + Node* y = x->right; + x->right = y->left; + + if (y->left) + y->left->parent = x; + + y->parent = x->parent; + + if (x->parent == 0) + root = y; + else if (x == x->parent->left) + x->parent->left = y; + else + x->parent->right = y; + + y->left = x; + x->parent = y; +} + +void RBTree::rightRotate(Node* x) { + Node* y = x->left; + x->left = y->right; + + if (y->right) + y->right->parent = x; + + y->parent = x->parent; + + if (x->parent == 0) + root = y; + else if (x == x->parent->right) + x->parent->right = y; + else + x->parent->left = y; + + y->right = x; + x->parent = y; +} + +void RBTree::insert(const string& k, const string& v) { + Node* n = new Node(k, v); + + if (root == 0) { + root = n; + root->red = false; + treeSize++; + return; + } + + Node* cur = root; + Node* par = 0; + + while (cur) { + par = cur; + + if (k < cur->key) + cur = cur->left; + else if (k > cur->key) + cur = cur->right; + else { + cur->value = v; + delete n; + return; + } + } + + n->parent = par; + + if (k < par->key) + par->left = n; + else + par->right = n; + + treeSize++; + fixAdd(n); +} + +void RBTree::fixAdd(Node* k) { + while (k->parent && k->parent->red) { + if (k->parent == k->parent->parent->left) { + Node* u = k->parent->parent->right; + + if (u && u->red) { + k->parent->red = false; + u->red = false; + k->parent->parent->red = true; + k = k->parent->parent; + } + else { + if (k == k->parent->right) { + k = k->parent; + leftRotate(k); + } + + k->parent->red = false; + k->parent->parent->red = true; + rightRotate(k->parent->parent); + } + } + else { + Node* u = k->parent->parent->left; + + if (u && u->red) { + k->parent->red = false; + u->red = false; + k->parent->parent->red = true; + k = k->parent->parent; + } + else { + if (k == k->parent->left) { + k = k->parent; + rightRotate(k); + } + + k->parent->red = false; + k->parent->parent->red = true; + leftRotate(k->parent->parent); + } + } + + if (k == root) break; + } + + root->red = false; +} + +RBTree::Node* RBTree::find(const string& k) { + Node* cur = root; + + while (cur) { + if (k < cur->key) + cur = cur->left; + else if (k > cur->key) + cur = cur->right; + else + return cur; + } + + return 0; +} + +bool RBTree::find(const string& k, string& v) { + Node* n = find(k); + + if (n) { + v = n->value; + return true; + } + + return false; +} + +void RBTree::replace(Node* u, Node* v) { + if (u->parent == 0) + root = v; + else if (u == u->parent->left) + u->parent->left = v; + else + u->parent->right = v; + + if (v) + v->parent = u->parent; +} + +RBTree::Node* RBTree::minNode(Node* n) { + while (n && n->left) + n = n->left; + + return n; +} + +void RBTree::remove(const string& k) { + Node* z = find(k); + if (z == 0) return; + + Node* y = z; + Node* x = 0; + bool yRed = y->red; + + if (z->left == 0) { + x = z->right; + replace(z, z->right); + } + else if (z->right == 0) { + x = z->left; + replace(z, z->left); + } + else { + y = minNode(z->right); + yRed = y->red; + x = y->right; + + if (y->parent == z) { + if (x) + x->parent = y; + } + else { + replace(y, y->right); + y->right = z->right; + + if (y->right) + y->right->parent = y; + } + + replace(z, y); + y->left = z->left; + + if (y->left) + y->left->parent = y; + + y->red = z->red; + } + + delete z; + treeSize--; + + if (yRed == false && x) + fixDel(x); +} + +void RBTree::fixDel(Node* x) { + while (x != root && x && x->red == false) { + if (x == x->parent->left) { + Node* s = x->parent->right; + + if (s && s->red) { + s->red = false; + x->parent->red = true; + leftRotate(x->parent); + s = x->parent->right; + } + + if (s && (s->left == 0 || s->left->red == false) && (s->right == 0 || s->right->red == false)) { + s->red = true; + x = x->parent; + } + else { + if (s && (s->right == 0 || s->right->red == false)) { + if (s->left) + s->left->red = false; + + s->red = true; + rightRotate(s); + s = x->parent->right; + } + + if (s) { + s->red = x->parent->red; + + if (s->right) + s->right->red = false; + } + + x->parent->red = false; + leftRotate(x->parent); + x = root; + } + } + else { + Node* s = x->parent->left; + + if (s && s->red) { + s->red = false; + x->parent->red = true; + rightRotate(x->parent); + s = x->parent->left; + } + + if (s && (s->right == 0 || s->right->red == false) && (s->left == 0 || s->left->red == false)) { + s->red = true; + x = x->parent; + } + else { + if (s && (s->left == 0 || s->left->red == false)) { + if (s->right) + s->right->red = false; + + s->red = true; + leftRotate(s); + s = x->parent->left; + } + + if (s) { + s->red = x->parent->red; + + if (s->left) + s->left->red = false; + } + + x->parent->red = false; + rightRotate(x->parent); + x = root; + } + } + } + + if (x) + x->red = false; +} + +int RBTree::size() const { + return treeSize; +} \ No newline at end of file diff --git a/LibraryCPPClass/RBTree.h b/LibraryCPPClass/RBTree.h new file mode 100644 index 0000000000..cc4bae30bb --- /dev/null +++ b/LibraryCPPClass/RBTree.h @@ -0,0 +1,43 @@ +#ifndef RBTREE_H +#define RBTREE_H + +#include + +using namespace std; + +class RBTree { +private: + struct Node { + string key; + string value; + bool red; + Node* left; + Node* right; + Node* parent; + + Node(const string& k, const string& v); + }; + + Node* root; + int treeSize; + + void clear(Node* n); + void leftRotate(Node* x); + void rightRotate(Node* x); + void fixAdd(Node* k); + void fixDel(Node* x); + Node* find(const string& k); + Node* minNode(Node* n); + void replace(Node* u, Node* v); + +public: + RBTree(); + ~RBTree(); + + void insert(const string& k, const string& v); + bool find(const string& k, string& v); + void remove(const string& k); + int size() const; +}; + +#endif \ No newline at end of file diff --git a/LibraryCPPClass/Tests/CMakeLists.txt b/LibraryCPPClass/Tests/CMakeLists.txt index 64ca313a4e..dfa3e72941 100644 --- a/LibraryCPPClass/Tests/CMakeLists.txt +++ b/LibraryCPPClass/Tests/CMakeLists.txt @@ -14,13 +14,18 @@ # add_test(TestQueueCPPClass TestQueueCPPClass) # set_tests_properties(TestQueueCPPClass PROPERTIES TIMEOUT 10) -add_executable(TestStackCPPClass stack.cpp) -target_include_directories(TestStackCPPClass PUBLIC ..) -target_link_libraries(TestStackCPPClass LibraryCPPClass) -add_test(TestStackCPPClass TestStackCPPClass) +#add_executable(TestStackCPPClass stack.cpp) +#target_include_directories(TestStackCPPClass PUBLIC ..) +#target_link_libraries(TestStackCPPClass LibraryCPPClass) +#add_test(TestStackCPPClass TestStackCPPClass) -add_executable(TestVectorCPPClass vector.cpp) -target_include_directories(TestVectorCPPClass PUBLIC ..) -target_link_libraries(TestVectorCPPClass LibraryCPPClass) -add_test(TestVectorCPPClass TestVectorCPPClass) -set_tests_properties(TestVectorCPPClass PROPERTIES TIMEOUT 10) +#add_executable(TestVectorCPPClass vector.cpp) +#target_include_directories(TestVectorCPPClass PUBLIC ..) +#target_link_libraries(TestVectorCPPClass LibraryCPPClass) +#add_test(TestVectorCPPClass TestVectorCPPClass) +#set_tests_properties(TestVectorCPPClass PROPERTIES TIMEOUT 10) + +add_executable(TestRBTreeCPPClass RBTree.cpp) +target_include_directories(TestRBTreeCPPClass PUBLIC ..) +target_link_libraries(TestRBTreeCPPClass LibraryCPPClass) +add_test(TestRBTreeCPPClass TestRBTreeCPPClass) \ No newline at end of file diff --git a/LibraryCPPClass/Tests/RBTree.cpp b/LibraryCPPClass/Tests/RBTree.cpp new file mode 100644 index 0000000000..4855289c9f --- /dev/null +++ b/LibraryCPPClass/Tests/RBTree.cpp @@ -0,0 +1,124 @@ +#include "RBTree.h" +#include +#include + +using namespace std; + +void check(bool condition, const string& message) { + if (condition == false) { + cout << "Test failed: " << message << endl; + exit(1); + } +} + +void test_basic() { + RBTree t; + string value; + + t.insert("key1", "value1"); + check(t.find("key1", value), "find key1"); + check(value == "value1", "value1 correct"); + check(t.size() == 1, "size after insert"); + + t.remove("key1"); + check(!t.find("key1", value), "key1 removed"); + check(t.size() == 0, "size after remove"); + + cout << "Basic tests passed" << endl; +} + +void test_1000() { + RBTree t; + string value; + + for (int i = 0; i < 1000; i++) { + t.insert("key" + to_string(i), "value" + to_string(i)); + } + check(t.size() == 1000, "size 1000"); + + for (int i = 0; i < 1000; i++) { + check(t.find("key" + to_string(i), value), "find key" + to_string(i)); + check(value == "value" + to_string(i), "value" + to_string(i) + " correct"); + } + + for (int i = 0; i < 1000; i++) { + t.remove("key" + to_string(i)); + } + check(t.size() == 0, "empty after remove all"); + + cout << "1000 elements test passed" << endl; +} + +void test_10000() { + RBTree t; + string value; + + for (int i = 0; i < 10000; i++) { + t.insert("k" + to_string(i), "v" + to_string(i)); + } + check(t.size() == 10000, "size 10000"); + + for (int i = 0; i < 10000; i = i + 100) { + check(t.find("k" + to_string(i), value), "find k" + to_string(i)); + check(value == "v" + to_string(i), "v" + to_string(i) + " correct"); + } + + for (int i = 0; i < 10000; i++) { + t.remove("k" + to_string(i)); + } + check(t.size() == 0, "empty after remove 10000"); + + cout << "10000 elements test passed" << endl; +} + +void test_updates() { + RBTree t; + string value; + + t.insert("key", "value1"); + t.insert("key", "value2"); + + check(t.find("key", value), "find after update"); + check(value == "value2", "updated value correct"); + check(t.size() == 1, "size stays 1 after update"); + + cout << "Update test passed" << endl; +} + +void test_mixed() { + RBTree t; + string value; + + for (int i = 0; i < 500; i++) { + t.insert("mixed" + to_string(i), "data" + to_string(i)); + } + + for (int i = 0; i < 500; i = i + 2) { + t.remove("mixed" + to_string(i)); + } + + for (int i = 1; i < 500; i = i + 2) { + check(t.find("mixed" + to_string(i), value), "find mixed" + to_string(i)); + } + + for (int i = 0; i < 500; i = i + 2) { + check(!t.find("mixed" + to_string(i), value), "mixed" + to_string(i) + " removed"); + } + + check(t.size() == 250, "size after mixed operations"); + + cout << "Mixed operations test passed" << endl; +} + +int main() { + cout << "Starting RBTree tests..." << endl; + + test_basic(); + test_updates(); + test_1000(); + test_10000(); + test_mixed(); + + cout << "\nAll tests passed!" << endl; + return 0; +} \ No newline at end of file From bc8d937e50a51a9e065a964256604a22200012e8 Mon Sep 17 00:00:00 2001 From: LevTrachuk Date: Sun, 28 Dec 2025 18:43:19 +0300 Subject: [PATCH 16/16] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B5=D1=81=D1=82,=20=D0=B8=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B3=D1=80=D0=B0=D1=84=D0=B8=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab5CPP/graphic_5lab.png | Bin 14829 -> 18254 bytes Lab5CPP/main.cpp | 8 +++--- LibraryCPPClass/Tests/RBTree.cpp | 46 +++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/Lab5CPP/graphic_5lab.png b/Lab5CPP/graphic_5lab.png index bcaa506c52c2aa5e4fe756601727acea07dfb14f..06df7e163211c4a23c76ecab68d6a01a9d329704 100644 GIT binary patch literal 18254 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