From cac5fbe4aad104140f792a4a4ae72cc6084e2041 Mon Sep 17 00:00:00 2001 From: Deep Raval Date: Sat, 18 Jul 2020 03:57:40 +0530 Subject: [PATCH 01/19] feat: add Bogo Sort (#952) * Added Bogo Sort * Changed code according to guidelines * Added Comments and example * Improved code quality * Added range based loop and included cassert * Changed Vectors to Array * Added const to vector arg and now returning sorted array * Changed vector to array and changed description format * Added namespace sorting, Function description and tests * Update sorting/Bogo_Sort.cpp Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> * Replaced Shuffle with std::random_shuffle * Renamed filename to smallercase, Added shuffle for ref and updated bracket styling * Added missing ')' * updating DIRECTORY.md * Added spaces in single line comments * Added Spaces * Update sorting/bogo_sort.cpp Co-authored-by: David Leal Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + sorting/bogo_sort.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 sorting/bogo_sort.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index 57a1b1c13..cd47fe955 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -215,6 +215,7 @@ ## Sorting * [Bead Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bead_sort.cpp) * [Bitonic Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bitonic_sort.cpp) + * [Bogo Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bogo_sort.cpp) * [Bubble Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bubble_sort.cpp) * [Bucket Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bucket_sort.cpp) * [Cocktail Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/cocktail_selection_sort.cpp) diff --git a/sorting/bogo_sort.cpp b/sorting/bogo_sort.cpp new file mode 100644 index 000000000..a7dfd8496 --- /dev/null +++ b/sorting/bogo_sort.cpp @@ -0,0 +1,115 @@ +/** + * @file + * @brief Implementation of [Bogosort algorithm](https://en.wikipedia.org/wiki/Bogosort) + * + * @details + * In computer science, bogosort (also known as permutation sort, stupid sort, slowsort, + * shotgun sort, random sort, monkey sort, bobosort or shuffle sort) is a highly inefficient + * sorting algorithm based on the generate and test paradigm. Two versions of this algorithm + * exist: a deterministic version that enumerates all permutations until it hits a sorted one, + * and a randomized version that randomly permutes its input.Randomized version is implemented here. + * + * Algorithm - + * + * Shuffle the array untill array is sorted. + * + */ +#include +#include +#include +#include + + +/** + * @namespace sorting + * @brief Sorting algorithms + */ +namespace sorting { +/** + * Function to shuffle the elements of an array. (for reference) + * @tparam T typename of the array + * @tparam N length of array + * @param arr array to shuffle + * @returns new array with elements shuffled from a given array + */ +template +std::array shuffle (std::array arr) { + for (int i = 0; i < N; i++) { + // Swaps i'th index with random index (less than array size) + std::swap(arr[i], arr[std::rand() % N]); + } + return arr; +} +/** + * Implement randomized Bogosort algorithm and sort the elements of a given array. + * @tparam T typename of the array + * @tparam N length of array + * @param arr array to sort + * @returns new array with elements sorted from a given array + */ +template +std::array randomized_bogosort (std::array arr) { + // Untill array is not sorted + while (!std::is_sorted(arr.begin(), arr.end())) { + std::random_shuffle(arr.begin(), arr.end());// Shuffle the array + } + return arr; +} + +} // namespace sorting + +/** + * Function to display array on screen + * @tparam T typename of the array + * @tparam N length of array + * @param arr array to display + */ +template +void show_array (const std::array &arr) { + for (int x : arr) { + std::cout << x << ' '; + } + std::cout << '\n'; +} + +/** + * Function to test above algorithm + */ +void test() { + // Test 1 + std::array arr1; + for (int &x : arr1) { + x = std::rand() % 100; + } + std::cout << "Original Array : "; + show_array(arr1); + arr1 = sorting::randomized_bogosort(arr1); + std::cout << "Sorted Array : "; + show_array(arr1); + assert(std::is_sorted(arr1.begin(), arr1.end())); + // Test 2 + std::array arr2; + for (int &x : arr2) { + x = std::rand() % 100; + } + std::cout << "Original Array : "; + show_array(arr2); + arr2 = sorting::randomized_bogosort(arr2); + std::cout << "Sorted Array : "; + show_array(arr2); + assert(std::is_sorted(arr2.begin(), arr2.end())); +} + +/** Driver Code */ +int main() { + // Testing + test(); + // Example Usage + std::array arr = {3, 7, 10, 4, 1}; // Defining array which we want to sort + std::cout << "Original Array : "; + show_array(arr); + arr = sorting::randomized_bogosort(arr); // Callling bogo sort on it + std::cout << "Sorted Array : "; + show_array(arr); // Printing sorted array + return 0; +} From 426ecd03f1797d65134389c2acb44f07054ada83 Mon Sep 17 00:00:00 2001 From: shoniavika <48753228+shoniavika@users.noreply.github.com> Date: Sun, 19 Jul 2020 01:01:03 +0400 Subject: [PATCH 02/19] Added queue implementation using two stacks (#953) * added queue implementation using 2 stacks * added empty queue error handling * added empty queue error handling * updated format * deleted macro * added documentation * updated documentation, new func for testing * added copyright * documented queue class * made queue a generic one * handles lvalue error & added consts * added namespace --- data_structures/queue_using_two_stacks.cpp | 144 +++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 data_structures/queue_using_two_stacks.cpp diff --git a/data_structures/queue_using_two_stacks.cpp b/data_structures/queue_using_two_stacks.cpp new file mode 100644 index 000000000..a09644686 --- /dev/null +++ b/data_structures/queue_using_two_stacks.cpp @@ -0,0 +1,144 @@ +/** + * @author [shoniavika](https://github.com/shoniavika) + * @file + * + * Implementation of a Queue using two Stacks. + */ + +#include +#include +#include + +namespace { +/** + * @brief Queue data structure. Stores elements in FIFO + * (first-in-first-out) manner. + * @tparam T datatype to store in the queue + */ +template +class MyQueue { + private: + std::stack s1, s2; + + public: + /** + * Constructor for queue. + */ + MyQueue() = default; + + /** + * Pushes x to the back of queue. + */ + void push(T x); + + /** + * Removes an element from the front of the queue. + */ + const T& pop(); + + /** + * Returns first element, without removing it. + */ + const T& peek() const; + + /** + * Returns whether the queue is empty. + */ + bool empty() const; +}; + +/** + * Appends element to the end of the queue + */ +template +void MyQueue::push(T x) { + while (!s2.empty()) { + s1.push(s2.top()); + s2.pop(); + } + s2.push(x); + while (!s1.empty()) { + s2.push(s1.top()); + s1.pop(); + } +} + +/** + * Removes element from the front of the queue + */ +template +const T& MyQueue::pop() { + const T& temp = MyQueue::peek(); + s2.pop(); + return temp; +} + +/** + * Returns element in the front. + * Does not remove it. + */ +template +const T& MyQueue::peek() const { + if (!empty()) { + return s2.top(); + } + std::cerr << "Queue is empty" << std::endl; + exit(0); +} + +/** + * Checks whether a queue is empty + */ +template +bool MyQueue::empty() const { + return s2.empty() && s1.empty(); +} +} // namespace + +/** + * Testing function + */ +void queue_test() { + MyQueue que; + std::cout << "Test #1\n"; + que.push(2); + que.push(5); + que.push(0); + assert(que.peek() == 2); + assert(que.pop() == 2); + assert(que.peek() == 5); + assert(que.pop() == 5); + assert(que.peek() == 0); + assert(que.pop() == 0); + assert(que.empty() == true); + std::cout << "PASSED\n"; + + std::cout << "Test #2\n"; + que.push(-1); + assert(que.empty() == false); + assert(que.peek() == -1); + assert(que.pop() == -1); + std::cout << "PASSED\n"; + + MyQueue que2; + std::cout << "Test #3\n"; + que2.push(2.31223); + que2.push(3.1415926); + que2.push(2.92); + + assert(que2.peek() == 2.31223); + assert(que2.pop() == 2.31223); + assert(que2.peek() == 3.1415926); + assert(que2.pop() == 3.1415926); + assert(que2.peek() == 2.92); + assert(que2.pop() == 2.92); + std::cout << "PASSED\n"; +} + +/** + * Main function, calls testing function + */ +int main() { + queue_test(); + return 0; +} From e07b0ce9f833f9c6c1d3201c2e97fe0b1de8f960 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sat, 18 Jul 2020 21:01:51 +0000 Subject: [PATCH 03/19] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index cd47fe955..0e699ba95 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -33,6 +33,7 @@ * [Queue Using Array2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_array2.cpp) * [Queue Using Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linked_list.cpp) * [Queue Using Linkedlist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linkedlist.cpp) + * [Queue Using Two Stacks](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_two_stacks.cpp) * [Skip List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/skip_list.cpp) * [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack.h) * [Stack Using Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack_using_array.cpp) From 67ec2aa982918a5c55ed88be2b889a6ed8088092 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sat, 18 Jul 2020 17:16:45 -0400 Subject: [PATCH 04/19] [feature] Gnome sort (#956) * implement gnome sort algorithm * change name as in contribute.md * remove std and fixed style on clang-format * Delete GnomeSort.cpp * style changes * add documentation * T template * style changes * style changes * repeated error fix * cout fixed * fix gnome_sort * add assertions' * added random values test * updating DIRECTORY.md * clang-tidy fixes for 97161cf894dc547ad4b97bd1bc3af4e068a2c137 * fix initial index value * add braces to one line for-loops * fix function documentation Co-authored-by: beqakd Co-authored-by: beqakd <39763019+beqakd@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + sorting/gnome_sort.cpp | 133 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 sorting/gnome_sort.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index 0e699ba95..439c601a9 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -223,6 +223,7 @@ * [Comb Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/comb_sort.cpp) * [Counting Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/counting_sort.cpp) * [Counting Sort String](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/counting_sort_string.cpp) + * [Gnome Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/gnome_sort.cpp) * [Heap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/heap_sort.cpp) * [Insertion Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/insertion_sort.cpp) * [Library Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/library_sort.cpp) diff --git a/sorting/gnome_sort.cpp b/sorting/gnome_sort.cpp new file mode 100644 index 000000000..d56662479 --- /dev/null +++ b/sorting/gnome_sort.cpp @@ -0,0 +1,133 @@ +/** + * @file + * @brief Implementation of [gnome + * sort](https://en.wikipedia.org/wiki/Gnome_sort) algorithm. + * @author [beqakd](https://github.com/beqakd) + * @author [Krishna Vedala](https://github.com/kvedala) + * @details + * Gnome sort algorithm is not the best one but it is widely used. + * The algorithm iteratively checks the order of pairs in the array. If they are + * on right order it moves to the next successive pair, otherwise it swaps + * elements. This operation is repeated until no more swaps are made thus + * indicating the values to be in ascending order. + * + * The time Complexity of the algorithm is \f$O(n^2)\f$ and in some cases it + * can be \f$O(n)\f$. + */ + +#include // for std::swap +#include // for std::array +#include // for assertions +#include // for io operations + +/** + * @namespace sorting + * Sorting algorithms + */ +namespace sorting { +/** + * This implementation is for a C-style array input that gets modified in place. + * @param [in,out] arr our array of elements. + * @param size size of given array + */ +template +void gnomeSort(T *arr, int size) { + // few easy cases + if (size <= 1) { + return; + } + + int index = 0; // initialize some variables. + while (index < size) { + // check for swap + if ((index == 0) || (arr[index] >= arr[index - 1])) { + index++; + } else { + std::swap(arr[index], arr[index - 1]); // swap + index--; + } + } +} + +/** + * This implementation is for a C++-style array input. The function argument is + * a pass-by-value and hence a copy of the array gets created which is then + * modified by the function and returned. + * @tparam T type of data variables in the array + * @tparam size size of the array + * @param [in] arr our array of elements. + * @return array with elements sorted + */ +template +std::array gnomeSort(std::array arr) { + // few easy cases + if (size <= 1) { + return arr; + } + + int index = 0; // initialize loop index + while (index < size) { + // check for swap + if ((index == 0) || (arr[index] >= arr[index - 1])) { + index++; + } else { + std::swap(arr[index], arr[index - 1]); // swap + index--; + } + } + return arr; +} +} // namespace sorting + +/** + * Test function + */ +static void test() { + // Example 1. Creating array of int, + std::cout << "Test 1 - as a C-array..."; + const int size = 6; + std::array arr = {-22, 100, 150, 35, -10, 99}; + sorting::gnomeSort(arr.data(), + size); // pass array data as a C-style array pointer + assert(std::is_sorted(std::begin(arr), std::end(arr))); + std::cout << " Passed\n"; + for (int i = 0; i < size; i++) { + std::cout << arr[i] << ", "; + } + std::cout << std::endl; + + // Example 2. Creating array of doubles. + std::cout << "\nTest 2 - as a std::array..."; + std::array double_arr = {-100.2, 10.2, 20.0, 9.0, 7.5, 7.2}; + std::array sorted_arr = sorting::gnomeSort(double_arr); + assert(std::is_sorted(std::begin(sorted_arr), std::end(sorted_arr))); + std::cout << " Passed\n"; + for (int i = 0; i < size; i++) { + std::cout << double_arr[i] << ", "; + } + std::cout << std::endl; + + // Example 3. Creating random array of float. + std::cout << "\nTest 3 - 200 random numbers as a std::array..."; + const int size2 = 200; + std::array rand_arr{}; + + for (auto &a : rand_arr) { + // generate random numbers between -5.0 and 4.99 + a = float(std::rand() % 1000 - 500) / 100.f; + } + + std::array float_arr = sorting::gnomeSort(rand_arr); + assert(std::is_sorted(std::begin(float_arr), std::end(float_arr))); + std::cout << " Passed\n"; + // for (int i = 0; i < size; i++) std::cout << double_arr[i] << ", "; + std::cout << std::endl; +} + +/** + * Our main function with example of sort method. + */ +int main() { + test(); + return 0; +} From 0b27a9e63198ae2aba2bdfdd7048804cc427823f Mon Sep 17 00:00:00 2001 From: Anmol Mittal Date: Sun, 19 Jul 2020 21:36:29 +0530 Subject: [PATCH 05/19] feat: Add BFS and DFS algorithms to check for cycle in a directed graph (#816) * feat: Add BFS and DFS algorithms to check for cycle in a directed graph * Remove const references for input of simple types Reason: overhead on access * fix bad code sorry for force push * Use pointer instead of the non-const reference because apparently google says so. * Remove a useless and possibly bad Graph constuctor overload * Explicitely specify type of vector during graph instantiation * Minor documentation fixes. * Fix bad code why did I even do this lol. * Some more fixes to the code * Fix a comment. * Use map instead of unordered_map for better performance when using map.find() function and make code compatible with C++11. * Remove copyright line. --- graph/cycle_check_directed_graph.cpp | 67 ++++++++++++++++------------ 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/graph/cycle_check_directed_graph.cpp b/graph/cycle_check_directed_graph.cpp index 0f7b84cd3..a9e4f2c8b 100644 --- a/graph/cycle_check_directed_graph.cpp +++ b/graph/cycle_check_directed_graph.cpp @@ -1,21 +1,19 @@ /** - * Copyright 2020 * @file cycle_check_directed graph.cpp * * @brief BFS and DFS algorithms to check for cycle in a directed graph. * - * @author Anmol3299 - * contact: mittalanmol22@gmail.com + * @author [Anmol3299](mailto:mittalanmol22@gmail.com) * */ -#include // for std::cout -#include // for std::queue -#include // for throwing errors -#include // for std::remove_reference_t -#include // for std::unordered_map -#include // for std::move -#include // for std::vector +#include // for std::cout +#include // for std::map +#include // for std::queue +#include // for throwing errors +#include // for std::remove_reference +#include // for std::move +#include // for std::vector /** * Implementation of non-weighted directed edge of a graph. @@ -43,7 +41,7 @@ struct Edge { : src(source), dest(destination) {} }; -using AdjList = std::unordered_map>; +using AdjList = std::map>; /** * Implementation of graph class. @@ -76,7 +74,7 @@ class Graph { * @param adjList is the adjacency list representation of graph. */ Graph(unsigned int vertices, AdjList&& adjList) - : m_vertices(std::move(vertices)), m_adjList(std::move(adjList)) {} + : m_vertices(vertices), m_adjList(std::move(adjList)) {} /** Create a graph from vertices and a set of edges. * @@ -102,16 +100,14 @@ class Graph { * * @return const reference to the adjacency list */ - std::remove_reference_t const& getAdjList() const { + std::remove_reference::type const& getAdjList() const { return m_adjList; } /** * @return number of vertices in the graph. */ - std::remove_reference_t const& getVertices() const { - return m_vertices; - } + unsigned int getVertices() const { return m_vertices; } /** Add vertices in the graph. * @@ -150,6 +146,15 @@ class Graph { AdjList m_adjList; }; +/** + * Check if a directed graph has a cycle or not. + * + * This class provides 2 methods to check for cycle in a directed graph: + * isCyclicDFS & isCyclicBFS. + * + * - isCyclicDFS uses DFS traversal method to check for cycle in a graph. + * - isCyclidBFS used BFS traversal method to check for cycle in a graph. + */ class CycleCheck { private: enum nodeStates : uint8_t { not_visited = 0, in_stack, visited }; @@ -170,12 +175,13 @@ class CycleCheck { // If the node has children, then recursively visit all children of the // node. - if (auto const& it = adjList.find(node); it != adjList.end()) { + auto const it = adjList.find(node); + if (it != adjList.end()) { for (auto child : it->second) { // If state of child node is "not_visited", evaluate that child // for presence of cycle. - if (auto state_of_child = (*state)[child]; - state_of_child == not_visited) { + auto state_of_child = (*state)[child]; + if (state_of_child == not_visited) { if (isCyclicDFSHelper(adjList, state, child)) { return true; } @@ -204,6 +210,8 @@ class CycleCheck { * @return true if a cycle is detected, else false. */ static bool isCyclicDFS(Graph const& graph) { + auto vertices = graph.getVertices(); + /** State of the node. * * It is a vector of "nodeStates" which represents the state node is in. @@ -211,10 +219,10 @@ class CycleCheck { * * Initially, all nodes are in "not_visited" state. */ - std::vector state(graph.getVertices(), not_visited); + std::vector state(vertices, not_visited); // Start visiting each node. - for (auto node = 0; node < graph.getVertices(); node++) { + for (unsigned int node = 0; node < vertices; node++) { // If a node is not visited, only then check for presence of cycle. // There is no need to check for presence of cycle for a visited // node as it has already been checked for presence of cycle. @@ -239,18 +247,20 @@ class CycleCheck { * @return true if a cycle is detected, else false. */ static bool isCyclicBFS(Graph const& graph) { - AdjList graphAjdList = graph.getAdjList(); + auto graphAjdList = graph.getAdjList(); + auto vertices = graph.getVertices(); - std::vector indegree(graph.getVertices(), 0); + std::vector indegree(vertices, 0); // Calculate the indegree i.e. the number of incident edges to the node. - for (auto const& [parent, children] : graphAjdList) { + for (auto const& list : graphAjdList) { + auto children = list.second; for (auto const& child : children) { indegree[child]++; } } std::queue can_be_solved; - for (auto node = 0; node < graph.getVertices(); node++) { + for (unsigned int node = 0; node < vertices; node++) { // If a node doesn't have any input edges, then that node will // definately not result in a cycle and can be visited safely. if (!indegree[node]) { @@ -259,17 +269,18 @@ class CycleCheck { } // Vertices that need to be traversed. - auto remain = graph.getVertices(); + auto remain = vertices; // While there are safe nodes that we can visit. while (!can_be_solved.empty()) { - auto front = can_be_solved.front(); + auto solved = can_be_solved.front(); // Visit the node. can_be_solved.pop(); // Decrease number of nodes that need to be traversed. remain--; // Visit all the children of the visited node. - if (auto it = graphAjdList.find(front); it != graphAjdList.end()) { + auto it = graphAjdList.find(solved); + if (it != graphAjdList.end()) { for (auto child : it->second) { // Check if we can visited the node safely. if (--indegree[child] == 0) { From ef1bf8849e01cf7f9c24315752e8c9b128615952 Mon Sep 17 00:00:00 2001 From: Deep Raval Date: Mon, 20 Jul 2020 00:12:01 +0530 Subject: [PATCH 06/19] Fixed an issue related to doc (doxygen) (#960) --- sorting/bogo_sort.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sorting/bogo_sort.cpp b/sorting/bogo_sort.cpp index a7dfd8496..62fbef48e 100644 --- a/sorting/bogo_sort.cpp +++ b/sorting/bogo_sort.cpp @@ -9,10 +9,10 @@ * exist: a deterministic version that enumerates all permutations until it hits a sorted one, * and a randomized version that randomly permutes its input.Randomized version is implemented here. * - * Algorithm - - * - * Shuffle the array untill array is sorted. + * ### Algorithm + * Shuffle the array untill array is sorted. * + * @author [Deep Raval](https://github.com/imdeep2905) */ #include #include From 01581bfd5bd8e5ce4de9003d69a9f3cf458a535b Mon Sep 17 00:00:00 2001 From: Deep Raval Date: Mon, 20 Jul 2020 00:20:02 +0530 Subject: [PATCH 07/19] feat: add Caesar Cipher (#957) * Added caesar_cipher.cpp * Added ranged based loops and made some args pass by ref * Changed comment styling and added unnamed namespace * Update ciphers/caesar_cipher.cpp Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> --- ciphers/caesar_cipher.cpp | 124 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 ciphers/caesar_cipher.cpp diff --git a/ciphers/caesar_cipher.cpp b/ciphers/caesar_cipher.cpp new file mode 100644 index 000000000..6c5bba15f --- /dev/null +++ b/ciphers/caesar_cipher.cpp @@ -0,0 +1,124 @@ +/** + * @file caesar_cipher.cpp + * @brief Implementation of [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm. + * + * @details + * In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, + * Caesar's code or Caesar shift, is one of the simplest and most widely known encryption + * techniques. It is a type of substitution cipher in which each letter in the plaintext + * is replaced by a letter some fixed number of positions down the alphabet. For example, + * with a left shift of 3, D would be replaced by A, E would become B, and so on. + * The method is named after Julius Caesar, who used it in his private correspondence. + * + * ### Algorithm + * The encryption can also be represented using modular arithmetic by first transforming + * the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25. + * Encryption of a letter x by a shift n can be described mathematically as, + * \f[ E(x) = (x + n)\;\mbox{mod}\; 26\f] + * while decryption can be described as, + * \f[ D(x) = (x - n) \;\mbox{mod}\; 26\f] + * + * \note This program implements caesar cipher for only uppercase English alphabet characters (i.e. A-Z). + * + * @author [Deep Raval](https://github.com/imdeep2905) + */ +#include +#include +#include + +/** \namespace ciphers + * \brief Algorithms for encryption and decryption + */ +namespace ciphers { + /** \namespace caesar + * \brief Functions for [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm. + */ + namespace caesar { + namespace { + /** + * This function finds character for given value (i.e.A-Z) + * @param x value for which we want character + * @returns corresponding character for perticular value + */ + inline char get_char(const int x) { + // By adding 65 we are scaling 0-25 to 65-90. + // Which are in fact ASCII values of A-Z. + return char(x + 65); + } + /** + * This function finds value for given character (i.e.0-25) + * @param c character for which we want value + * @returns returns corresponding value for perticular character + */ + inline int get_value(const char c) { + // A-Z have ASCII values in range 65-90. + // Hence subtracting 65 will scale them to 0-25. + return int(c - 65); + } + } // Unnamed namespace + /** + * Encrypt given text using caesar cipher. + * @param text text to be encrypted + * @param shift number of shifts to be applied + * @returns new encrypted text + */ + std::string encrypt (const std::string &text, const int &shift) { + std::string encrypted_text = ""; // Empty string to store encrypted text + for (char c : text) { // Going through each character + int place_value = get_value(c); // Getting value of character (i.e. 0-25) + place_value = (place_value + shift) % 26; // Applying encryption formula + char new_char = get_char(place_value); // Getting new character from new value (i.e. A-Z) + encrypted_text += new_char; // Appending encrypted character + } + return encrypted_text; // Returning encrypted text + } + /** + * Decrypt given text using caesar cipher. + * @param text text to be decrypted + * @param shift number of shifts to be applied + * @returns new decrypted text + */ + std::string decrypt (const std::string &text, const int &shift) { + std::string decrypted_text = ""; // Empty string to store decrypted text + for (char c : text) { // Going through each character + int place_value = get_value(c); // Getting value of character (i.e. 0-25) + place_value = (place_value - shift) % 26;// Applying decryption formula + if(place_value < 0) { // Handling case where remainder is negative + place_value = place_value + 26; + } + char new_char = get_char(place_value); // Getting original character from decrypted value (i.e. A-Z) + decrypted_text += new_char; // Appending decrypted character + } + return decrypted_text; // Returning decrypted text + } + } // namespace caesar +} // namespace ciphers + +/** + * Function to test above algorithm + */ +void test() { + // Test 1 + std::string text1 = "ALANTURING"; + std::string encrypted1 = ciphers::caesar::encrypt(text1, 17); + std::string decrypted1 = ciphers::caesar::decrypt(encrypted1, 17); + assert(text1 == decrypted1); + std::cout << "Original text : " << text1; + std::cout << " , Encrypted text (with shift = 21) : " << encrypted1; + std::cout << " , Decrypted text : "<< decrypted1 << std::endl; + // Test 2 + std::string text2 = "HELLOWORLD"; + std::string encrypted2 = ciphers::caesar::encrypt(text2, 1729); + std::string decrypted2 = ciphers::caesar::decrypt(encrypted2, 1729); + assert(text2 == decrypted2); + std::cout << "Original text : " << text2; + std::cout << " , Encrypted text (with shift = 1729) : " << encrypted2; + std::cout << " , Decrypted text : "<< decrypted2 << std::endl; +} + +/** Driver Code */ +int main() { + // Testing + test(); + return 0; +} From eaf4bb20192cb25201cf1cb28ea7003effc6a950 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 19 Jul 2020 18:50:47 +0000 Subject: [PATCH 08/19] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 439c601a9..e7ce1ee1d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -11,6 +11,7 @@ * [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp) ## Ciphers + * [Caesar Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/caesar_cipher.cpp) * [Hill Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/hill_cipher.cpp) ## Data Structures From 7f92f54bdea33fef4da6e2c01b7d61122d5893cf Mon Sep 17 00:00:00 2001 From: Deep Raval Date: Mon, 20 Jul 2020 02:15:45 +0530 Subject: [PATCH 09/19] feat: Add XOR Cipher (#961) * Added XOR Cipher * Remoced repetition of c ^ key in encrypt * Added explicit type conversion * Applied Suggested Changes * Added bullet points --- ciphers/xor_cipher.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 ciphers/xor_cipher.cpp diff --git a/ciphers/xor_cipher.cpp b/ciphers/xor_cipher.cpp new file mode 100644 index 000000000..18cbdd61f --- /dev/null +++ b/ciphers/xor_cipher.cpp @@ -0,0 +1,99 @@ +/** + * @file xor_cipher.cpp + * @brief Implementation of [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm. + * + * @details + * In cryptography, the simple XOR cipher is a type of additive cipher, an encryption + * algorithm that operates according to the principles: + * + * * \f$A {\oplus} 0 = A\f$ + * * \f$A {\oplus} A = 0\f$ + * * \f$ (A {\oplus} B) {\oplus} C = A {\oplus} (B {\oplus} C)\f$ + * * \f$ (B {\oplus} A) {\oplus} B = B {\oplus} 0 = B \f$ + * + * + * where \f$\oplus\f$ symbol denotes the exclusive disjunction (XOR) operation. + * This operation is sometimes called modulus 2 addition (or subtraction, which is identical). + * With this logic, a string of text can be encrypted by applying the bitwise XOR operator to + * every character using a given key. To decrypt the output, merely reapplying the XOR function + * with the key will remove the cipher. + * + * ### Algorithm + * Choose the key for encryption and apply XOR operation to each character of a string. + * Reapplying XOR operation to each character of encrypted string will give original string back. + * + * \note This program implements XOR Cipher for string with ASCII characters. + * + * @author [Deep Raval](https://github.com/imdeep2905) + */ +#include +#include +#include + +/** \namespace ciphers + * \brief Algorithms for encryption and decryption + */ +namespace ciphers { + /** \namespace XOR + * \brief Functions for [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm. + */ + namespace XOR { + /** + * Encrypt given text using XOR cipher. + * @param text text to be encrypted + * @param key to be used for encyption + * @return new encrypted text + */ + std::string encrypt (const std::string &text, const int &key) { + std::string encrypted_text = ""; // Empty string to store encrypted text + for (auto &c: text) { // Going through each character + char encrypted_char = char(c ^ key); // Applying encyption + encrypted_text += encrypted_char; // Appending encrypted character + } + return encrypted_text; // Returning encrypted text + } + /** + * Decrypt given text using XOR cipher. + * @param text text to be encrypted + * @param key to be used for decryption + * @return new decrypted text + */ + std::string decrypt (const std::string &text, const int &key) { + std::string decrypted_text = ""; // Empty string to store decrypted text + for (auto &c : text) { // Going through each character + char decrypted_char = char(c ^ key); // Applying decryption + decrypted_text += decrypted_char; // Appending decrypted character + } + return decrypted_text; // Returning decrypted text + } + } // namespace XOR +} // namespace ciphers + +/** + * Function to test above algorithm + */ +void test() { + // Test 1 + std::string text1 = "Whipalsh! : Do watch this movie..."; + std::string encrypted1 = ciphers::XOR::encrypt(text1, 17); + std::string decrypted1 = ciphers::XOR::decrypt(encrypted1, 17); + assert(text1 == decrypted1); + std::cout << "Original text : " << text1; + std::cout << " , Encrypted text (with key = 17) : " << encrypted1; + std::cout << " , Decrypted text : "<< decrypted1 << std::endl; + // Test 2 + std::string text2 = "->Valar M0rghulis<-"; + std::string encrypted2 = ciphers::XOR::encrypt(text2, 29); + std::string decrypted2 = ciphers::XOR::decrypt(encrypted2, 29); + assert(text2 == decrypted2); + std::cout << "Original text : " << text2; + std::cout << " , Encrypted text (with key = 29) : " << encrypted2; + std::cout << " , Decrypted text : "<< decrypted2 << std::endl; +} + +/** Driver Code */ +int main() { + // Testing + test(); + return 0; +} From 193f9c466acff2c64a49da4094d6c3bc8daa5c46 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 19 Jul 2020 20:46:35 +0000 Subject: [PATCH 10/19] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index e7ce1ee1d..ac51f2df1 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -13,6 +13,7 @@ ## Ciphers * [Caesar Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/caesar_cipher.cpp) * [Hill Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/hill_cipher.cpp) + * [Xor Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/xor_cipher.cpp) ## Data Structures * [Avltree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/avltree.cpp) From cf562f224473f25f6ecb7b7034fb07a9b02eb61f Mon Sep 17 00:00:00 2001 From: Deep Raval Date: Mon, 20 Jul 2020 23:20:40 +0530 Subject: [PATCH 11/19] =?UTF-8?q?feat:=20Add=20Vigen=C3=A8re=20cipher=20(#?= =?UTF-8?q?962)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added Vigenere Cipher * Added size_t instead of int in for loop * Update ciphers/vigenere_cipher.cpp Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> * Update ciphers/vigenere_cipher.cpp Co-authored-by: David Leal Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Co-authored-by: David Leal --- ciphers/vigenere_cipher.cpp | 135 ++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 ciphers/vigenere_cipher.cpp diff --git a/ciphers/vigenere_cipher.cpp b/ciphers/vigenere_cipher.cpp new file mode 100644 index 000000000..cb5b959b6 --- /dev/null +++ b/ciphers/vigenere_cipher.cpp @@ -0,0 +1,135 @@ +/** + * @file vigenere_cipher.cpp + * @brief Implementation of [Vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm. + * + * @details + * The Vigenère cipher is a method of encrypting alphabetic text by using a series of interwoven vigenere + * ciphers, based on the letters of a keyword. It employs a form of polyalphabetic substitution. + * + * ### Algorithm + * The encryption can also be represented using modular arithmetic by first transforming + * the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25. + * Encryption of \f$\i^{th}\f$ character in Message M by key K can be described mathematically as, + * + * \f[ E_{K}(M_{i}) = (M_{i} + K_{i})\;\mbox{mod}\; 26\f] + * + * while decryption of \f$\i^{th}\f$ character in Cipher C by key K can be described mathematically as, + * + * \f[ D_{k}(C_{i}) = (C_{i} - K_{i} + 26)\;\mbox{mod}\; 26\f] + * + * Where \f$\K_{i}\f$ denotes corresponding character in key. If \f$\|key| < |text|\f$ than + * same key is repeated untill their lengths are equal. + * + * For Example, + * If M = "ATTACKATDAWN" and K = "LEMON" than K becomes "LEMONLEMONLE". + * + * \note Rather than creating new key of equal length this program does this by using modular index for key + * (i.e. \f$(j + 1) \;\mbox{mod}\; |\mbox{key}|\f$) + * + * \note This program implements Vigenère cipher for only uppercase English alphabet characters (i.e. A-Z). + * + * @author [Deep Raval](https://github.com/imdeep2905) + */ +#include +#include +#include + +/** \namespace ciphers + * \brief Algorithms for encryption and decryption + */ +namespace ciphers { + /** \namespace vigenere + * \brief Functions for [vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm. + */ + namespace vigenere { + namespace { + /** + * This function finds character for given value (i.e.A-Z) + * @param x value for which we want character + * @return corresponding character for perticular value + */ + inline char get_char(const int x) { + // By adding 65 we are scaling 0-25 to 65-90. + // Which are in fact ASCII values of A-Z. + return char(x + 65); + } + /** + * This function finds value for given character (i.e.0-25) + * @param c character for which we want value + * @return returns corresponding value for perticular character + */ + inline int get_value(const char c) { + // A-Z have ASCII values in range 65-90. + // Hence subtracting 65 will scale them to 0-25. + return int(c - 65); + } + } // Unnamed namespace + /** + * Encrypt given text using vigenere cipher. + * @param text text to be encrypted + * @param key to be used for encryption + * @return new encrypted text + */ + std::string encrypt (const std::string &text, const std::string &key) { + std::string encrypted_text = ""; // Empty string to store encrypted text + // Going through each character of text and key + // Note that key is visited in circular way hence j = (j + 1) % |key| + for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) { + int place_value_text = get_value(text[i]); // Getting value of character in text + int place_value_key = get_value(key[j]); // Getting value of character in key + place_value_text = (place_value_text + place_value_key) % 26; // Applying encryption + char encrypted_char = get_char(place_value_text); // Getting new character from encrypted value + encrypted_text += encrypted_char; // Appending encrypted character + } + return encrypted_text; // Returning encrypted text + } + /** + * Decrypt given text using vigenere cipher. + * @param text text to be decrypted + * @param key key to be used for decryption + * @return new decrypted text + */ + std::string decrypt (const std::string &text, const std::string &key) { + // Going through each character of text and key + // Note that key is visited in circular way hence j = (j + 1) % |key| + std::string decrypted_text = ""; // Empty string to store decrypted text + for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) { + int place_value_text = get_value(text[i]); // Getting value of character in text + int place_value_key = get_value(key[j]); // Getting value of character in key + place_value_text = (place_value_text - place_value_key + 26) % 26; // Applying decryption + char decrypted_char = get_char(place_value_text); // Getting new character from decrypted value + decrypted_text += decrypted_char; // Appending decrypted character + } + return decrypted_text; // Returning decrypted text + } + } // namespace vigenere +} // namespace ciphers + +/** + * Function to test above algorithm + */ +void test() { + // Test 1 + std::string text1 = "NIKOLATESLA"; + std::string encrypted1 = ciphers::vigenere::encrypt(text1, "TESLA"); + std::string decrypted1 = ciphers::vigenere::decrypt(encrypted1, "TESLA"); + assert(text1 == decrypted1); + std::cout << "Original text : " << text1; + std::cout << " , Encrypted text (with key = TESLA) : " << encrypted1; + std::cout << " , Decrypted text : "<< decrypted1 << std::endl; + // Test 2 + std::string text2 = "GOOGLEIT"; + std::string encrypted2 = ciphers::vigenere::encrypt(text2, "REALLY"); + std::string decrypted2 = ciphers::vigenere::decrypt(encrypted2, "REALLY"); + assert(text2 == decrypted2); + std::cout << "Original text : " << text2; + std::cout << " , Encrypted text (with key = REALLY) : " << encrypted2; + std::cout << " , Decrypted text : "<< decrypted2 << std::endl; +} + +/** Driver Code */ +int main() { + // Testing + test(); + return 0; +} From 01ba336866527a480214ae50e874c59a0c4b7f2d Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 20 Jul 2020 17:51:30 +0000 Subject: [PATCH 12/19] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index ac51f2df1..f10518ae4 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -13,6 +13,7 @@ ## Ciphers * [Caesar Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/caesar_cipher.cpp) * [Hill Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/hill_cipher.cpp) + * [Vigenere Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/vigenere_cipher.cpp) * [Xor Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/xor_cipher.cpp) ## Data Structures From 8d68e61edf226acfe3a4ed0890ea55cd09de3fd9 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Mon, 20 Jul 2020 21:12:31 -0400 Subject: [PATCH 13/19] [feature] new implementation of Quick sort (#958) * added quick_sort_3 * Corrected some formatting error * made more C-plus-plusy * add test cases * updating DIRECTORY.md * clang-tidy fixes for 30c9a199ad0ad1ee524c85766dcefe70723afc3a * better selef-tests + use std::vector * use size_t * change size_t to int32_t Co-authored-by: mohit Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + sorting/quick_sort_3.cpp | 188 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 sorting/quick_sort_3.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index f10518ae4..59c3a7e40 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -235,6 +235,7 @@ * [Numeric String Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/numeric_string_sort.cpp) * [Odd Even Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/odd_even_sort.cpp) * [Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort.cpp) + * [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) * [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/quick_sort_3.cpp b/sorting/quick_sort_3.cpp new file mode 100644 index 000000000..b365144a1 --- /dev/null +++ b/sorting/quick_sort_3.cpp @@ -0,0 +1,188 @@ +/** + * @file + * @brief Implementation Details + * @details Quick sort 3 works on Dutch National Flag Algorithm + * The major difference between simple quicksort and quick sort 3 comes in the + * function partition3 In quick_sort_partition3 we divide the vector/array into + * 3 parts. quick sort 3 works faster in some cases as compared to simple + * quicksort. + * @author immortal-j + * @author [Krishna Vedala](https://github/kvedala) + */ +#include +#include +#include +#include +#include + +namespace { +/** + * Operator to print the array. + * @param out std::ostream object to write to + * @param arr array to write + */ +template +std::ostream &operator<<(std::ostream &out, const std::vector &arr) { + for (size_t i = 0; i < arr.size(); ++i) { + out << arr[i]; + if (i < arr.size() - 1) { + out << ", "; + } + } + return out; +} + +} // namespace + +/** + * @namespace sorting + * @brief Sorting Algorithms + */ +namespace sorting { +namespace { // using un-named namespace here to prevent partition function + // being visible to end-users +/** This function partitions `arr[]` in three parts + * 1. \f$arr[l\ldots i]\f$ contains all elements smaller than pivot + * 2. \f$arr[(i+1)\ldots (j-1)]\f$ contains all occurrences of pivot + * 3. \f$arr[j\ldots r]\f$ contains all elements greater than pivot + * @tparam T type of data in the vector array + * @param [in,out] arr vector array being partitioned + * @param [in] low lower limit of window to partition + * @param [in] high upper limit of window to partition + * @param [out] i updated lower limit of partition + * @param [out] j updated upper limit of partition + */ +template +void partition3(std::vector *arr, int32_t low, int32_t high, int32_t *i, + int32_t *j) { + // To handle 2 elements + if (high - low <= 1) { + if ((*arr)[high] < (*arr)[low]) { + std::swap((*arr)[high], (*arr)[low]); + } + *i = low; + *j = high; + return; + } + + int32_t mid = low; + T pivot = (*arr)[high]; + while (mid <= high) { + if ((*arr)[mid] < pivot) { + std::swap((*arr)[low++], (*arr)[mid++]); + } else if ((*arr)[mid] == pivot) { + mid++; + } else if ((*arr)[mid] > pivot) { + std::swap((*arr)[mid], (*arr)[high--]); + } + } + + // update i and j + *i = low - 1; + *j = mid; // or high-1 +} +} // namespace + +/** 3-way partition based quick sort. This function accepts array pointer and + * modified the input array. + * @tparam T type of data in the vector array + * @param [in,out] arr vector array to sort + * @param [in] low lower limit of window to partition + * @param [in] high upper limit of window to partition + */ +template +void quicksort(std::vector *arr, int32_t low, int32_t high) { + if (low >= high) { // 1 or 0 elements + return; + } + + int32_t i = 0, j = 0; + + // i and j are passed as reference + partition3(arr, low, high, &i, &j); + + // Recur two halves + quicksort(arr, low, i); + quicksort(arr, j, high); +} + +/** 3-way partition based quick sort. This function accepts array by value and + * creates a copy of it. The array copy gets sorted and returned by the + * function. + * @tparam T type of data in the vector array + * @param [in] arr vector array to sort + * @param [in] low lower limit of window to partition + * @param [in] high upper limit of window to partition + * @returns sorted array vector + */ +template +std::vector quicksort(std::vector arr, int32_t low, int32_t high) { + if (low >= high) { // 1 or 0 elements + return arr; + } + + int32_t i = 0, j = 0; + + // i and j are passed as reference + partition3(&arr, low, high, &i, &j); + + // Recur two halves + quicksort(&arr, low, i); + quicksort(&arr, j, high); + + return arr; +} +} // namespace sorting + +/** Test function for integer type arrays */ +static void test_int() { + std::cout << "\nTesting integer type arrays\n"; + + for (int num_tests = 1; num_tests < 21; num_tests++) { + size_t size = std::rand() % 500; + std::vector arr(size); + for (auto &a : arr) { + a = std::rand() % 500 - 250; // random numbers between -250, 249 + } + + std::cout << "Test " << num_tests << "\t Array size:" << size << "\t "; + std::vector sorted = sorting::quicksort(arr, 0, size - 1); + if (size < 20) { + std::cout << "\t Sorted Array is:\n\t"; + std::cout << sorted << "\n"; + } + assert(std::is_sorted(std::begin(sorted), std::end(sorted))); + std::cout << "\t Passed\n"; + } +} + +/** Test function for double type arrays */ +static void test_double() { + std::cout << "\nTesting Double type arrays\n"; + for (int num_tests = 1; num_tests < 21; num_tests++) { + size_t size = std::rand() % 500; + std::vector arr(size); + for (auto &a : arr) { + a = double(std::rand() % 500) - + 250.f; // random numbers between -250, 249 + a /= 100.f; // convert to -2.5 to 2.49 + } + + std::cout << "Test " << num_tests << "\t Array size:" << size << "\t "; + std::vector sorted = sorting::quicksort(arr, 0, size - 1); + if (size < 20) { + std::cout << "\t Sorted Array is:\n\t"; + std::cout << sorted << "\n"; + } + assert(std::is_sorted(std::begin(sorted), std::end(sorted))); + std::cout << "\t Passed\n"; + } +} + +/** Driver program for above functions */ +int main() { + std::srand(std::time(nullptr)); + test_int(); + test_double(); + return 0; +} From 794e1765bd425d4f1771c6731940fa9f58399bac Mon Sep 17 00:00:00 2001 From: Deep Raval Date: Tue, 21 Jul 2020 17:11:05 +0530 Subject: [PATCH 14/19] docs: Fixed an issue in Vigenere cipher documentation (#964) * Fixed a doxygen doc issue * Chnaged ||key| < |text| to |key| < |text| --- ciphers/vigenere_cipher.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ciphers/vigenere_cipher.cpp b/ciphers/vigenere_cipher.cpp index cb5b959b6..4efd56c00 100644 --- a/ciphers/vigenere_cipher.cpp +++ b/ciphers/vigenere_cipher.cpp @@ -9,15 +9,15 @@ * ### Algorithm * The encryption can also be represented using modular arithmetic by first transforming * the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25. - * Encryption of \f$\i^{th}\f$ character in Message M by key K can be described mathematically as, + * Encryption of \f$i^{th}\f$ character in Message M by key K can be described mathematically as, * * \f[ E_{K}(M_{i}) = (M_{i} + K_{i})\;\mbox{mod}\; 26\f] * - * while decryption of \f$\i^{th}\f$ character in Cipher C by key K can be described mathematically as, + * while decryption of \f$i^{th}\f$ character in Cipher C by key K can be described mathematically as, * * \f[ D_{k}(C_{i}) = (C_{i} - K_{i} + 26)\;\mbox{mod}\; 26\f] * - * Where \f$\K_{i}\f$ denotes corresponding character in key. If \f$\|key| < |text|\f$ than + * Where \f$K_{i}\f$ denotes corresponding character in key. If \f$|key| < |text|\f$ than * same key is repeated untill their lengths are equal. * * For Example, From d58954523f338dbf541c86024fd4f957b9ea87e4 Mon Sep 17 00:00:00 2001 From: Filip Hlasek Date: Wed, 22 Jul 2020 05:01:06 -0700 Subject: [PATCH 15/19] fix: Integer overflow of least_common_multiple. (#970) * fix: Integer overflow of least_common_multiple. * Update the typing (linter warning). --- math/least_common_multiple.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/math/least_common_multiple.cpp b/math/least_common_multiple.cpp index 741945716..e9e46490a 100644 --- a/math/least_common_multiple.cpp +++ b/math/least_common_multiple.cpp @@ -26,12 +26,12 @@ unsigned int gcd(unsigned int x, unsigned int y) { if (x > y) { // The following is valid because we have checked whether y == 0 - int temp = x / y; + unsigned int temp = x / y; return gcd(y, x - temp * y); } // Again the following is valid because we have checked whether x == 0 - int temp = y / x; + unsigned int temp = y / x; return gcd(x, y - temp * x); } @@ -40,7 +40,9 @@ unsigned int gcd(unsigned int x, unsigned int y) { * @params integer x and y whose lcm we want to find. * @return lcm of x and y using the relation x * y = gcd(x, y) * lcm(x, y) */ -unsigned int lcm(unsigned int x, unsigned int y) { return x * y / gcd(x, y); } +unsigned int lcm(unsigned int x, unsigned int y) { + return x / gcd(x, y) * y; +} /** * Function for testing the lcm() functions with some assert statements. @@ -59,6 +61,15 @@ void tests() { lcm(2, 3) == 6)); std::cout << "Second assertion passes: LCM of 2 and 3 is " << lcm(2, 3) << std::endl; + + // Testing an integer overflow. + // The algorithm should work as long as the result fits into integer. + assert(((void)"LCM of 987654321 and 987654321 is 987654321 but lcm function" + " gives a different result.\n", + lcm(987654321, 987654321) == 987654321)); + std::cout << "Third assertion passes: LCM of 987654321 and 987654321 is " + << lcm(987654321, 987654321) + << std::endl; } /** From 42e1246ffcbb2954bbb20cc4a7c51a8611fe8fd6 Mon Sep 17 00:00:00 2001 From: Filip Hlasek Date: Thu, 23 Jul 2020 04:50:38 -0700 Subject: [PATCH 16/19] fix, test: Refactor of sieve_of_eratosthenes (#969) * fix, test: Refactor of sieve_of_eratosthenes * Add missing include. * Modernize the vector initialization. * Add @details for the documentation. --- math/sieve_of_eratosthenes.cpp | 56 +++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/math/sieve_of_eratosthenes.cpp b/math/sieve_of_eratosthenes.cpp index e30bc1891..e011b6c00 100644 --- a/math/sieve_of_eratosthenes.cpp +++ b/math/sieve_of_eratosthenes.cpp @@ -1,58 +1,72 @@ /** * @file * @brief Get list of prime numbers using Sieve of Eratosthenes - * Sieve of Eratosthenes is an algorithm to find the primes - * that is between 2 to N (as defined in main). + * @details + * Sieve of Eratosthenes is an algorithm that finds all the primes + * between 2 and N. * - * Time Complexity : \f$O(N \cdot\log N)\f$ + * Time Complexity : \f$O(N \cdot\log \log N)\f$ *
Space Complexity : \f$O(N)\f$ * * @see primes_up_to_billion.cpp prime_numbers.cpp */ -#include // for io operations +#include +#include +#include /** - * This is the function that finds the primes and eliminates - * the multiples. + * This is the function that finds the primes and eliminates the multiples. + * Contains a common optimization to start eliminating multiples of + * a prime p starting from p * p since all of the lower multiples + * have been already eliminated. * @param N number of primes to check - * @param [out] isprime a boolean array of size `N` identifying if `i`^th number is prime or not + * @return is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not */ -void sieve(uint32_t N, bool *isprime) { - isprime[0] = true; - isprime[1] = true; +std::vector sieve(uint32_t N) { + std::vector is_prime(N + 1, true); + is_prime[0] = is_prime[1] = false; for (uint32_t i = 2; i * i <= N; i++) { - if (!isprime[i]) { - for (uint32_t j = (i << 1); j <= N; j = j + i) { - isprime[j] = true; + if (is_prime[i]) { + for (uint32_t j = i * i; j <= N; j += i) { + is_prime[j] = false; } } } + return is_prime; } /** * This function prints out the primes to STDOUT * @param N number of primes to check - * @param [in] isprime a boolean array of size `N` identifying if `i`^th number is prime or not + * @param is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not */ -void print(uint32_t N, const bool *isprime) { +void print(uint32_t N, const std::vector &is_prime) { for (uint32_t i = 2; i <= N; i++) { - if (!isprime[i]) { + if (is_prime[i]) { std::cout << i << ' '; } } std::cout << std::endl; } +/** + * Test implementations + */ +void tests() { + // 0 1 2 3 4 5 6 7 8 9 10 + std::vector ans{false, false, true, true, false, true, false, true, false, false, false}; + assert(sieve(10) == ans); +} + /** * Main function */ int main() { - uint32_t N = 100; - bool *isprime = new bool[N]; - sieve(N, isprime); - print(N, isprime); - delete[] isprime; + tests(); + uint32_t N = 100; + std::vector is_prime = sieve(N); + print(N, is_prime); return 0; } From 528228640834c0e25d48c2cc1bf2b258f1f024dd Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 15:51:48 -0400 Subject: [PATCH 17/19] install freeglut3-dev (#973) --- .gitpod.dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile index 53d336f81..f38914053 100644 --- a/.gitpod.dockerfile +++ b/.gitpod.dockerfile @@ -5,5 +5,7 @@ RUN sudo apt-get update \ doxygen \ graphviz \ ninja-build \ + freeglut3 \ + freeglut3-dev \ && pip install cpplint \ && sudo rm -rf /var/lib/apt/lists/* From 09d47709f87af94462bc7f1f9fabe27822e27df6 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 16:59:28 -0400 Subject: [PATCH 18/19] updated free glut checksum (#976) --- graphics/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index 2ea6ca230..753b79ff8 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -7,7 +7,7 @@ if(OpenGL_FOUND) ExternalProject_Add ( FREEGLUT-PRJ URL https://sourceforge.net/projects/freeglut/files/freeglut/3.2.1/freeglut-3.2.1.tar.gz - URL_MD5 cd5c670c1086358598a6d4a9d166949d + URL_MD5 afd33cb888461aae3bfd05b80c9e42a8 CMAKE_GENERATOR ${CMAKE_GENERATOR} CMAKE_GENERATOR_TOOLSET ${CMAKE_GENERATOR_TOOLSET} CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM} From d8affb52e30a1fd6f993dcc07750892f9b1216ea Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 24 Jul 2020 16:41:01 -0400 Subject: [PATCH 19/19] Revert "updated free glut checksum (#976)" (#979) This reverts commit 09d47709f87af94462bc7f1f9fabe27822e27df6. --- graphics/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index 753b79ff8..2ea6ca230 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -7,7 +7,7 @@ if(OpenGL_FOUND) ExternalProject_Add ( FREEGLUT-PRJ URL https://sourceforge.net/projects/freeglut/files/freeglut/3.2.1/freeglut-3.2.1.tar.gz - URL_MD5 afd33cb888461aae3bfd05b80c9e42a8 + URL_MD5 cd5c670c1086358598a6d4a9d166949d CMAKE_GENERATOR ${CMAKE_GENERATOR} CMAKE_GENERATOR_TOOLSET ${CMAKE_GENERATOR_TOOLSET} CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM}