From 60ee52fd6a701352ae71a985bfa10614429d7cf2 Mon Sep 17 00:00:00 2001 From: Nitin Sharma <32377892+foo290@users.noreply.github.com> Date: Tue, 6 Jul 2021 22:49:27 +0530 Subject: [PATCH 1/9] feat: add random pivot quick sort algorithm (#1510) * feat: add random pivot quick sort algorithm, test cases included * updating DIRECTORY.md * docs: add proper docs for random pivot quick sort algorithm, code reformatted. * fix: copy constructor bug fixed for TestCase class for random pivot quick sort algo * docs and code reformatted according to standards * c-style array declarations removed * added minor suggestion in docs * resource link added in docs * docs formatted * test function's docs added, using stl function for swap * generator function migrated to namespace * Update sorting/random_pivot_quick_sort.cpp Co-authored-by: David Leal * Update sorting/random_pivot_quick_sort.cpp Co-authored-by: David Leal * Update sorting/random_pivot_quick_sort.cpp Co-authored-by: David Leal * docs fixed sorting/random pivot quick sort * Apply suggestions from code review Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + sorting/random_pivot_quick_sort.cpp | 309 ++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 sorting/random_pivot_quick_sort.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index f735080e1..38e65a8a6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -298,6 +298,7 @@ * [Quick Sort 3](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort_3.cpp) * [Radix Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/radix_sort.cpp) * [Radix Sort2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/radix_sort2.cpp) + * [Random Pivot Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/random_pivot_quick_sort.cpp) * [Recursive Bubble Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/recursive_bubble_sort.cpp) * [Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/selection_sort.cpp) * [Shell Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/shell_sort.cpp) diff --git a/sorting/random_pivot_quick_sort.cpp b/sorting/random_pivot_quick_sort.cpp new file mode 100644 index 000000000..97892368f --- /dev/null +++ b/sorting/random_pivot_quick_sort.cpp @@ -0,0 +1,309 @@ +/** + * @file + * @brief Implementation of the [Random Pivot Quick Sort](https://www.sanfoundry.com/cpp-program-implement-quick-sort-using-randomisation) algorithm. + * @details + * * A random pivot quick sort algorithm is pretty much same as quick sort with a difference of having a logic of + * selecting next pivot element from the input array. + * * Where in quick sort is fast, but still can give you the time complexity of O(n^2) in worst case. + * * To avoid hitting the time complexity of O(n^2), we use the logic of randomize the selection process of pivot + * element. + * + * ### Logic + * * The logic is pretty simple, the only change is in the partitioning algorithm, which is selecting the + * pivot element. + * * Instead of selecting the last or the first element from array for pivot we use a random index to select + * pivot element. + * * This avoids hitting the O(n^2) time complexity in practical use cases. + * + * ### Partition Logic + * * Partitions are done such as numbers lower than the "pivot" element is arranged on the left side of the "pivot", + * and number larger than the "pivot" element are arranged on the right part of the array. + * + * ### Algorithm + * * Select the pivot element randomly using getRandomIndex() function from this namespace. + * * Initialize the pInd (partition index) from the start of the array. + * * Loop through the array from start to less than end. (from start to < end). + * (Inside the loop) :- + * * Check if the current element (arr[i]) is less than the pivot element in each iteration. + * * If current element in the iteration is less than the pivot element, + * then swap the elements at current index (i) and partition index (pInd) and increment the partition index by one. + * * At the end of the loop, swap the pivot element with partition index element. + * * Return the partition index from the function. + * + * @author [Nitin Sharma](https://github.com/foo290) + */ + +#include /// for IO operations +#include /// for initializing random number generator +#include /// for assert +#include /// for std::is_sorted(), std::swap() +#include /// for std::array +#include /// for returning multiple values form a function at once + +/** + * @namespace sorting + * @brief Sorting algorithms + */ +namespace sorting { +/** + * @brief Functions for the [Random Pivot Quick Sort](https://www.sanfoundry.com/cpp-program-implement-quick-sort-using-randomisation) implementation + * @namespace random_pivot_quick_sort + */ + namespace random_pivot_quick_sort { + /** + * @brief Utility function to print the array + * @tparam T size of the array + * @param arr array used to print its content + * @returns void + * */ + template + void showArray(std::array arr) { + for (int64_t i = 0; i < arr.size(); i++) { + std::cout << arr[i] << " "; + } + std::cout << std::endl; + } + + /** + * @brief Takes the start and end indices of an array and returns a random int64_teger between the range of those two + * for selecting pivot element. + * + * @param start The starting index. + * @param end The ending index. + * @returns int64_t A random number between start and end index. + * */ + int64_t getRandomIndex(int64_t start, int64_t end) { + srand(time(nullptr)); // Initialize random number generator. + int64_t randomPivotIndex = start + rand() % (end - start + 1); + return randomPivotIndex; + } + + /** + * @brief A partition function which handles the partition logic of quick sort. + * @tparam size size of the array to be passed as argument. + * @param start The start index of the passed array + * @param end The ending index of the passed array + * @returns std::tuple> A tuple of pivot index and pivot sorted array. + */ + template + std::tuple> partition(std::array arr, int64_t start, int64_t end) { + + int64_t pivot = arr[end]; // Randomly selected element will be here from caller function (quickSortRP()). + int64_t pInd = start; + + for (int64_t i = start; i < end; i++) { + if (arr[i] <= pivot) { + std::swap(arr[i], arr[pInd]); // swapping the elements from current index to pInd. + pInd++; + } + } + std::swap(arr[pInd], arr[end]); // swapping the pivot element to its sorted position + return std::make_tuple(pInd, arr); + } + + /** + * @brief Random pivot quick sort function. This function is the starting point of the algorithm. + * @tparam size size of the array to be passed as argument. + * @param start The start index of the passed array + * @param end The ending index of the passed array + * @returns std::array A fully sorted array in ascending order. + */ + template + std::array quickSortRP(std::array arr, int64_t start, int64_t end) { + if (start < end) { + + int64_t randomIndex = getRandomIndex(start, end); + + // switching the pivot with right most bound. + std::swap(arr[end], arr[randomIndex]); + + int64_t pivotIndex = 0; + // getting pivot index and pivot sorted array. + std::tie(pivotIndex, arr) = partition(arr, start, end); + + // Recursively calling + std::array rightSortingLeft = quickSortRP(arr, start, pivotIndex - 1); + std::array full_sorted = quickSortRP(rightSortingLeft, pivotIndex + 1, end); + arr = full_sorted; + } + return arr; + } + + /** + * @brief A function utility to generate unsorted array of given size and range. + * @tparam size Size of the output array. + * @param from Stating of the range. + * @param to Ending of the range. + * @returns std::array Unsorted array of specified size. + * */ + template + std::array generateUnsortedArray(int64_t from, int64_t to) { + srand(time(nullptr)); + std::array unsortedArray{}; + assert(from < to); + int64_t i = 0; + while (i < size) { + int64_t randomNum = from + rand() % (to - from + 1); + if (randomNum) { + unsortedArray[i] = randomNum; + i++; + } + } + return unsortedArray; + } + +} // namespace random_pivot_quick_sort +} // namespace sorting + +/** + * @brief a class containing the necessary test cases + */ +class TestCases { +private: + /** + * @brief A function to print64_t given message on console. + * @tparam T Type of the given message. + * @returns void + * */ + template + void log(T msg) { + // It's just to avoid writing cout and endl + std::cout << "[TESTS] : ---> " << msg << std::endl; + } + +public: + /** + * @brief Executes test cases + * @returns void + * */ + void runTests() { + log("Running Tests..."); + + testCase_1(); + testCase_2(); + testCase_3(); + + log("Test Cases over!"); + std::cout << std::endl; + } + + /** + * @brief A test case with single input + * @returns void + * */ + void testCase_1() { + const int64_t inputSize = 1; + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + log("This is test case 1 for Random Pivot Quick Sort Algorithm : "); + log("Description:"); + log(" EDGE CASE : Only contains one element"); + std::array unsorted_arr{2}; + + int64_t start = 0; + int64_t end = unsorted_arr.size() - 1; // length - 1 + + log("Running algorithm of data of length 50 ..."); + std::array sorted_arr = sorting::random_pivot_quick_sort::quickSortRP( + unsorted_arr, start, end + ); + log("Algorithm finished!"); + + log("Checking assert expression..."); + assert(std::is_sorted(sorted_arr.begin(), sorted_arr.end())); + log("Assertion check passed!"); + + log("[PASS] : TEST CASE 1 PASS!"); + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + } + + /** + * @brief A test case with input array of length 500 + * @returns void + * */ + void testCase_2() { + const int64_t inputSize = 500; + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + log("Description:"); + log(" BIG INPUT : Contains 500 elements and repeated elements"); + log("This is test case 2 for Random Pivot Quick Sort Algorithm : "); + std::array unsorted_arr = sorting::random_pivot_quick_sort::generateUnsortedArray(1, 10000); + + int64_t start = 0; + int64_t end = unsorted_arr.size() - 1; // length - 1 + + log("Running algorithm of data of length 500 ..."); + std::array sorted_arr = sorting::random_pivot_quick_sort::quickSortRP( + unsorted_arr, start, end + ); + log("Algorithm finished!"); + + log("Checking assert expression..."); + assert(std::is_sorted(sorted_arr.begin(), sorted_arr.end())); + log("Assertion check passed!"); + + log("[PASS] : TEST CASE 2 PASS!"); + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + } + + /** + * @brief A test case with array of length 1000. + * @returns void + * */ + void testCase_3() { + const int64_t inputSize = 1000; + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + log("This is test case 3 for Random Pivot Quick Sort Algorithm : "); + log("Description:"); + log(" LARGE INPUT : Contains 1000 elements and repeated elements"); + std::array unsorted_arr = sorting::random_pivot_quick_sort::generateUnsortedArray(1, 10000); + + int64_t start = 0; + int64_t end = unsorted_arr.size() - 1; // length - 1 + + log("Running algorithm..."); + std::array sorted_arr = sorting::random_pivot_quick_sort::quickSortRP( + unsorted_arr, start, end + ); + log("Algorithm finished!"); + + log("Checking assert expression..."); + assert(std::is_sorted(sorted_arr.begin(), sorted_arr.end())); + log("Assertion check passed!"); + + log("[PASS] : TEST CASE 3 PASS!"); + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + } +}; + + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + TestCases tc = TestCases(); + tc.runTests(); +} + +/** + * @brief Main function + * @param argc commandline argument count (ignored) + * @param argv commandline array of arguments (ignored) + * @returns 0 on exit + */ +int main(int argc, char *argv[]) { + test(); // Executes various test cases. + + const int64_t inputSize = 10; + std::array unsorted_array = sorting::random_pivot_quick_sort::generateUnsortedArray(50, 1000); + std::cout << "Unsorted array is : " << std::endl; + sorting::random_pivot_quick_sort::showArray(unsorted_array); + + std::array sorted_array = sorting::random_pivot_quick_sort::quickSortRP( + unsorted_array, 0, + unsorted_array.size() - 1 + ); + std::cout << "Sorted array is : " << std::endl; + sorting::random_pivot_quick_sort::showArray(sorted_array); + return 0; +} From 97afa0e3e4d817d2fa238e3213668bbb988e74e4 Mon Sep 17 00:00:00 2001 From: Nitin Sharma <32377892+foo290@users.noreply.github.com> Date: Wed, 7 Jul 2021 14:53:29 +0530 Subject: [PATCH 2/9] feat: add Sublist Search Algorithm (#1513) * feat: add sublist search algorithm * updating DIRECTORY.md * clang-format and clang-tidy fixes for e59bc3bf * Update search/sublist_search.cpp header docs Co-authored-by: David Leal * Update search/sublist_search.cpp docs Co-authored-by: David Leal * Update docs search/sublist_search.cpp Co-authored-by: David Leal * Update docs search/sublist_search.cpp Co-authored-by: David Leal * Update minor docs in search/sublist_search.cpp Co-authored-by: David Leal * made test function non static Co-authored-by: David Leal * test docs updated Co-authored-by: David Leal * namespaces added for search algo, docs added for test cases * [feat/fix/docs]: Perform some necessary changes * clang-format and clang-tidy fixes for 5a02b336 * test cases docs added, merge fixed * clang-format and clang-tidy fixes for be0160b4 * one liner docs added * clang-format and clang-tidy fixes for 95b362f3 * some final docs fixes * clang-format and clang-tidy fixes for 798972e9 * Apply suggestions from code review * Apply suggestions from code review * Apply suggestions from code review * docs updated for one line docs * clang-format and clang-tidy fixes for aebae1df * added one liner docs * clang-format and clang-tidy fixes for f6913b75 * Update search/sublist_search.cpp Co-authored-by: David Leal * Update search/sublist_search.cpp Co-authored-by: David Leal * clang-format and clang-tidy fixes for 66d1b87f * Update search/sublist_search.cpp Co-authored-by: David Leal * Update search/sublist_search.cpp Co-authored-by: David Leal * Apply suggestions from code review * clang-format and clang-tidy fixes for dc5b0c6c * Apply suggestions from code review * clang-format and clang-tidy fixes for 6436932f * Apply suggestions from code review * clang-format and clang-tidy fixes for 35f39b57 * Update docs search/sublist_search.cpp Co-authored-by: David Leal Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + search/sublist_search.cpp | 370 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 search/sublist_search.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index 38e65a8a6..964b49aeb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -268,6 +268,7 @@ * [Linear Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/linear_search.cpp) * [Median Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/median_search.cpp) * [Saddleback Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/saddleback_search.cpp) + * [Sublist Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/sublist_search.cpp) * [Ternary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/ternary_search.cpp) * [Text Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/text_search.cpp) diff --git a/search/sublist_search.cpp b/search/sublist_search.cpp new file mode 100644 index 000000000..9f854ce57 --- /dev/null +++ b/search/sublist_search.cpp @@ -0,0 +1,370 @@ +/** + * @file + * @brief Implementation of the [Sublist Search + * Algorithm](https://www.geeksforgeeks.org/sublist-search-search-a-linked-list-in-another-list) + * @details + * + * ### Algorithm + * + * * Sublist search is used to detect a presence of one list in another list. + * * Suppose we have a single-node list (let's say the first list), and we + * want to ensure that the list is present in another list (let's say the + * second list), then we can perform the sublist search to find it. + * + * * For instance, the first list contains these elements: 23 -> 30 -> 41, + * and the second list contains these elements: 10 -> 15 -> 23 -> 30 -> 41 + * -> 49. At a glance, we see that the first list presents in the second list. + * + * ### Working + * + * * The sublist search algorithm works by comparing the first element + * of the first list with the first element of the second list. + * * If the two values don't match, it goes to the next element of the + * second list. It does this until the two values match. + * + * @author [Nitin Sharma](https://github.com/foo290) + */ + +#include /// for assert +#include /// for IO operations +#include /// for std::vector + +/** + * @namespace search + * @brief Searching algorithms + */ +namespace search { +/** + * @namespace sublist_search + * @brief Functions for the [Sublist + * Search](https://www.geeksforgeeks.org/sublist-search-search-a-linked-list-in-another-list) + * implementation + */ +namespace sublist_search { +/** + * @brief A Node structure representing a single link Node in a linked list + */ +struct Node { + uint32_t data = 0; ///< the key/value of the node + Node *next{}; ///< pointer to the next node +}; + +/** + * @brief A simple function to print the linked list + * @param start The head of the linked list + * @returns void + */ +void printLinkedList(Node *start) { + while (start != nullptr) { + std::cout << "->" << start->data; + start = start->next; + } + std::cout << std::endl; +} + +/** + * @brief Give a vector of data, + * it adds each element of vector in the linked list and return the address of + * head pointer. + * @param data A vector of "int" containing the data that is supposed to be + * stored in nodes of linked list. + * @returns Node* A head pointer to the linked list. + */ +Node *makeLinkedList(const std::vector &data) { + /// This is used in test cases for rapidly creating linked list with 100+ + /// elements, instead of hard-coding 100 elements in test cases. + Node *head = nullptr; + Node *tail = nullptr; + for (int i : data) { + Node *node = new Node; + node->data = i; + node->next = nullptr; + if (head == nullptr) { + head = node; + tail = node; + } else { + tail->next = node; + tail = tail->next; + } + } + return head; +} + +/** + * @brief Main searching function + * @param sublist A linked list which is supposed to be searched in mainList. + * @param mainList A linked list in which sublist will be searched. + * @returns true if the sublist is found + * @returns false if the sublist is NOT found + */ +bool sublistSearch(Node *sublist, Node *mainList) { + if (sublist == nullptr || mainList == nullptr) { + return false; + } + + /// Initialize target pointer to the head node of sublist. + Node *target_ptr = sublist; + + while (mainList != nullptr) { + /// Initialize main pointer to the current node of main list. + Node *main_ptr = mainList; + + while (target_ptr != nullptr) { + if (main_ptr == nullptr) { + return false; + + } else if (main_ptr->data == target_ptr->data) { + /// If the data of target node and main node is equal then move + /// to the next node of both lists. + target_ptr = target_ptr->next; + main_ptr = main_ptr->next; + + } else { + break; + } + } + + if (target_ptr == nullptr) { + /// Is target pointer becomes null that means the target list is + /// been traversed without returning false. Which means the sublist + /// has been found and return ture. + return true; + } + + /// set the target pointer again to stating point of target list. + target_ptr = sublist; + + /// set the main pointer to the next element of the main list and repeat + /// the algo. + mainList = mainList->next; + } + + /// If the main list is exhausted, means sublist does not found, return + /// false + return false; +} + +} // namespace sublist_search +} // namespace search + +/** + * @brief class encapsulating the necessary test cases + */ +class TestCases { + private: + /** + * @brief A function to print given message on console. + * @tparam T Type of the given message. + * @returns void + * */ + template + void log(T msg) { + // It's just to avoid writing cout and endl + std::cout << "[TESTS] : ---> " << msg << std::endl; + } + + public: + /** + * @brief Executes test cases + * @returns void + * */ + void runTests() { + log("Running Tests..."); + + testCase_1(); + testCase_2(); + testCase_3(); + + log("Test Cases over!"); + std::cout << std::endl; + } + + /** + * @brief A test case contains edge case, Only contains one element. + * @returns void + * */ + void testCase_1() { + const bool expectedOutput = true; ///< Expected output of this test + + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + "~"); + log("This is test case 1 for sublist search Algorithm : "); + log("Description:"); + log(" EDGE CASE : Only contains one element"); + + std::vector sublistData = { + 6}; ///< Data to make linked list which will be the sublist + std::vector mainlistData = { + 2, 5, 6, 7, + 8}; ///< Data to make linked list which will be the main list + + search::sublist_search::Node *sublistLL = + search::sublist_search::makeLinkedList( + sublistData); ///< Sublist to be searched + search::sublist_search::Node *mainlistLL = + search::sublist_search::makeLinkedList( + mainlistData); ///< Main list in which sublist is to be + ///< searched + + bool exists = search::sublist_search::sublistSearch( + sublistLL, mainlistLL); ///< boolean, if sublist exist or not + + log("Checking assert expression..."); + assert(exists == expectedOutput); + log("Assertion check passed!"); + + log("[PASS] : TEST CASE 1 PASS!"); + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + "~"); + + delete (sublistLL); + delete (mainlistLL); + } + + /** + * @brief A test case which contains main list of 100 elements and sublist + * of 20. + * @returns void + * */ + void testCase_2() { + const bool expectedOutput = true; /// Expected output of this test + + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + "~"); + log("This is test case 2 for sublist search Algorithm : "); + log("Description:"); + log(" contains main list of 100 elements and sublist of 20"); + + std::vector sublistData( + 20); ///< Data to make linked list which will be the sublist + std::vector mainlistData( + 100); ///< Main list in which sublist is to be searched + + for (int i = 0; i < 100; i++) { + /// Inserts 100 elements in main list + mainlistData[i] = i + 1; + } + + int temp = 0; + for (int i = 45; i < 65; i++) { + /// Inserts 20 elements in sublist + sublistData[temp] = i + 1; + temp++; + } + + search::sublist_search::Node *sublistLL = + search::sublist_search::makeLinkedList( + sublistData); ///< Sublist to be searched + search::sublist_search::Node *mainlistLL = + search::sublist_search::makeLinkedList( + mainlistData); ///< Main list in which sublist is to be + ///< searched + + bool exists = search::sublist_search::sublistSearch( + sublistLL, mainlistLL); ///< boolean, if sublist exist or not + + log("Checking assert expression..."); + assert(exists == expectedOutput); + log("Assertion check passed!"); + + log("[PASS] : TEST CASE 2 PASS!"); + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + "~"); + } + + /** + * @brief A test case which contains main list of 50 elements and sublist + * of 20. + * @returns void + * */ + void testCase_3() { + const bool expectedOutput = false; ///< Expected output of this test + + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + "~"); + log("This is test case 3 for sublist search Algorithm : "); + log("Description:"); + log(" contains main list of 50 elements and sublist of 20"); + + std::vector sublistData(20); ///< Sublist to be searched + std::vector mainlistData( + 50); ///< Main list in which sublist is to be searched + + for (int i = 0; i < 50; i++) { + /// Inserts 100 elements in main list + mainlistData.push_back(i + 1); + } + + for (int i = 45; i < 65; i++) { + /// Inserts 20 elements in sublist + sublistData.push_back(i + 1); + } + + search::sublist_search::Node *sublistLL = + search::sublist_search::makeLinkedList( + sublistData); ///< Sublist to be searched + search::sublist_search::Node *mainlistLL = + search::sublist_search::makeLinkedList( + mainlistData); ///< Main list in which sublist is to be + ///< searched + + bool exists = search::sublist_search::sublistSearch( + sublistLL, mainlistLL); ///< boolean, if sublist exist or not + + log("Checking assert expression..."); + assert(exists == expectedOutput); + log("Assertion check passed!"); + + log("[PASS] : TEST CASE 3 PASS!"); + log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + "~"); + } +}; + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + TestCases tc; + tc.runTests(); +} + +/** + * @brief Main function + * @param argc commandline argument count (ignored) + * @param argv commandline array of arguments (ignored) + * @returns 0 on exit + */ +int main(int argc, char *argv[]) { + test(); // run self-test implementations + + std::vector mainlistData = { + 2, 5, 6, 7, 8}; ///< Main list in which sublist is to be searched + std::vector sublistData = {6, 8}; ///< Sublist to be searched + + search::sublist_search::Node *mainlistLL = + search::sublist_search::makeLinkedList(mainlistData); + search::sublist_search::Node *sublistLL = + search::sublist_search::makeLinkedList( + sublistData); ///< Main list in which sublist is to be + ///< searched + + bool exists = search::sublist_search::sublistSearch( + sublistLL, + mainlistLL); ///< boolean to check if the sublist exists or not + + std::cout << "Sublist: " << std::endl; + search::sublist_search::printLinkedList(sublistLL); + + std::cout << "Main list: " << std::endl; + search::sublist_search::printLinkedList(mainlistLL); + std::cout << std::endl; + + if (exists) { + std::cout << "[TRUE] - sublist found in main list\n"; + } else { + std::cout << "[FALSE] - sublist NOT found in main list\n"; + } + return 0; +} From 34556ad93925310cb8f92a6a0142bdbac4482f8a Mon Sep 17 00:00:00 2001 From: Swastika Gupta <64654203+Swastyy@users.noreply.github.com> Date: Fri, 9 Jul 2021 15:13:57 +0530 Subject: [PATCH 3/9] Create count_of_set_bits.cpp (#1515) * Create count_of_set_bits.cpp * Update count_of_set_bits.cpp * updating DIRECTORY.md * clang-format and clang-tidy fixes for d0dc7eb3 * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * clang-format and clang-tidy fixes for f8606e8f * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * clang-format and clang-tidy fixes for 40e0f745 * Update count_of_set_bits.cpp * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal * Update bit_manipulation/count_of_set_bits.cpp Co-authored-by: David Leal Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + bit_manipulation/count_of_set_bits.cpp | 80 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 bit_manipulation/count_of_set_bits.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index 964b49aeb..b65d77995 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -10,6 +10,7 @@ * [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp) ## Bit Manipulation + * [Count Of Set Bits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/bit_manipulation/count_of_set_bits.cpp) * [Hamming Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/bit_manipulation/hamming_distance.cpp) ## Ciphers diff --git a/bit_manipulation/count_of_set_bits.cpp b/bit_manipulation/count_of_set_bits.cpp new file mode 100644 index 000000000..87f01d161 --- /dev/null +++ b/bit_manipulation/count_of_set_bits.cpp @@ -0,0 +1,80 @@ +/** + * @file + * @brief Implementation to [count sets + * bits](https://www.geeksforgeeks.org/count-set-bits-in-an-integer/) in an + * integer. + * + * @details + * We are given an integer number. Let’s say, number. The task is to first + * calculate the binary digit of a number and then calculate the total set bits + * of a number. + * + * Set bits in a binary number is represented by 1. Whenever we calculate the + * binary number of an integer value it is formed as the combination of 0’s and + * 1’s. So digit 1 is known as a set bit in computer terms. + * Time Complexity: O(log n) + * Space complexity: O(1) + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for assert +#include /// for io operations +#include /// for std::vector + +/** + * @namespace bit_manipulation + * @brief Bit manipulation algorithms + */ +namespace bit_manipulation { +/** + * @namespace count_of_set_bits + * @brief Functions for the [count sets + * bits](https://www.geeksforgeeks.org/count-set-bits-in-an-integer/) + * implementation + */ +namespace count_of_set_bits { +/** + * @brief The main function implements set bit count + * @param n is the number whose set bit will be counted + * @returns the count of the number set bit in the binary representation of `n` + */ +std::uint64_t countSetBits(int n) { + int count = 0; // "count" variable is used to count number of 1's in binary + // representation of the number + while (n != 0) { + count += n & 1; + n = n >> 1; // n=n/2 + } + return count; +} +} // namespace count_of_set_bits +} // namespace bit_manipulation + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // n = 4 return 1 + assert(bit_manipulation::count_of_set_bits::countSetBits(4) == 1); + // n = 6 return 2 + assert(bit_manipulation::count_of_set_bits::countSetBits(6) == 2); + // n = 13 return 3 + assert(bit_manipulation::count_of_set_bits::countSetBits(13) == 3); + // n = 9 return 2 + assert(bit_manipulation::count_of_set_bits::countSetBits(9) == 2); + // n = 15 return 4 + assert(bit_manipulation::count_of_set_bits::countSetBits(15) == 4); + // n = 25 return 3 + assert(bit_manipulation::count_of_set_bits::countSetBits(25) == 3); + std::cout << "All test cases successfully passed!" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} From 1ab5e4e56466a3a9b06c330c4e52cc7bb06699c3 Mon Sep 17 00:00:00 2001 From: Jxtopher <39927513+Jxtopher@users.noreply.github.com> Date: Fri, 9 Jul 2021 21:00:34 +0200 Subject: [PATCH 4/9] feat: Replace "\n" -> std::endl (#1530) Co-authored-by: David Leal --- backtracking/graph_coloring.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtracking/graph_coloring.cpp b/backtracking/graph_coloring.cpp index f2ac572c5..0f82a77bf 100644 --- a/backtracking/graph_coloring.cpp +++ b/backtracking/graph_coloring.cpp @@ -30,11 +30,11 @@ namespace backtracking { */ template void printSolution(const std::array & color) { - std::cout << "Following are the assigned colors\n"; + std::cout << "Following are the assigned colors" << std::endl; for (auto &col : color) { std::cout << col; } - std::cout << "\n"; + std::cout << std::endl; } /** A utility function to check if the current color assignment is safe for From 6115bc298154dc996c0315e79673fa436d02f6ea Mon Sep 17 00:00:00 2001 From: Swastika Gupta <64654203+Swastyy@users.noreply.github.com> Date: Sat, 10 Jul 2021 00:32:28 +0530 Subject: [PATCH 5/9] feat: Add House Robber algorithm (#1524) * Create house_robber.cpp * updating DIRECTORY.md * Update dynamic_programming/house_robber.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update dynamic_programming/house_robber.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update dynamic_programming/house_robber.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * clang-format and clang-tidy fixes for c00823e8 * Update house_robber.cpp * clang-format and clang-tidy fixes for cdf701c2 * Update house_robber.cpp * clang-format and clang-tidy fixes for 39c3719f * Update dynamic_programming/house_robber.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * clang-format and clang-tidy fixes for 126e3f21 * Update house_robber.cpp * Update dynamic_programming/house_robber.cpp Co-authored-by: David Leal * Update dynamic_programming/house_robber.cpp Co-authored-by: David Leal * Update dynamic_programming/house_robber.cpp Co-authored-by: David Leal * Update dynamic_programming/house_robber.cpp Co-authored-by: David Leal * Update house_robber.cpp * clang-format and clang-tidy fixes for 474a5f0b * Update dynamic_programming/house_robber.cpp Co-authored-by: David Leal * Update dynamic_programming/house_robber.cpp Co-authored-by: David Leal * clang-format and clang-tidy fixes for 203cce31 * Update house_robber.cpp * Update house_robber.cpp * Update house_robber.cpp * clang-format and clang-tidy fixes for 6b0bea93 * Apply suggestions from code review * Apply suggestions from code review * clang-format and clang-tidy fixes for 913baf88 Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + dynamic_programming/house_robber.cpp | 114 +++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 dynamic_programming/house_robber.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index b65d77995..ea7ed6779 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -74,6 +74,7 @@ * [Egg Dropping Puzzle](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/egg_dropping_puzzle.cpp) * [Fibonacci Bottom Up](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/fibonacci_bottom_up.cpp) * [Floyd Warshall](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/floyd_warshall.cpp) + * [House Robber](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/house_robber.cpp) * [Kadane](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/kadane.cpp) * [Kadane2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/kadane2.cpp) * [Longest Common String](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/longest_common_string.cpp) diff --git a/dynamic_programming/house_robber.cpp b/dynamic_programming/house_robber.cpp new file mode 100644 index 000000000..0d238b9c1 --- /dev/null +++ b/dynamic_programming/house_robber.cpp @@ -0,0 +1,114 @@ +/** + * @file + * @brief Implementation of [House Robber + * Problem](https://labuladong.gitbook.io/algo-en/i.-dynamic-programming/houserobber) + * algorithm + * @details + * Solution of House robber problem uses a dynamic programming concept that + * works in \f$O(n)\f$ time and works in \f$O(1)\f$ space. + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for assert +#include /// for std::max +#include /// for io operations +#include /// for std::vector + +/** + * @namespace dynamic_programming + * @brief Dynamic Programming algorithms + */ +namespace dynamic_programming { +/** + * @namespace house_robber + * @brief Functions for the [House + * Robber](https://labuladong.gitbook.io/algo-en/i.-dynamic-programming/houserobber) + * algorithm + */ +namespace house_robber { +/** + * @brief The main function that implements the House Robber algorithm using + * dynamic programming + * @param money array containing money in the ith house + * @param n size of array + * @returns maximum amount of money that can be robbed + */ +std::uint32_t houseRobber(const std::vector &money, + const uint32_t &n) { + if (n == 0) { // if there is no house + return 0; + } + if (n == 1) { // if there is only one house + return money[0]; + } + if (n == 2) { // if there are two houses, one with the maximum amount of + // money will be robbed + return std::max(money[0], money[1]); + } + uint32_t max_value = 0; // contains maximum stolen value at the end + uint32_t value1 = money[0]; + uint32_t value2 = std::max(money[0], money[1]); + for (uint32_t i = 2; i < n; i++) { + max_value = std::max(money[i] + value1, value2); + value1 = value2; + value2 = max_value; + } + + return max_value; +} +} // namespace house_robber +} // namespace dynamic_programming + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // Test 1 + // [1, 2, 3, 1] return 4 + std::vector array1 = {1, 2, 3, 1}; + std::cout << "Test 1... "; + assert( + dynamic_programming::house_robber::houseRobber(array1, array1.size()) == + 4); // here the two non-adjacent houses that are robbed are first and + // third with total sum money as 4 + std::cout << "passed" << std::endl; + + // Test 2 + // [6, 7, 1, 3, 8, 2, 4] return 19 + std::vector array2 = {6, 7, 1, 3, 8, 2, 4}; + std::cout << "Test 2... "; + assert( + dynamic_programming::house_robber::houseRobber(array2, array2.size()) == + 19); // here the four non-adjacent houses that are robbed are first, + // third, fifth and seventh with total sum money as 19 + std::cout << "passed" << std::endl; + + // Test 3 + // [] return 0 + std::vector array3 = {}; + std::cout << "Test 3... "; + assert( + dynamic_programming::house_robber::houseRobber(array3, array3.size()) == + 0); // since there is no house no money can be robbed + std::cout << "passed" << std::endl; + + // Test 4 + // [2,7,9,3,1] return 12 + std::vector array4 = {2, 7, 9, 3, 1}; + std::cout << "Test 4... "; + assert( + dynamic_programming::house_robber::houseRobber(array4, array4.size()) == + 12); // here the three non-adjacent houses that are robbed are first, + // third and fifth with total sum money as 12 + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} From 394811e601743d39650dda263a07fa61bf030b67 Mon Sep 17 00:00:00 2001 From: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> Date: Sat, 10 Jul 2021 00:33:57 +0530 Subject: [PATCH 6/9] fix: spelling error in `CONTRIBUTING.md` (#1531) Co-authored-by: David Leal --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 72014433d..2ff8cb72c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -113,7 +113,7 @@ bool func(int param1, T param2) { * @returns void */ static void test() { - /* desciptions of the following test */ + /* descriptions of the following test */ assert(func(...) == ...); // this ensures that the algorithm works as expected // can have multiple checks From 82290e72c540e63aabd7af9abe487bc0a4aa6d64 Mon Sep 17 00:00:00 2001 From: Swastika Gupta <64654203+Swastyy@users.noreply.github.com> Date: Tue, 13 Jul 2021 06:20:56 +0530 Subject: [PATCH 7/9] tests: Add test in `cycle_sort.cpp` (#1520) * Update cycle_sort.cpp * Update sorting/cycle_sort.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update sorting/cycle_sort.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * clang-format and clang-tidy fixes for 2601c621 * Update cycle_sort.cpp * Update cycle_sort.cpp * Update cycle_sort.cpp * clang-format and clang-tidy fixes for 39cf3f34 * Update sorting/cycle_sort.cpp Co-authored-by: David Leal * Update cycle_sort.cpp * Update cycle_sort.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal --- sorting/cycle_sort.cpp | 46 ++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/sorting/cycle_sort.cpp b/sorting/cycle_sort.cpp index 7700b2115..8acf462af 100644 --- a/sorting/cycle_sort.cpp +++ b/sorting/cycle_sort.cpp @@ -2,14 +2,12 @@ * @file * @brief Implementation of [Cycle * sort](https://en.wikipedia.org/wiki/Cycle_sort) algorithm - * * @details - * Cycle Sort is a sorting algorithm that works in \f$O(n^2)\f$ time in best cas - * and works in \f$O(n^2)\f$ in worst case. If a element is already at its + * Cycle Sort is a sorting algorithm that works in \f$O(n^2)\f$ time in the best + * case and works in \f$O(n^2)\f$ in worst case. If a element is already at its * correct position, do nothing. If a element is not at its correct position, * we then need to move it to its correct position by computing the correct * positions.Therefore, we should make sure the duplicate elements. - * * @author [TsungHan Ho](https://github.com/dalaoqi) */ @@ -38,14 +36,14 @@ namespace cycle_sort { template std::vector cycleSort(const std::vector &in_arr) { std::vector arr(in_arr); - for (size_t cycle_start = 0; cycle_start <= arr.size() - 1; cycle_start++) { + for (int cycle_start = 0; cycle_start <= arr.size() - 1; cycle_start++) { // initialize item T item = arr[cycle_start]; // Count the number of elements smaller than item, this number is the // correct index of item. int pos = cycle_start; - for (size_t i = cycle_start + 1; i < arr.size(); i++) { + for (int i = cycle_start + 1; i < arr.size(); i++) { if (arr[i] < item) { pos++; } @@ -58,8 +56,11 @@ std::vector cycleSort(const std::vector &in_arr) { // duplicate elements while (item == arr[pos]) pos += 1; - std::swap(item, arr[pos]); - + if (pos == cycle_start) { + continue; + } else { + std::swap(item, arr[pos]); + } // Rest of the elements while (pos != cycle_start) { pos = cycle_start; @@ -71,7 +72,11 @@ std::vector cycleSort(const std::vector &in_arr) { } // duplicate elements while (item == arr[pos]) pos += 1; - std::swap(item, arr[pos]); + if (item == arr[pos]) { + continue; + } else { + std::swap(item, arr[pos]); + } } } return arr; @@ -84,11 +89,11 @@ std::vector cycleSort(const std::vector &in_arr) { * @returns void */ static void test() { - // [506, 48, 123, 79, 0, 362, 951, 500, 0] return [0, 0, 48, 79, 123, 362, - // 500, 506, 951] - std::vector array1 = {506, 48, 123, 79, 0, 362, 951, 500, 0}; + // Test 1 + // [4, 3, 2, 1] return [1, 2, 3, 4] + std::vector array1 = {4, 3, 2, 1}; std::cout << "Test 1... "; - std::vector arr1 = sorting::cycle_sort::cycleSort(array1); + std::vector arr1 = sorting::cycle_sort::cycleSort(array1); assert(std::is_sorted(std::begin(arr1), std::end(arr1))); std::cout << "passed" << std::endl; @@ -98,6 +103,21 @@ static void test() { std::vector arr2 = sorting::cycle_sort::cycleSort(array2); assert(std::is_sorted(std::begin(arr2), std::end(arr2))); std::cout << "passed" << std::endl; + + // Test 3 + // [3, 3, 3, 3] return [3, 3, 3, 3] + std::vector array3 = {3, 3, 3, 3}; + std::cout << "Test 3... "; + std::vector arr3 = sorting::cycle_sort::cycleSort(array3); + assert(std::is_sorted(std::begin(arr3), std::end(arr3))); + std::cout << "passed" << std::endl; + + // [9, 4, 6, 8, 14, 3] return [9, 4, 6, 8, 14, 3] + std::vector array4 = {3, 4, 6, 8, 9, 14}; + std::cout << "Test 4... "; + std::vector arr4 = sorting::cycle_sort::cycleSort(array4); + assert(std::is_sorted(std::begin(arr4), std::end(arr4))); + std::cout << "passed" << std::endl; } /** From e059765f79d5a6dffe6b7554f53e030dfc2e7e2d Mon Sep 17 00:00:00 2001 From: Swastika Gupta <64654203+Swastyy@users.noreply.github.com> Date: Tue, 13 Jul 2021 06:49:03 +0530 Subject: [PATCH 8/9] Create subset_sum.cpp (#1517) * Create subset_sum.cpp * Update subset_sum.cpp * Update subset_sum.cpp * updating DIRECTORY.md * clang-format and clang-tidy fixes for 4827805a * Update subset_sum.cpp * clang-format and clang-tidy fixes for dac32465 * Update backtracking/subset_sum.cpp Co-authored-by: Filip Hlasek * Update backtracking/subset_sum.cpp Co-authored-by: Filip Hlasek * clang-format and clang-tidy fixes for 1328571c * Update backtracking/subset_sum.cpp Co-authored-by: Filip Hlasek * Update subset_sum.cpp * clang-format and clang-tidy fixes for 2325e165 * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * clang-format and clang-tidy fixes for 1b82d499 * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * clang-format and clang-tidy fixes for 31a1deae * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update backtracking/subset_sum.cpp Co-authored-by: David Leal * Update subset_sum.cpp * clang-format and clang-tidy fixes for 9cd07635 * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update backtracking/subset_sum.cpp Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> * Update subset_sum.cpp * Update subset_sum.cpp * clang-format and clang-tidy fixes for 2405a142 * Update subset_sum.cpp * clang-format and clang-tidy fixes for 383baeb3 * Update subset_sum.cpp * Update backtracking/subset_sum.cpp * Update backtracking/subset_sum.cpp * Update backtracking/subset_sum.cpp * Update backtracking/subset_sum.cpp * Update backtracking/subset_sum.cpp * Update backtracking/subset_sum.cpp * Update backtracking/subset_sum.cpp Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Filip Hlasek Co-authored-by: Abhinn Mishra <49574460+mishraabhinn@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + backtracking/subset_sum.cpp | 106 ++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 backtracking/subset_sum.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index ea7ed6779..f56b46e2e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -7,6 +7,7 @@ * [N Queens All Solution Optimised](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/n_queens_all_solution_optimised.cpp) * [Nqueen Print All Solutions](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/nqueen_print_all_solutions.cpp) * [Rat Maze](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/rat_maze.cpp) + * [Subset Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/subset_sum.cpp) * [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp) ## Bit Manipulation diff --git a/backtracking/subset_sum.cpp b/backtracking/subset_sum.cpp new file mode 100644 index 000000000..fad820920 --- /dev/null +++ b/backtracking/subset_sum.cpp @@ -0,0 +1,106 @@ +/** + * @file + * @brief Implementation of the [Subset + * Sum](https://en.wikipedia.org/wiki/Subset_sum_problem) problem. + * @details + * We are given an array and a sum value. The algorithm finds all + * the subsets of that array with sum equal to the given sum and return such + * subsets count. This approach will have exponential time complexity. + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for assert +#include /// for IO operations +#include /// for std::vector + +/** + * @namespace backtracking + * @brief Backtracking algorithms + */ +namespace backtracking { +/** + * @namespace Subsets + * @brief Functions for the [Subset + * Sum](https://en.wikipedia.org/wiki/Subset_sum_problem) problem. + */ +namespace subset_sum { +/** + * @brief The main function implements count of subsets + * @param sum is the required sum of any subset + * @param in_arr is the input array + * @returns count of the number of subsets with required sum + */ +uint64_t number_of_subsets(int32_t sum, const std::vector &in_arr) { + int32_t nelement = in_arr.size(); + uint64_t count_of_subset = 0; + + for (int32_t i = 0; i < (1 << (nelement)); i++) { + int32_t check = 0; + for (int32_t j = 0; j < nelement; j++) { + if (i & (1 << j)) { + check += (in_arr[j]); + } + } + if (check == sum) { + count_of_subset++; + } + } + return count_of_subset; +} +} // namespace subset_sum +} // namespace backtracking + +/** + * @brief Test implementations + * @returns void + */ +static void test() { + // 1st test + std::cout << "1st test "; + std::vector array1 = {-7, -3, -2, 5, 8}; // input array + assert(backtracking::subset_sum::number_of_subsets(0, array1) == + 2); // first argument in subset_sum function is the required sum and + // second is the input array + std::cout << "passed" << std::endl; + + // 2nd test + std::cout << "2nd test "; + std::vector array2 = {1, 2, 3, 3}; + assert(backtracking::subset_sum::number_of_subsets(6, array2) == + 3); // here we are expecting 3 subsets which sum up to 6 i.e. + // {(1,2,3),(1,2,3),(3,3)} + std::cout << "passed" << std::endl; + + // 3rd test + std::cout << "3rd test "; + std::vector array3 = {1, 1, 1, 1}; + assert(backtracking::subset_sum::number_of_subsets(1, array3) == + 4); // here we are expecting 4 subsets which sum up to 1 i.e. + // {(1),(1),(1),(1)} + std::cout << "passed" << std::endl; + + // 4th test + std::cout << "4th test "; + std::vector array4 = {3, 3, 3, 3}; + assert(backtracking::subset_sum::number_of_subsets(6, array4) == + 6); // here we are expecting 6 subsets which sum up to 6 i.e. + // {(3,3),(3,3),(3,3),(3,3),(3,3),(3,3)} + std::cout << "passed" << std::endl; + + // Test 5 + std::cout << "5th test "; + std::vector array5 = {}; + assert(backtracking::subset_sum::number_of_subsets(6, array5) == + 0); // here we are expecting 0 subsets which sum up to 6 i.e. we + // cannot select anything from an empty array + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} From 7bab516e59c10a2c51e5a24a55b9c7e20442115d Mon Sep 17 00:00:00 2001 From: Swastika Gupta <64654203+Swastyy@users.noreply.github.com> Date: Sat, 17 Jul 2021 00:11:54 +0530 Subject: [PATCH 9/9] feat: Add the Wave Sort algorithm (#1525) * Create wave_sort.cpp * Update wave_sort.cpp * Update wave_sort.cpp * Update wave_sort.cpp * updating DIRECTORY.md * clang-format and clang-tidy fixes for 196165e7 * Update wave_sort.cpp * Update sorting/wave_sort.cpp Co-authored-by: David Leal * Update sorting/wave_sort.cpp Co-authored-by: David Leal * Update sorting/wave_sort.cpp Co-authored-by: David Leal * Update wave_sort.cpp * clang-format and clang-tidy fixes for b5f9663f * Update sorting/wave_sort.cpp Co-authored-by: David Leal * Update sorting/wave_sort.cpp Co-authored-by: David Leal * clang-format and clang-tidy fixes for 8651884e Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + sorting/wave_sort.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 sorting/wave_sort.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index f56b46e2e..00757255a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -311,6 +311,7 @@ * [Strand Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/strand_sort.cpp) * [Swap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/swap_sort.cpp) * [Tim Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/tim_sort.cpp) + * [Wave Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/wave_sort.cpp) * [Wiggle Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/wiggle_sort.cpp) ## Strings diff --git a/sorting/wave_sort.cpp b/sorting/wave_sort.cpp new file mode 100644 index 000000000..85fdb61ad --- /dev/null +++ b/sorting/wave_sort.cpp @@ -0,0 +1,94 @@ +/** + * @file + * @brief Implementation of the [Wave + * sort](https://www.geeksforgeeks.org/sort-array-wave-form-2/) algorithm + * @details + * Wave Sort is a sorting algorithm that works in \f$O(nlogn)\f$ time assuming + * the sort function used works in \f$O(nlogn)\f$ time. + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for std::is_sorted, std::swap +#include /// for assert +#include /// for IO operations +#include /// for std::vector + +/** + * @namespace sorting + * @brief Sorting algorithms + */ +namespace sorting { +/** + * @namespace wave_sort + * @brief Functions for the [Wave + * sort](https://www.geeksforgeeks.org/sort-array-wave-form-2/) implementation + */ +namespace wave_sort { +/** + * @brief The main function implements that implements the Wave Sort algorithm + * @tparam T type of array + * @param in_arr array to be sorted + * @returns arr the wave sorted array + */ +template +std::vector waveSort(const std::vector &in_arr, int64_t n) { + std::vector arr(in_arr); + + for (int64_t i = 0; i < n; i++) { + arr[i] = in_arr[i]; + } + std::sort(arr.begin(), arr.end()); + for (int64_t i = 0; i < n - 1; i += 2) { // swap all the adjacent elements + std::swap(arr[i], arr[i + 1]); + } + return arr; +} +} // namespace wave_sort +} // namespace sorting + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // [10, 90, 49, 2, 1, 5, 23] return [2, 1, 10, 5, 49, 23, 90] + std::vector array1 = {10, 90, 49, 2, 1, 5, 23}; + std::cout << "Test 1... "; + std::vector arr1 = sorting::wave_sort::waveSort(array1, 7); + const std::vector o1 = {2, 1, 10, 5, 49, 23, 90}; + assert(arr1 == o1); + std::cout << "passed" << std::endl; + + // [1, 3, 4, 2, 7, 8] return [2, 1, 4, 3, 8, 7] + std::vector array2 = {1, 3, 4, 2, 7, 8}; + std::cout << "Test 2... "; + std::vector arr2 = sorting::wave_sort::waveSort(array2, 6); + const std::vector o2 = {2, 1, 4, 3, 8, 7}; + assert(arr2 == o2); + std::cout << "passed" << std::endl; + + // [3, 3, 3, 3] return [3, 3, 3, 3] + std::vector array3 = {3, 3, 3, 3}; + std::cout << "Test 3... "; + std::vector arr3 = sorting::wave_sort::waveSort(array3, 4); + const std::vector o3 = {3, 3, 3, 3}; + assert(arr3 == o3); + std::cout << "passed" << std::endl; + + // [9, 4, 6, 8, 14, 3] return [4, 3, 8, 6, 14, 9] + std::vector array4 = {9, 4, 6, 8, 14, 3}; + std::cout << "Test 4... "; + std::vector arr4 = sorting::wave_sort::waveSort(array4, 6); + const std::vector o4 = {4, 3, 8, 6, 14, 9}; + assert(arr4 == o4); + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +}