diff --git a/DIRECTORY.md b/DIRECTORY.md index 5a8c7fa04..d86f504c4 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -155,6 +155,7 @@ * [Modular Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_exponentiation.cpp) * [Modular Inverse Fermat Little Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_inverse_fermat_little_theorem.cpp) * [N Choose R](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/n_choose_r.cpp) + * [Ncr Modulo P](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/ncr_modulo_p.cpp) * [Number Of Positive Divisors](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/number_of_positive_divisors.cpp) * [Power For Huge Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/power_for_huge_numbers.cpp) * [Prime Factorization](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/prime_factorization.cpp) diff --git a/data_structures/list_array.cpp b/data_structures/list_array.cpp index 6cbf8e154..9dd142a5a 100644 --- a/data_structures/list_array.cpp +++ b/data_structures/list_array.cpp @@ -3,25 +3,27 @@ * @todo Add documentation * @warning The sorting algorithm is erroneous */ -#include #include +#include struct list { std::array data{}; int top = 0; bool isSorted = false; - int BinarySearch(const std::array& dataArr, int first, int last, int x) { + int BinarySearch(const std::array& dataArr, int first, int last, + int x) { if (last < first) { return -1; } int mid = (first + last) / 2; - if (dataArr[mid] == x) + if (dataArr[mid] == x) { return mid; - else if (x < dataArr[mid]) + } else if (x < dataArr[mid]) { return (BinarySearch(dataArr, first, mid - 1, x)); - else if (x > dataArr[mid]) + } else if (x > dataArr[mid]) { return (BinarySearch(dataArr, mid + 1, last, x)); + } std::cerr << __func__ << ":" << __LINE__ << ": Undefined condition\n"; return -1; @@ -38,7 +40,7 @@ struct list { } int Search(int x) { - int pos; + int pos = 0; if (isSorted) { pos = BinarySearch(data, 0, top - 1, x); @@ -55,7 +57,7 @@ struct list { } void Sort() { - int i, j, pos=0; + int i = 0, j = 0, pos = 0; for (i = 0; i < top; i++) { int min = data[i]; for (j = i + 1; j < top; j++) { @@ -119,8 +121,8 @@ struct list { int main() { list L; - int choice; - int x; + int choice = 0; + int x = 0; do { // Choices for operations on the list_array. std::cout << "\n0.Exit"; diff --git a/data_structures/queue_using_array.cpp b/data_structures/queue_using_array.cpp index 4cda860ca..8b9b387c5 100644 --- a/data_structures/queue_using_array.cpp +++ b/data_structures/queue_using_array.cpp @@ -7,19 +7,20 @@ * values, which can be added to the end line (enqueue), removed from * head of line (dequeue) and displayed. * ### Algorithm - * Values can be added by increasing the `rear` variable by 1 (which points to - * the end of the array), then assigning new value to `rear`'s element of the array. - * - * Values can be removed by increasing the `front` variable by 1 (which points to - * the first of the array), so it cannot reached any more. - * + * Values can be added by increasing the `rear` variable by 1 (which points to + * the end of the array), then assigning new value to `rear`'s element of the + * array. + * + * Values can be removed by increasing the `front` variable by 1 (which points + * to the first of the array), so it cannot reached any more. + * * @author [Pooja](https://github.com/pooja-git11) * @author [Farbod Ahmadian](https://github.com/farbodahm) */ -#include /// for io operations -#include /// for std::array +#include /// for std::array +#include /// for io operations -constexpr uint16_t max_size{10}; ///< Maximum size of the queue +constexpr uint16_t max_size{10}; ///< Maximum size of the queue /** * @namespace data_structures @@ -30,29 +31,31 @@ namespace data_structures { /** * @namespace queue_using_array * @brief Functions for [Queue using Array] - * (https://www.geeksforgeeks.org/array-implementation-of-queue-simple/) implementation. + * (https://www.geeksforgeeks.org/array-implementation-of-queue-simple/) + * implementation. */ namespace queue_using_array { /** - * @brief Queue_Array class containing the main data and also index of head and tail of the array. + * @brief Queue_Array class containing the main data and also index of head and + * tail of the array. */ class Queue_Array { -public: + public: void enqueue(const int16_t&); ///< Add element to the first of the queue - int dequeue(); ///< Delete element from back of the queue - void display() const; ///< Show all saved data -private: - int8_t front{-1}; ///< Index of head of the array - int8_t rear{-1}; ///< Index of tail of the array - std::array arr; ///< All stored data + int dequeue(); ///< Delete element from back of the queue + void display() const; ///< Show all saved data + private: + int8_t front{-1}; ///< Index of head of the array + int8_t rear{-1}; ///< Index of tail of the array + std::array arr{}; ///< All stored data }; /** * @brief Adds new element to the end of the queue * @param ele to be added to the end of the queue */ -void Queue_Array::enqueue(const int16_t& ele ) { +void Queue_Array::enqueue(const int16_t& ele) { if (rear == arr.size() - 1) { std::cout << "\nStack is full"; } else if (front == -1 && rear == -1) { @@ -98,7 +101,6 @@ void Queue_Array::display() const { } // namespace queue_using_array } // namespace data_structures - /** * @brief Main function * @details diff --git a/dynamic_programming/0_1_knapsack.cpp b/dynamic_programming/0_1_knapsack.cpp index 2e0a82e6a..4820c9ff1 100644 --- a/dynamic_programming/0_1_knapsack.cpp +++ b/dynamic_programming/0_1_knapsack.cpp @@ -75,10 +75,11 @@ int maxKnapsackValue(const int capacity, const std::array &weight, int profit2 = maxValue[i - 1][j]; maxValue[i][j] = std::max(profit1, profit2); - } else + } else { // as weight of current item is greater than allowed weight, so // maxProfit will be profit obtained by excluding current item. maxValue[i][j] = maxValue[i - 1][j]; + } } } diff --git a/dynamic_programming/coin_change_topdown.cpp b/dynamic_programming/coin_change_topdown.cpp index e8112b089..14f69507d 100644 --- a/dynamic_programming/coin_change_topdown.cpp +++ b/dynamic_programming/coin_change_topdown.cpp @@ -1,7 +1,8 @@ /** * @file - * @brief [Minimum coins](https://leetcode.com/problems/coin-change/) change problem is a problem used to find the minimum number of - * coins required to completely reach a target amount. + * @brief [Minimum coins](https://leetcode.com/problems/coin-change/) change + * problem is a problem used to find the minimum number of coins required to + * completely reach a target amount. * * @details * This problem can be solved using 2 methods: @@ -17,10 +18,10 @@ * @author [Divyansh Kushwaha](https://github.com/webdesignbydivyansh) */ -#include // for io operations -#include // for std::vector -#include // for assert -#include // for INT_MAX +#include // for assert +#include // for INT_MAX +#include // for io operations +#include // for std::vector /** * @namespace dynamic_programming @@ -29,36 +30,39 @@ namespace dynamic_programming { /** * @namespace mincoins_topdown - * @brief Functions for [minimum coin exchange](https://leetcode.com/problems/coin-change/) problem + * @brief Functions for [minimum coin + * exchange](https://leetcode.com/problems/coin-change/) problem */ namespace mincoins_topdown { - /** - * @brief This implementation is for finding minimum number of coins . - * @param T template-type to use any kind of value - * @param n amount to be reached - * @param coins vector of coins - * @param t deontes the number of coins - * @param dp initilised to 0 - * @returns minimum number of coins - */ - template - int64_t mincoins(const T &n, const std::vector &coins, const int16_t &t, std::vector dp){ - if(n==0){ - return 0; - } - if(dp[n]!=0){ - return dp[n]; - } - int ans=INT_MAX; //variable to store min coins - for(int i=0;i=0){ //if after subtracting the current denomination is it greater than 0 or not - int sub=mincoins(n-coins[i],coins,t,dp); - ans=std::min(ans,sub+1); - } - } - dp[n]=ans; - return dp[n]; //returns minimum number of coins +/** + * @brief This implementation is for finding minimum number of coins . + * @param T template-type to use any kind of value + * @param n amount to be reached + * @param coins vector of coins + * @param t deontes the number of coins + * @param dp initilised to 0 + * @returns minimum number of coins + */ +template +int64_t mincoins(const T &n, const std::vector &coins, const int16_t &t, + std::vector dp) { + if (n == 0) { + return 0; } + if (dp[n] != 0) { + return dp[n]; + } + int ans = INT_MAX; // variable to store min coins + for (int i = 0; i < t; i++) { + if (n - coins[i] >= 0) { // if after subtracting the current + // denomination is it greater than 0 or not + int sub = mincoins(n - coins[i], coins, t, dp); + ans = std::min(ans, sub + 1); + } + } + dp[n] = ans; + return dp[n]; // returns minimum number of coins +} } // namespace mincoins_topdown } // namespace dynamic_programming @@ -70,12 +74,13 @@ namespace mincoins_topdown { static void test() { // example 1: number of coins=3 and minimum coins required=3(7,7,1) const int64_t n1 = 15; - const int8_t t1=3, a1=0; + const int8_t t1 = 3, a1 = 0; std::cout << "\nTest 1..."; - std::vector arr1 {1,7,10}; - std::vector dp1 (n1+1); - fill(dp1.begin(),dp1.end(),a1); - assert(dynamic_programming::mincoins_topdown::mincoins(n1, arr1, t1, dp1)==3); + std::vector arr1{1, 7, 10}; + std::vector dp1(n1 + 1); + fill(dp1.begin(), dp1.end(), a1); + assert(dynamic_programming::mincoins_topdown::mincoins(n1, arr1, t1, dp1) == + 3); std::cout << "Passed\n"; } @@ -84,6 +89,6 @@ static void test() { * @returns 0 on exit */ int main() { - test(); // execute the test + test(); // execute the test return 0; } diff --git a/dynamic_programming/palindrome_partitioning.cpp b/dynamic_programming/palindrome_partitioning.cpp index b5ab4ed6c..9b69a125e 100644 --- a/dynamic_programming/palindrome_partitioning.cpp +++ b/dynamic_programming/palindrome_partitioning.cpp @@ -1,26 +1,26 @@ /** * @file - * @brief Implements [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) algorithm, giving you the minimum number of partitions you need to make + * @brief Implements [Palindrome + * Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) + * algorithm, giving you the minimum number of partitions you need to make * * @details - * palindrome partitioning uses dynamic programming and goes to all the possible partitions to find the minimum - * you are given a string and you need to give minimum number of partitions needed to divide it into a number of palindromes - * [Palindrome Partitioning] (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/) - * overall time complexity O(n^2) - * For example: example 1:- - * String : "nitik" - * Output : 2 => "n | iti | k" - * For example: example 2:- - * String : "ababbbabbababa" - * Output : 3 => "aba | b | bbabb | ababa" + * palindrome partitioning uses dynamic programming and goes to all the possible + * partitions to find the minimum you are given a string and you need to give + * minimum number of partitions needed to divide it into a number of palindromes + * [Palindrome Partitioning] + * (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/) overall time + * complexity O(n^2) For example: example 1:- String : "nitik" Output : 2 => "n + * | iti | k" For example: example 2:- String : "ababbbabbababa" Output : 3 => + * "aba | b | bbabb | ababa" * @author [Sujay Kaushik] (https://github.com/sujaykaushik008) */ -#include // for io operations -#include // for std::vector #include // for std::min #include // for std::assert #include // for INT_MAX +#include // for io operations +#include // for std::vector /** * @namespace dynamic_programming @@ -28,67 +28,73 @@ */ namespace dynamic_programming { - /** - * @namespace palindrome_partitioning - * @brief Functions for [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) algorithm - */ - namespace palindrome_partitioning { +/** + * @namespace palindrome_partitioning + * @brief Functions for [Palindrome + * Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) + * algorithm + */ +namespace palindrome_partitioning { - /** - * Function implementing palindrome partitioning algorithm using lookup table method. - * @param str input string - * @returns minimum number of partitions - */ - int pal_part(const std::string &str) { +/** + * Function implementing palindrome partitioning algorithm using lookup table + * method. + * @param str input string + * @returns minimum number of partitions + */ +int pal_part(const std::string &str) { + int n = str.size(); - int n = str.size(); + // creating lookup table for minimum number of cuts + std::vector > cuts(n, std::vector(n, 0)); - // creating lookup table for minimum number of cuts - std::vector > cuts(n, std::vector(n, 0)); + // creating lookup table for palindrome checking + std::vector > is_palindrome(n, + std::vector(n, false)); - // creating lookup table for palindrome checking - std::vector > is_palindrome(n, std::vector(n, false)); + // initialization + for (int i = 0; i < n; i++) { + is_palindrome[i][i] = true; + cuts[i][i] = 0; + } - // initialization - for (int i = 0; i < n; i++) { - is_palindrome[i][i] = true; - cuts[i][i] = 0; + for (int len = 2; len <= n; len++) { + for (int start_index = 0; start_index < n - len + 1; start_index++) { + int end_index = start_index + len - 1; + + if (len == 2) { + is_palindrome[start_index][end_index] = + (str[start_index] == str[end_index]); + } else { + is_palindrome[start_index][end_index] = + (str[start_index] == str[end_index]) && + is_palindrome[start_index + 1][end_index - 1]; } - for (int len = 2; len <= n; len++) { - for (int start_index = 0; start_index < n - len + 1; start_index++) { - - int end_index = start_index + len - 1; - - if (len == 2) { - is_palindrome[start_index][end_index] = (str[start_index] == str[end_index]); - } else { - is_palindrome[start_index][end_index] = - (str[start_index] == str[end_index]) && is_palindrome[start_index + 1][end_index - 1]; - } - - if (is_palindrome[start_index][end_index]) { - cuts[start_index][end_index] = 0; - } else { - cuts[start_index][end_index] = INT_MAX; - for (int partition = start_index; partition <= end_index - 1; partition++) { - cuts[start_index][end_index] = std::min(cuts[start_index][end_index], - cuts[start_index][partition] + - cuts[partition + 1][end_index] + 1); - } - } + if (is_palindrome[start_index][end_index]) { + cuts[start_index][end_index] = 0; + } else { + cuts[start_index][end_index] = INT_MAX; + for (int partition = start_index; partition <= end_index - 1; + partition++) { + cuts[start_index][end_index] = + std::min(cuts[start_index][end_index], + cuts[start_index][partition] + + cuts[partition + 1][end_index] + 1); } } - - return cuts[0][n - 1]; } - } // namespace palindrome_partitioning + } + + return cuts[0][n - 1]; +} +} // namespace palindrome_partitioning } // namespace dynamic_programming /** * @brief Test Function * @return void -*/ + */ static void test() { // custom input vector std::vector custom_input{"nitik", "ababbbabbababa", "abdc"}; @@ -97,7 +103,9 @@ static void test() { std::vector calculated_output(3); for (int i = 0; i < 3; i++) { - calculated_output[i] = dynamic_programming::palindrome_partitioning::pal_part(custom_input[i]); + calculated_output[i] = + dynamic_programming::palindrome_partitioning::pal_part( + custom_input[i]); } // expected output vector diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index a0c872681..4bc58f342 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -48,136 +48,138 @@ #include #include #include -#include -#include -#include #include +#include +#include #include +#include /** * \namespace graph * \brief Graph algorithms */ -namespace graph{ - /* Class Graph definition */ - template - class Graph{ +namespace graph { +/* Class Graph definition */ +template +class Graph { /** - * adjacency_list maps every vertex to the list of its neighbours in the order - * in which they are added. - */ - std::map > adjacency_list; - public: - Graph(){}; - void add_edge(T u,T v, bool bidir=true){ + * adjacency_list maps every vertex to the list of its neighbours in the + * order in which they are added. + */ + std::map > adjacency_list; + + public: + Graph() = default; + ; + void add_edge(T u, T v, bool bidir = true) { /** - * add_edge(u,v,bidir) is used to add an edge between node u and node v - * by default , bidir is made true , i.e graph is bidirectional . - * It means if edge(u,v) is added then u-->v and v-->u both edges exist. - * - * to make the graph unidirectional pass the third parameter of add_edge as - * false which will - */ - adjacency_list[u].push_back(v); // u-->v edge added - if(bidir==true){ - // if graph is bidirectional - adjacency_list[v].push_back(u); // v-->u edge added + * add_edge(u,v,bidir) is used to add an edge between node u and + * node v by default , bidir is made true , i.e graph is + * bidirectional . It means if edge(u,v) is added then u-->v and + * v-->u both edges exist. + * + * to make the graph unidirectional pass the third parameter of + * add_edge as false which will + */ + adjacency_list[u].push_back(v); // u-->v edge added + if (bidir == true) { + // if graph is bidirectional + adjacency_list[v].push_back(u); // v-->u edge added } - } - - - /** - * this function performs the breadth first search on graph and return a - * mapping which maps the nodes to a boolean value representing whether the - * node was traversed or not. - */ - std::map breadth_first_search(T src){ - /// mapping to keep track of all visited nodes - std::map visited; + } + + /** + * this function performs the breadth first search on graph and return a + * mapping which maps the nodes to a boolean value representing whether the + * node was traversed or not. + */ + std::map breadth_first_search(T src) { + /// mapping to keep track of all visited nodes + std::map visited; /// initialise every possible vertex to map to false /// initially none of the vertices are unvisited - for(auto const &adjlist: adjacency_list){ - visited[adjlist.first]=false; - for(auto const &node:adjacency_list[adjlist.first]){ - visited[node]=false; - } + for (auto const &adjlist : adjacency_list) { + visited[adjlist.first] = false; + for (auto const &node : adjacency_list[adjlist.first]) { + visited[node] = false; + } } - + /// queue to store the nodes which are yet to be traversed std::queue tracker; - - /// push the source vertex to queue to begin traversing + + /// push the source vertex to queue to begin traversing tracker.push(src); - ///mark the source vertex as visited - visited[src]=true; - while(!tracker.empty()){ - /// traverse the graph till no connected vertex are left - /// extract a node from queue for further traversal - T node = tracker.front(); - /// remove the node from the queue - tracker.pop(); - for(T const &neighbour : adjacency_list[node]){ - /// check every vertex connected to the node which are still unvisited - if(!visited[neighbour]){ - /// if the neighbour is unvisited , push it into the queue - tracker.push(neighbour); - /// mark the neighbour as visited - visited[neighbour]=true; + /// mark the source vertex as visited + visited[src] = true; + while (!tracker.empty()) { + /// traverse the graph till no connected vertex are left + /// extract a node from queue for further traversal + T node = tracker.front(); + /// remove the node from the queue + tracker.pop(); + for (T const &neighbour : adjacency_list[node]) { + /// check every vertex connected to the node which are still + /// unvisited + if (!visited[neighbour]) { + /// if the neighbour is unvisited , push it into the queue + tracker.push(neighbour); + /// mark the neighbour as visited + visited[neighbour] = true; + } } - } } return visited; - } - }; - /* Class definition ends */ -} - + } +}; +/* Class definition ends */ +} // namespace graph /** Test function */ static void tests() { /// Test 1 Begin graph::Graph g; - std::map correct_result; - g.add_edge(0,1); - g.add_edge(1,2); - g.add_edge(2,3); - correct_result[0]=true; - correct_result[1]=true; - correct_result[2]=true; - correct_result[3]=true; + std::map correct_result; + g.add_edge(0, 1); + g.add_edge(1, 2); + g.add_edge(2, 3); + correct_result[0] = true; + correct_result[1] = true; + correct_result[2] = true; + correct_result[3] = true; - std::map returned_result = g.breadth_first_search(2); + std::map returned_result = g.breadth_first_search(2); - assert(returned_result==correct_result); + assert(returned_result == correct_result); std::cout << "Test 1 Passed..." << std::endl; /// Test 2 Begin returned_result = g.breadth_first_search(0); - - assert(returned_result==correct_result); + + assert(returned_result == correct_result); std::cout << "Test 2 Passed..." << std::endl; /// Test 3 Begins graph::Graph g2; - g2.add_edge("Gorakhpur","Lucknow",false); - g2.add_edge("Gorakhpur","Kanpur",false); - g2.add_edge("Lucknow","Agra",false); - g2.add_edge("Kanpur","Agra",false); - g2.add_edge("Lucknow","Prayagraj",false); - g2.add_edge("Agra","Noida",false); + g2.add_edge("Gorakhpur", "Lucknow", false); + g2.add_edge("Gorakhpur", "Kanpur", false); + g2.add_edge("Lucknow", "Agra", false); + g2.add_edge("Kanpur", "Agra", false); + g2.add_edge("Lucknow", "Prayagraj", false); + g2.add_edge("Agra", "Noida", false); - std::map correct_res; - std::map returned_res=g2.breadth_first_search("Kanpur"); - correct_res["Gorakhpur"]=false; - correct_res["Lucknow"]=false; - correct_res["Kanpur"]=true; - correct_res["Agra"]=true; - correct_res["Prayagraj"]=false; - correct_res["Noida"]=true; - assert(correct_res==returned_res); + std::map correct_res; + std::map returned_res = + g2.breadth_first_search("Kanpur"); + correct_res["Gorakhpur"] = false; + correct_res["Lucknow"] = false; + correct_res["Kanpur"] = true; + correct_res["Agra"] = true; + correct_res["Prayagraj"] = false; + correct_res["Noida"] = true; + assert(correct_res == returned_res); std::cout << "Test 3 Passed..." << std::endl; - } /** Main function */ @@ -194,7 +196,7 @@ int main() { while (edges--) { int u = 0, v = 0; std::cin >> u >> v; - g.add_edge(u,v); + g.add_edge(u, v); } g.breadth_first_search(0); diff --git a/greedy_algorithms/kruskals_minimum_spanning_tree.cpp b/greedy_algorithms/kruskals_minimum_spanning_tree.cpp index 42c044241..ed7f82b72 100644 --- a/greedy_algorithms/kruskals_minimum_spanning_tree.cpp +++ b/greedy_algorithms/kruskals_minimum_spanning_tree.cpp @@ -1,30 +1,31 @@ -#include #include +#include -void findMinimumEdge(int INFINITY, std::array< std::array< int ,6 >,6 > graph) { +void findMinimumEdge(int INFINITY, std::array, 6> graph) { for (int i = 0; i < graph.size(); i++) { int min = INFINITY; int minIndex = 0; - for (int j = 0; j < graph.size(); j++) { + for (int j = 0; j < graph.size(); j++) { if (graph[i][j] != 0 && graph[i][j] < min) { min = graph[i][j]; minIndex = j; } } - std::cout << i << " - " << minIndex << "\t" << graph[i][minIndex] << std::endl; + std::cout << i << " - " << minIndex << "\t" << graph[i][minIndex] + << std::endl; } } int main() { constexpr int INFINITY = 99999; - std::array< std::array< int ,6 >,6 >graph - {0, 4, 1, 4, INFINITY, INFINITY, - 4, 0, 3, 8, 3, INFINITY, - 1, 3, 0, INFINITY, 1, INFINITY, - 4, 8, INFINITY, 0, 5, 7, - INFINITY, 3, 1, 5, 0, INFINITY, - INFINITY, INFINITY, INFINITY, 7, INFINITY, 0}; + std::array, 6> graph{ + 0, 4, 1, 4, INFINITY, INFINITY, + 4, 0, 3, 8, 3, INFINITY, + 1, 3, 0, INFINITY, 1, INFINITY, + 4, 8, INFINITY, 0, 5, 7, + INFINITY, 3, 1, 5, 0, INFINITY, + INFINITY, INFINITY, INFINITY, 7, INFINITY, 0}; - findMinimumEdge(INFINITY,graph); + findMinimumEdge(INFINITY, graph); return 0; } diff --git a/linear_algebra/gram_schmidt.cpp b/linear_algebra/gram_schmidt.cpp index 09ebc8d7c..9d25b2033 100644 --- a/linear_algebra/gram_schmidt.cpp +++ b/linear_algebra/gram_schmidt.cpp @@ -1,20 +1,22 @@ -/** - * @file - * @brief [Gram Schmidt Orthogonalisation Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process) +/** + * @file + * @brief [Gram Schmidt Orthogonalisation + * Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process) * * @details * Takes the input of Linearly Independent Vectors, * returns vectors orthogonal to each other. - * + * * ### Algorithm - * Take the first vector of given LI vectors as first vector of Orthogonal vectors. - * Take projection of second input vector on the first vector of Orthogonal vector - * and subtract it from the 2nd LI vector. - * Take projection of third vector on the second vector of Othogonal vectors and subtract it from the 3rd LI vector. - * Keep repeating the above process until all the vectors in the given input array are exhausted. + * Take the first vector of given LI vectors as first vector of Orthogonal + * vectors. Take projection of second input vector on the first vector of + * Orthogonal vector and subtract it from the 2nd LI vector. Take projection of + * third vector on the second vector of Othogonal vectors and subtract it from + * the 3rd LI vector. Keep repeating the above process until all the vectors in + * the given input array are exhausted. * * For Example: - * In R2, + * In R2, * Input LI Vectors={(3,1),(2,2)} * then Orthogonal Vectors= {(3, 1),(-0.4, 1.2)} * @@ -26,10 +28,12 @@ * @author [Akanksha Gupta](https://github.com/Akanksha-Gupta920) */ -#include /// for io operations -#include /// for assert -#include /// for fabs -#include /// for std::array +#include /// for std::array +#include /// for assert +#include /// for fabs +#include /// for io operations + +#include "math.h" /** * @namespace linear_algebra @@ -38,29 +42,33 @@ namespace linear_algebra { /** * @namespace gram_schmidt - * @brief Functions for [Gram Schmidt Orthogonalisation Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process) + * @brief Functions for [Gram Schmidt Orthogonalisation + * Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process) */ namespace gram_schmidt { /** * Dot product function. - * Takes 2 vectors along with their dimension as input and returns the dot product. + * Takes 2 vectors along with their dimension as input and returns the dot + * product. * @param x vector 1 * @param y vector 2 * @param c dimension of the vectors - * + * * @returns sum */ -double dot_product(const std::array& x, const std::array& y, const int& c) { - double sum = 0; - for (int i = 0; i < c; ++i) { - sum += x[i] * y[i]; - } - return sum; +double dot_product(const std::array& x, + const std::array& y, const int& c) { + double sum = 0; + for (int i = 0; i < c; ++i) { + sum += x[i] * y[i]; + } + return sum; } /** * Projection Function - * Takes input of 2 vectors along with their dimension and evaluates their projection in temp + * Takes input of 2 vectors along with their dimension and evaluates their + * projection in temp * * @param x Vector 1 * @param y Vector 2 @@ -68,12 +76,17 @@ double dot_product(const std::array& x, const std::array * * @returns factor */ -double projection(const std::array& x,const std::array& y, - const int& c) { - double dot = dot_product(x, y, c); ///The dot product of two vectors is taken - double anorm = dot_product(y, y, c); ///The norm of the second vector is taken. - double factor = dot / anorm; ///multiply that factor with every element in a 3rd vector, whose initial values are same as the 2nd vector. - return factor; +double projection(const std::array& x, + const std::array& y, const int& c) { + double dot = + dot_product(x, y, c); /// The dot product of two vectors is taken + double anorm = + dot_product(y, y, c); /// The norm of the second vector is taken. + double factor = + dot / + anorm; /// multiply that factor with every element in a 3rd vector, + /// whose initial values are same as the 2nd vector. + return factor; } /** @@ -85,14 +98,15 @@ double projection(const std::array& x,const std::array& * * @returns void */ -void display(const int& r,const int& c,const std::array, 20>& B) { - for (int i = 0; i < r; ++i) { - std::cout << "Vector " << i + 1 << ": "; - for (int j = 0; j < c; ++j) { - std::cout << B[i][j] << " "; +void display(const int& r, const int& c, + const std::array, 20>& B) { + for (int i = 0; i < r; ++i) { + std::cout << "Vector " << i + 1 << ": "; + for (int j = 0; j < c; ++j) { + std::cout << B[i][j] << " "; + } + std::cout << '\n'; } - std::cout << '\n'; - } } /** @@ -101,50 +115,62 @@ void display(const int& r,const int& c,const std::array, * @param c dimension of vectors * @param A stores input of given LI vectors * @param B stores orthogonalised vectors - * + * * @returns void */ -void gram_schmidt(int r,const int& c,const std::array, 20>& A, +void gram_schmidt(int r, const int& c, + const std::array, 20>& A, std::array, 20> B) { - if (c < r) { /// we check whether appropriate dimensions are given or not. - std::cout - << "Dimension of vector is less than number of vector, hence \n first " - << c << " vectors are orthogonalised\n"; - r = c; - } - - int k = 1; - - while (k <= r) { - if (k == 1) { - for (int j = 0; j < c; j++) B[0][j] = A[0][j]; ///First vector is copied as it is. + if (c < r) { /// we check whether appropriate dimensions are given or not. + std::cout << "Dimension of vector is less than number of vector, hence " + "\n first " + << c << " vectors are orthogonalised\n"; + r = c; } - else { - std::array all_projection{}; ///array to store projections - for (int i = 0; i < c; ++i) { - all_projection[i] = 0; ///First initialised to zero - } + int k = 1; - int l = 1; - while (l < k) { - std::array temp{}; ///to store previous projected array - double factor; ///to store the factor by which the previous array will change - factor = projection(A[k - 1], B[l - 1], c); - for(int i = 0; i < c; ++i) - temp[i] = B[l - 1][i] * factor; ///projected array created - for (int j = 0; j < c; ++j) { - all_projection[j] = all_projection[j] + temp[j]; ///we take the projection with all the previous vector and add them. + while (k <= r) { + if (k == 1) { + for (int j = 0; j < c; j++) + B[0][j] = A[0][j]; /// First vector is copied as it is. } - l++; - } - for (int i = 0; i < c; ++i) { - B[k - 1][i] = A[k - 1][i] - all_projection[i]; ///subtract total projection vector from the input vector - } + + else { + std::array + all_projection{}; /// array to store projections + for (int i = 0; i < c; ++i) { + all_projection[i] = 0; /// First initialised to zero + } + + int l = 1; + while (l < k) { + std::array + temp{}; /// to store previous projected array + double factor = NAN; /// to store the factor by which the + /// previous array will change + factor = projection(A[k - 1], B[l - 1], c); + for (int i = 0; i < c; ++i) { + temp[i] = B[l - 1][i] * factor; /// projected array created + } + for (int j = 0; j < c; ++j) { + all_projection[j] = + all_projection[j] + + temp[j]; /// we take the projection with all the + /// previous vector and add them. + } + l++; + } + for (int i = 0; i < c; ++i) { + B[k - 1][i] = + A[k - 1][i] - + all_projection[i]; /// subtract total projection vector + /// from the input vector + } + } + k++; } - k++; - } - display(r, c, B); //for displaying orthogoanlised vectors + display(r, c, B); // for displaying orthogoanlised vectors } } // namespace gram_schmidt } // namespace linear_algebra @@ -153,57 +179,66 @@ void gram_schmidt(int r,const int& c,const std::array, 20 * @returns void */ static void test() { - std::array, 20> a1 = { - {{1, 0, 1, 0}, {1, 1, 1, 1}, {0, 1, 2, 1}}}; - std::array, 20> b1 = {{0}}; - double dot1 = 0; - linear_algebra::gram_schmidt::gram_schmidt(3, 4, a1, b1); - int flag = 1; - for (int i = 0; i < 2; ++i) - for (int j = i + 1; j < 3; ++j) { - dot1 = fabs(linear_algebra::gram_schmidt::dot_product(b1[i], b1[j], 4)); - if (dot1 > 0.1) { - flag = 0; - break; - } + std::array, 20> a1 = { + {{1, 0, 1, 0}, {1, 1, 1, 1}, {0, 1, 2, 1}}}; + std::array, 20> b1 = {{0}}; + double dot1 = 0; + linear_algebra::gram_schmidt::gram_schmidt(3, 4, a1, b1); + int flag = 1; + for (int i = 0; i < 2; ++i) { + for (int j = i + 1; j < 3; ++j) { + dot1 = fabs( + linear_algebra::gram_schmidt::dot_product(b1[i], b1[j], 4)); + if (dot1 > 0.1) { + flag = 0; + break; + } + } } - if (flag == 0) std::cout << "Vectors are linearly dependent\n"; - assert(flag == 1); - std::cout << "Passed Test Case 1\n "; + if (flag == 0) + std::cout << "Vectors are linearly dependent\n"; + assert(flag == 1); + std::cout << "Passed Test Case 1\n "; - std::array, 20> a2 = {{{3, 1}, {2, 2}}}; - std::array, 20> b2 = {{0}}; - double dot2 = 0; - linear_algebra::gram_schmidt::gram_schmidt(2, 2, a2, b2); - flag = 1; - for (int i = 0; i < 1; ++i) - for (int j = i + 1; j < 2; ++j) { - dot2 = fabs(linear_algebra::gram_schmidt::dot_product(b2[i], b2[j], 2)); - if (dot2 > 0.1) { - flag = 0; - break; - } + std::array, 20> a2 = {{{3, 1}, {2, 2}}}; + std::array, 20> b2 = {{0}}; + double dot2 = 0; + linear_algebra::gram_schmidt::gram_schmidt(2, 2, a2, b2); + flag = 1; + for (int i = 0; i < 1; ++i) { + for (int j = i + 1; j < 2; ++j) { + dot2 = fabs( + linear_algebra::gram_schmidt::dot_product(b2[i], b2[j], 2)); + if (dot2 > 0.1) { + flag = 0; + break; + } + } } - if (flag == 0) std::cout << "Vectors are linearly dependent\n"; - assert(flag == 1); - std::cout << "Passed Test Case 2\n"; + if (flag == 0) + std::cout << "Vectors are linearly dependent\n"; + assert(flag == 1); + std::cout << "Passed Test Case 2\n"; - std::array, 20> a3 = {{{1, 2, 2}, {-4, 3, 2}}}; - std::array, 20> b3 = {{0}}; - double dot3 = 0; - linear_algebra::gram_schmidt::gram_schmidt(2, 3, a3, b3); - flag = 1; - for (int i = 0; i < 1; ++i) - for (int j = i + 1; j < 2; ++j) { - dot3 = fabs(linear_algebra::gram_schmidt::dot_product(b3[i], b3[j], 3)); - if (dot3 > 0.1) { - flag = 0; - break; - } + std::array, 20> a3 = {{{1, 2, 2}, {-4, 3, 2}}}; + std::array, 20> b3 = {{0}}; + double dot3 = 0; + linear_algebra::gram_schmidt::gram_schmidt(2, 3, a3, b3); + flag = 1; + for (int i = 0; i < 1; ++i) { + for (int j = i + 1; j < 2; ++j) { + dot3 = fabs( + linear_algebra::gram_schmidt::dot_product(b3[i], b3[j], 3)); + if (dot3 > 0.1) { + flag = 0; + break; + } + } } - if (flag == 0) std::cout << "Vectors are linearly dependent\n" ; - assert(flag == 1); - std::cout << "Passed Test Case 3\n"; + if (flag == 0) + std::cout << "Vectors are linearly dependent\n"; + assert(flag == 1); + std::cout << "Passed Test Case 3\n"; } /** @@ -211,41 +246,45 @@ static void test() { * @return 0 on exit */ int main() { - int r=0, c=0; - test(); // perform self tests - std::cout << "Enter the dimension of your vectors\n"; - std::cin >> c; - std::cout << "Enter the number of vectors you will enter\n"; - std::cin >> r; + int r = 0, c = 0; + test(); // perform self tests + std::cout << "Enter the dimension of your vectors\n"; + std::cin >> c; + std::cout << "Enter the number of vectors you will enter\n"; + std::cin >> r; - std::array, 20> - A{}; ///a 2-D array for storing all vectors - std::array, 20> B = { - {0}}; /// a 2-D array for storing orthogonalised vectors - /// storing vectors in array A - for (int i = 0; i < r; ++i) { - std::cout << "Enter vector " << i + 1 <<'\n'; ///Input of vectors is taken - for (int j = 0; j < c; ++j) { - std::cout << "Value " << j + 1 << "th of vector: "; - std::cin >> A[i][j]; + std::array, 20> + A{}; /// a 2-D array for storing all vectors + std::array, 20> B = { + {0}}; /// a 2-D array for storing orthogonalised vectors + /// storing vectors in array A + for (int i = 0; i < r; ++i) { + std::cout << "Enter vector " << i + 1 + << '\n'; /// Input of vectors is taken + for (int j = 0; j < c; ++j) { + std::cout << "Value " << j + 1 << "th of vector: "; + std::cin >> A[i][j]; + } + std::cout << '\n'; } - std::cout <<'\n'; - } - linear_algebra::gram_schmidt::gram_schmidt(r, c, A, B); + linear_algebra::gram_schmidt::gram_schmidt(r, c, A, B); - double dot = 0; - int flag = 1; ///To check whether vectors are orthogonal or not - for (int i = 0; i < r - 1; ++i) { - for (int j = i + 1; j < r; ++j) { - dot = fabs(linear_algebra::gram_schmidt::dot_product(B[i], B[j], c)); - if (dot > 0.1) /// take make the process numerically stable, upper bound for the dot product take 0.1 - { - flag = 0; - break; - } + double dot = 0; + int flag = 1; /// To check whether vectors are orthogonal or not + for (int i = 0; i < r - 1; ++i) { + for (int j = i + 1; j < r; ++j) { + dot = + fabs(linear_algebra::gram_schmidt::dot_product(B[i], B[j], c)); + if (dot > 0.1) /// take make the process numerically stable, upper + /// bound for the dot product take 0.1 + { + flag = 0; + break; + } + } } - } - if (flag == 0) std::cout << "Vectors are linearly dependent\n"; - return 0; + if (flag == 0) + std::cout << "Vectors are linearly dependent\n"; + return 0; } diff --git a/math/fibonacci_sum.cpp b/math/fibonacci_sum.cpp index abe85023b..510757888 100644 --- a/math/fibonacci_sum.cpp +++ b/math/fibonacci_sum.cpp @@ -21,75 +21,76 @@ * @brief Mathematical algorithms */ namespace math { - /** - * @namespace fibonacci_sum - * @brief Functions for the sum of the Fibonacci Sequence: \f$\mathrm{F}(n) + - * \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$ - */ - namespace fibonacci_sum { - using matrix = std::vector >; +/** + * @namespace fibonacci_sum + * @brief Functions for the sum of the Fibonacci Sequence: \f$\mathrm{F}(n) + + * \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$ + */ +namespace fibonacci_sum { +using matrix = std::vector >; - /** - * Function to multiply two matrices - * @param T matrix 1 - * @param A martix 2 - * @returns resultant matrix - */ - math::fibonacci_sum::matrix multiply(const math::fibonacci_sum::matrix &T, const math::fibonacci_sum::matrix &A) { - math::fibonacci_sum::matrix result(2, std::vector(2, 0)); +/** + * Function to multiply two matrices + * @param T matrix 1 + * @param A martix 2 + * @returns resultant matrix + */ +math::fibonacci_sum::matrix multiply(const math::fibonacci_sum::matrix &T, + const math::fibonacci_sum::matrix &A) { + math::fibonacci_sum::matrix result(2, std::vector(2, 0)); - // multiplying matrices - result[0][0] = T[0][0]*A[0][0] + T[0][1]*A[1][0]; - result[0][1] = T[0][0]*A[0][1] + T[0][1]*A[1][1]; - result[1][0] = T[1][0]*A[0][0] + T[1][1]*A[1][0]; - result[1][1] = T[1][0]*A[0][1] + T[1][1]*A[1][1]; + // multiplying matrices + result[0][0] = T[0][0] * A[0][0] + T[0][1] * A[1][0]; + result[0][1] = T[0][0] * A[0][1] + T[0][1] * A[1][1]; + result[1][0] = T[1][0] * A[0][0] + T[1][1] * A[1][0]; + result[1][1] = T[1][0] * A[0][1] + T[1][1] * A[1][1]; - return result; - } + return result; +} - /** - * Function to compute A^n where A is a matrix. - * @param T matrix - * @param ex power - * @returns resultant matrix - */ - math::fibonacci_sum::matrix power(math::fibonacci_sum::matrix T, uint64_t ex) { - math::fibonacci_sum::matrix A{{1, 1}, {1, 0}}; - if (ex == 0 || ex == 1) { - return T; - } +/** + * Function to compute A^n where A is a matrix. + * @param T matrix + * @param ex power + * @returns resultant matrix + */ +math::fibonacci_sum::matrix power(math::fibonacci_sum::matrix T, uint64_t ex) { + math::fibonacci_sum::matrix A{{1, 1}, {1, 0}}; + if (ex == 0 || ex == 1) { + return T; + } - T = power(T, ex / 2); - T = multiply(T, T); - if (ex & 1) { - T = multiply(T, A); - } - return T; - } + T = power(T, ex / 2); + T = multiply(T, T); + if (ex & 1) { + T = multiply(T, A); + } + return T; +} - /** - * Function to compute sum of fibonacci sequence from 0 to n. - * @param n number - * @returns uint64_t ans, the sum of sequence - */ - uint64_t result(uint64_t n) { - math::fibonacci_sum::matrix T{{1, 1}, {1, 0}}; - T = power(T, n); - uint64_t ans = T[0][1]; - ans = (ans - 1); - return ans; - } +/** + * Function to compute sum of fibonacci sequence from 0 to n. + * @param n number + * @returns uint64_t ans, the sum of sequence + */ +uint64_t result(uint64_t n) { + math::fibonacci_sum::matrix T{{1, 1}, {1, 0}}; + T = power(T, n); + uint64_t ans = T[0][1]; + ans = (ans - 1); + return ans; +} - /** - * Function to compute sum of fibonacci sequence from n to m. - * @param n start of sequence - * @param m end of sequence - * @returns uint64_t the sum of sequence - */ - uint64_t fiboSum(uint64_t n, uint64_t m) { - return (result(m + 2) - result(n + 1)); - } - } // namespace fibonacci_sum +/** + * Function to compute sum of fibonacci sequence from n to m. + * @param n start of sequence + * @param m end of sequence + * @returns uint64_t the sum of sequence + */ +uint64_t fiboSum(uint64_t n, uint64_t m) { + return (result(m + 2) - result(n + 1)); +} +} // namespace fibonacci_sum } // namespace math /** diff --git a/math/lcm_sum.cpp b/math/lcm_sum.cpp index 34b46020f..97acbd336 100644 --- a/math/lcm_sum.cpp +++ b/math/lcm_sum.cpp @@ -1,67 +1,67 @@ /** * @file - * @brief An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ - * @details An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ where \f$\mathrm{LCM}(i,n)\f$ - * denotes the Least Common Multiple of the integers i and n. For n greater than or equal to 1. - * The value of the sum is calculated by formula: - * \f[ - * \sum\mathrm{LCM}(i, n) = \frac{1}{2} \left[\left(\sum (d * \mathrm{ETF}(d)) + 1\right) * n\right] - * \f] - * where \mathrm{ETF}(i) represents Euler totient function of i. + * @brief An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + + * \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ + * @details An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + + * \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ where + * \f$\mathrm{LCM}(i,n)\f$ denotes the Least Common Multiple of the integers i + * and n. For n greater than or equal to 1. The value of the sum is calculated + * by formula: \f[ \sum\mathrm{LCM}(i, n) = \frac{1}{2} \left[\left(\sum (d * + * \mathrm{ETF}(d)) + 1\right) * n\right] \f] where \mathrm{ETF}(i) represents + * Euler totient function of i. * @author [Chesta Mittal](https://github.com/chestamittal) */ -#include /// for std::cin and std::cout -#include /// for assert -#include /// for std::vector +#include /// for assert +#include /// for std::cin and std::cout +#include /// for std::vector /** * @namespace math * @brief Mathematical algorithms */ namespace math { - /** - * Function to compute sum of euler totients in sumOfEulerTotient vector - * @param num input number - * @returns int Sum of LCMs, i.e. ∑LCM(i, num) from i = 1 to num - */ - uint64_t lcmSum(const uint16_t& num) { - - uint64_t i=0, j=0; - std::vector eulerTotient(num+1); - std::vector sumOfEulerTotient(num+1); - - // storing initial values in eulerTotient vector - for(i=1; i<=num; i++) { - eulerTotient[i] = i; - } +/** + * Function to compute sum of euler totients in sumOfEulerTotient vector + * @param num input number + * @returns int Sum of LCMs, i.e. ∑LCM(i, num) from i = 1 to num + */ +uint64_t lcmSum(const uint16_t& num) { + uint64_t i = 0, j = 0; + std::vector eulerTotient(num + 1); + std::vector sumOfEulerTotient(num + 1); - // applying totient sieve - for(i=2; i<=num; i++) { - if(eulerTotient[i] == i) { - for(j=i; j<=num; j+=i) { - eulerTotient[j] = eulerTotient[j]/i; - eulerTotient[j] = eulerTotient[j]*(i-1); - } - } - } - - // computing sum of euler totients - for(i=1; i<=num; i++) { - for(j=i; j <=num; j+=i) { - sumOfEulerTotient[j] += eulerTotient[i]*i; - } - } - - return ((sumOfEulerTotient[num] + 1 ) * num) / 2; + // storing initial values in eulerTotient vector + for (i = 1; i <= num; i++) { + eulerTotient[i] = i; } + + // applying totient sieve + for (i = 2; i <= num; i++) { + if (eulerTotient[i] == i) { + for (j = i; j <= num; j += i) { + eulerTotient[j] = eulerTotient[j] / i; + eulerTotient[j] = eulerTotient[j] * (i - 1); + } + } + } + + // computing sum of euler totients + for (i = 1; i <= num; i++) { + for (j = i; j <= num; j += i) { + sumOfEulerTotient[j] += eulerTotient[i] * i; + } + } + + return ((sumOfEulerTotient[num] + 1) * num) / 2; +} } // namespace math /** * Function for testing lcmSum function. * test cases and assert statement. * @returns `void` -*/ + */ static void test() { uint64_t n = 2; uint64_t test_1 = math::lcmSum(n); diff --git a/math/n_choose_r.cpp b/math/n_choose_r.cpp index fa3287abc..8bb3bbcdc 100644 --- a/math/n_choose_r.cpp +++ b/math/n_choose_r.cpp @@ -1,6 +1,7 @@ /** * @file - * @brief [Combinations](https://en.wikipedia.org/wiki/Combination) n choose r function implementation + * @brief [Combinations](https://en.wikipedia.org/wiki/Combination) n choose r + * function implementation * @details * A very basic and efficient method of calculating * choosing r from n different choices. @@ -9,8 +10,8 @@ * @author [Tajmeet Singh](https://github.com/tjgurwara99) */ -#include /// for io operations #include /// for assert +#include /// for io operations /** * @namespace math @@ -22,8 +23,9 @@ namespace math { * @details * We are calculating the ans with iterations * instead of calculating three different factorials. - * Also, we are using the fact that - * \f$ \frac{n!}{r! (n-r)!} = \frac{(n - r + 1) \times \cdots \times n}{1 \times \cdots \times r} \f$ + * Also, we are using the fact that + * \f$ \frac{n!}{r! (n-r)!} = \frac{(n - r + 1) \times \cdots \times n}{1 \times + * \cdots \times r} \f$ * @tparam T Only for integer types such as long, int_64 etc * @param n \f$ n \f$ in \f$ \binom{n}{r} \f$ * @param r \f$ r \f$ in \f$ \binom{n}{r} \f$ @@ -31,16 +33,17 @@ namespace math { */ template T n_choose_r(T n, T r) { - if(r > n / 2) - r = n - r; // Because of the fact that nCr(n, r) == nCr(n, n - r) + if (r > n / 2) { + r = n - r; // Because of the fact that nCr(n, r) == nCr(n, n - r) + } T ans = 1; - for(int i = 1; i <= r; i++) { + for (int i = 1; i <= r; i++) { ans *= n - r + i; ans /= i; } return ans; } -} // namespace math +} // namespace math /** * @brief Test implementations @@ -48,25 +51,24 @@ T n_choose_r(T n, T r) { */ static void test() { // First test on 5 choose 2 - uint8_t t = math::n_choose_r(5, 2); - assert(((void)"10 is the answer but function says otherwise.\n", - t == 10)); - std::cout << "First test passes." << std::endl; - // Second test on 5 choose 3 - t = math::n_choose_r(5, 3); - assert(((void)"10 is the answer but the function says otherwise.\n", - t == 10)); - std::cout << "Second test passes." << std::endl; - // Third test on 3 choose 2 - t = math::n_choose_r(3, 2); - assert(((void)"3 is the answer but the function says otherwise.\n", - t == 3)); - std::cout << "Third test passes." << std::endl; - // Fourth test on 10 choose 4 - t = math::n_choose_r(10, 4); - assert(((void)"210 is the answer but the function says otherwise.\n", - t == 210)); - std::cout << "Fourth test passes." << std::endl; + uint8_t t = math::n_choose_r(5, 2); + assert(((void)"10 is the answer but function says otherwise.\n", t == 10)); + std::cout << "First test passes." << std::endl; + // Second test on 5 choose 3 + t = math::n_choose_r(5, 3); + assert( + ((void)"10 is the answer but the function says otherwise.\n", t == 10)); + std::cout << "Second test passes." << std::endl; + // Third test on 3 choose 2 + t = math::n_choose_r(3, 2); + assert( + ((void)"3 is the answer but the function says otherwise.\n", t == 3)); + std::cout << "Third test passes." << std::endl; + // Fourth test on 10 choose 4 + t = math::n_choose_r(10, 4); + assert(((void)"210 is the answer but the function says otherwise.\n", + t == 210)); + std::cout << "Fourth test passes." << std::endl; } /** @@ -76,6 +78,6 @@ static void test() { * @returns 0 on exit */ int main(int argc, char *argv[]) { - test(); // executing tests + test(); // executing tests return 0; } diff --git a/math/ncr_modulo_p.cpp b/math/ncr_modulo_p.cpp new file mode 100644 index 000000000..03aecf67e --- /dev/null +++ b/math/ncr_modulo_p.cpp @@ -0,0 +1,150 @@ +/** + * @file + * @brief This program aims at calculating [nCr modulo + * p](https://cp-algorithms.com/combinatorics/binomial-coefficients.html). + * @details nCr is defined as n! / (r! * (n-r)!) where n! represents factorial + * of n. In many cases, the value of nCr is too large to fit in a 64 bit + * integer. Hence, in competitive programming, there are many problems or + * subproblems to compute nCr modulo p where p is a given number. + * @author [Kaustubh Damania](https://github.com/KaustubhDamania) + */ + +#include /// for assert +#include /// for io operations +#include /// for std::vector + +/** + * @namespace math + * @brief Mathematical algorithms + */ +namespace math { +/** + * @namespace ncr_modulo_p + * @brief Functions for [nCr modulo + * p](https://cp-algorithms.com/combinatorics/binomial-coefficients.html) + * implementation. + */ +namespace ncr_modulo_p { +/** + * @brief Class which contains all methods required for calculating nCr mod p + */ +class NCRModuloP { + private: + std::vector fac{}; /// stores precomputed factorial(i) % p value + uint64_t p = 0; /// the p from (nCr % p) + + public: + /** Constructor which precomputes the values of n! % mod from n=0 to size + * and stores them in vector 'fac' + * @params[in] the numbers 'size', 'mod' + */ + NCRModuloP(const uint64_t& size, const uint64_t& mod) { + p = mod; + fac = std::vector(size); + fac[0] = 1; + for (int i = 1; i <= size; i++) { + fac[i] = (fac[i - 1] * i) % p; + } + } + + /** Finds the value of x, y such that a*x + b*y = gcd(a,b) + * + * @params[in] the numbers 'a', 'b' and address of 'x' and 'y' from above + * equation + * @returns the gcd of a and b + */ + uint64_t gcdExtended(const uint64_t& a, const uint64_t& b, int64_t* x, + int64_t* y) { + if (a == 0) { + *x = 0, *y = 1; + return b; + } + + int64_t x1 = 0, y1 = 0; + uint64_t gcd = gcdExtended(b % a, a, &x1, &y1); + + *x = y1 - (b / a) * x1; + *y = x1; + return gcd; + } + + /** Find modular inverse of a with m i.e. a number x such that (a*x)%m = 1 + * + * @params[in] the numbers 'a' and 'm' from above equation + * @returns the modular inverse of a + */ + int64_t modInverse(const uint64_t& a, const uint64_t& m) { + int64_t x = 0, y = 0; + uint64_t g = gcdExtended(a, m, &x, &y); + if (g != 1) { // modular inverse doesn't exist + return -1; + } else { + int64_t res = ((x + m) % m); + return res; + } + } + + /** Find nCr % p + * + * @params[in] the numbers 'n', 'r' and 'p' + * @returns the value nCr % p + */ + int64_t ncr(const uint64_t& n, const uint64_t& r, const uint64_t& p) { + // Base cases + if (r > n) { + return 0; + } + if (r == 1) { + return n % p; + } + if (r == 0 || r == n) { + return 1; + } + // fac is a global array with fac[r] = (r! % p) + int64_t denominator = modInverse(fac[r], p); + if (denominator < 0) { // modular inverse doesn't exist + return -1; + } + denominator = (denominator * modInverse(fac[n - r], p)) % p; + if (denominator < 0) { // modular inverse doesn't exist + return -1; + } + return (fac[n] * denominator) % p; + } +}; +} // namespace ncr_modulo_p +} // namespace math + +/** + * @brief Test implementations + * @param ncrObj object which contains the precomputed factorial values and + * ncr function + * @returns void + */ +static void tests(math::ncr_modulo_p::NCRModuloP ncrObj) { + // (52323 C 26161) % (1e9 + 7) = 224944353 + assert(ncrObj.ncr(52323, 26161, 1000000007) == 224944353); + // 6 C 2 = 30, 30%5 = 0 + assert(ncrObj.ncr(6, 2, 5) == 0); + // 7C3 = 35, 35 % 29 = 8 + assert(ncrObj.ncr(7, 3, 29) == 6); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + // populate the fac array + const uint64_t size = 1e6 + 1; + const uint64_t p = 1e9 + 7; + math::ncr_modulo_p::NCRModuloP ncrObj = + math::ncr_modulo_p::NCRModuloP(size, p); + // test 6Ci for i=0 to 7 + for (int i = 0; i <= 7; i++) { + std::cout << 6 << "C" << i << " = " << ncrObj.ncr(6, i, p) << "\n"; + } + tests(ncrObj); // execute the tests + std::cout << "Assertions passed\n"; + return 0; +} diff --git a/math/sum_of_binomial_coefficient.cpp b/math/sum_of_binomial_coefficient.cpp index e0dc826b8..1942df527 100644 --- a/math/sum_of_binomial_coefficient.cpp +++ b/math/sum_of_binomial_coefficient.cpp @@ -1,14 +1,16 @@ /** * @file - * @brief Algorithm to find sum of binomial coefficients of a given positive integer. - * @details Given a positive integer n, the task is to find the sum of binomial coefficient i.e - * nC0 + nC1 + nC2 + ... + nCn-1 + nCn - * By induction, we can prove that the sum is equal to 2^n - * @see more on https://en.wikipedia.org/wiki/Binomial_coefficient#Sums_of_the_binomial_coefficients + * @brief Algorithm to find sum of binomial coefficients of a given positive + * integer. + * @details Given a positive integer n, the task is to find the sum of binomial + * coefficient i.e nC0 + nC1 + nC2 + ... + nCn-1 + nCn By induction, we can + * prove that the sum is equal to 2^n + * @see more on + * https://en.wikipedia.org/wiki/Binomial_coefficient#Sums_of_the_binomial_coefficients * @author [muskan0719](https://github.com/muskan0719) */ -#include /// for std::cin and std::cout -#include /// for assert +#include /// for assert +#include /// for std::cin and std::cout /** * @namespace math @@ -16,52 +18,49 @@ */ namespace math { - /** - * Function to calculate sum of binomial coefficients - * @param n number - * @return Sum of binomial coefficients of number - */ - uint64_t binomialCoeffSum(uint64_t n) - { - // Calculating 2^n - return (1 << n); - } +/** + * Function to calculate sum of binomial coefficients + * @param n number + * @return Sum of binomial coefficients of number + */ +uint64_t binomialCoeffSum(uint64_t n) { + // Calculating 2^n + return (1 << n); +} } // namespace math /** * Function for testing binomialCoeffSum function. * test cases and assert statement. * @returns `void` -*/ -static void test() -{ - int test_case_1 = math::binomialCoeffSum(2); - assert(test_case_1==4); - std::cout<<"Test_case_1 Passed!"< /// for math operations -#include /// for io operations +#include /// for math operations +#include /// for io operations /** * @namespace numerical_methods @@ -37,93 +37,92 @@ namespace numerical_methods { */ namespace false_position { /** -* @brief This function gives the value of f(x) for given x. -* @param x value for which we have to find value of f(x). -* @return value of f(x) for given x. -*/ + * @brief This function gives the value of f(x) for given x. + * @param x value for which we have to find value of f(x). + * @return value of f(x) for given x. + */ static float eq(float x) { - return (x*x-x); // original equation + return (x * x - x); // original equation } /** -* @brief This function finds root of the equation in given interval i.e. (x1,x2). +* @brief This function finds root of the equation in given interval i.e. +(x1,x2). * @param x1,x2 values for an interval in which root is present. @param y1,y2 values of function at x1, x2 espectively. * @return root of the equation in the given interval. -*/ -static float regula_falsi(float x1,float x2,float y1,float y2){ - float diff = x1-x2; - if(diff<0){ - diff= (-1)*diff; +*/ +static float regula_falsi(float x1, float x2, float y1, float y2) { + float diff = x1 - x2; + if (diff < 0) { + diff = (-1) * diff; } - if(diff<0.00001){ - if (y1<0) { - y1=-y1; + if (diff < 0.00001) { + if (y1 < 0) { + y1 = -y1; } - if (y2<0) { - y2=-y2; + if (y2 < 0) { + y2 = -y2; } - if (y1 /// for io operations -#include /// for using the vector container -#include /// asserting the test functions +#include /// asserting the test functions +#include /// for io operations +#include /// for using the vector container /** - * @brief The change() function is used - * to return the updated iterative value corresponding + * @brief The change() function is used + * to return the updated iterative value corresponding * to the given function * @param x is the value corresponding to the x coordinate - * @param y is the value corresponding to the y coordinate + * @param y is the value corresponding to the y coordinate * @returns the computed function value at that call */ -static double change(double x, double y) -{ - return ((x - y)/2.0); - -} +static double change(double x, double y) { return ((x - y) / 2.0); } /** * @namespace numerical_methods @@ -41,95 +39,95 @@ static double change(double x, double y) namespace numerical_methods { /** * @namespace runge_kutta - * @brief Functions for [Runge Kutta fourth order](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods) method + * @brief Functions for [Runge Kutta fourth + * order](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods) method */ namespace runge_kutta { /** - * @brief the Runge Kutta method finds the value of integration of a function in the given limits. - * the lower limit of integration as the initial value and the upper limit is the given x + * @brief the Runge Kutta method finds the value of integration of a function in + * the given limits. the lower limit of integration as the initial value and the + * upper limit is the given x * @param init_x is the value of initial x and is updated after each call * @param init_y is the value of initial x and is updated after each call * @param x is current iteration at which the function needs to be evaluated - * @param h is the step value - * @returns the value of y at thr required value of x from the initial conditions + * @param h is the step value + * @returns the value of y at thr required value of x from the initial + * conditions */ -double rungeKutta(double init_x, const double &init_y, const double &x, const double &h) -{ - - // Count number of iterations - // using step size or - // step height h - - - // n calucates the number of iterations - // k1, k2, k3, k4 are the Runge Kutta variables - // used for calculation of y at each iteration - - auto n = static_cast((x - init_x) / h); - // used a vector container for the variables - std::vector k(4,0.0); - - - // Iterate for number of iterations - - double y = init_y; - for (int i=1; i<=n; ++i) - { - - // Apply Runge Kutta Formulas - // to find next value of y - k[0] = h*change(init_x, y); - k[1] = h*change(init_x + 0.5*h, y + 0.5*k[0]); - k[2] = h*change(init_x + 0.5*h, y + 0.5*k[1]); - k[3] = h*change(init_x + h, y + k[2]); - - - // Update next value of y - - y += (1.0/6.0)*(k[0] + 2*k[1] + 2*k[2] + k[3]); - - // Update next value of x - - init_x += h; - } +double rungeKutta(double init_x, const double &init_y, const double &x, + const double &h) { + // Count number of iterations + // using step size or + // step height h - return y; -} -} // namespace runge_kutta -} // namespace numerical_methods + // n calucates the number of iterations + // k1, k2, k3, k4 are the Runge Kutta variables + // used for calculation of y at each iteration + + auto n = static_cast((x - init_x) / h); + // used a vector container for the variables + std::vector k(4, 0.0); + + // Iterate for number of iterations + + double y = init_y; + for (int i = 1; i <= n; ++i) { + // Apply Runge Kutta Formulas + // to find next value of y + k[0] = h * change(init_x, y); + k[1] = h * change(init_x + 0.5 * h, y + 0.5 * k[0]); + k[2] = h * change(init_x + 0.5 * h, y + 0.5 * k[1]); + k[3] = h * change(init_x + h, y + k[2]); + + // Update next value of y + + y += (1.0 / 6.0) * (k[0] + 2 * k[1] + 2 * k[2] + k[3]); + + // Update next value of x + + init_x += h; + } + + return y; +} +} // namespace runge_kutta +} // namespace numerical_methods /** * @brief Tests to check algorithm implementation. - * @returns void + * @returns void */ - static void test() - { - std::cout << "The Runge Kutta function will be tested on the basis of precomputed values\n"; +static void test() { + std::cout << "The Runge Kutta function will be tested on the basis of " + "precomputed values\n"; - std::cout << "Test 1...." << "\n"; - double valfirst=numerical_methods::runge_kutta::rungeKutta(2,3,4,0.2); // Tests the function with pre calculated values - assert(valfirst==3.10363932323749570); - std::cout << "Passed Test 1\n"; + std::cout << "Test 1...." + << "\n"; + double valfirst = numerical_methods::runge_kutta::rungeKutta( + 2, 3, 4, 0.2); // Tests the function with pre calculated values + assert(valfirst == 3.10363932323749570); + std::cout << "Passed Test 1\n"; - std::cout << "Test 2...." << "\n"; - double valsec=numerical_methods::runge_kutta::rungeKutta(1,2,5,0.1); // The value of step changed - assert(valsec==3.40600589380261409); - std::cout << "Passed Test 2\n"; + std::cout << "Test 2...." + << "\n"; + double valsec = numerical_methods::runge_kutta::rungeKutta( + 1, 2, 5, 0.1); // The value of step changed + assert(valsec == 3.40600589380261409); + std::cout << "Passed Test 2\n"; + + std::cout << "Test 3...." + << "\n"; + double valthird = numerical_methods::runge_kutta::rungeKutta( + -1, 3, 4, 0.1); // Tested with negative value + assert(valthird == 2.49251005860244268); + std::cout << "Passed Test 3\n"; +} - std::cout << "Test 3...." << "\n"; - double valthird=numerical_methods::runge_kutta::rungeKutta(-1,3,4,0.1); // Tested with negative value - assert(valthird==2.49251005860244268); - std::cout << "Passed Test 3\n"; - } - - /** * @brief Main function - * @returns 0 on exit + * @returns 0 on exit */ -int main() -{ - - test(); // Execute the tests - return 0; -} +int main() { + test(); // Execute the tests + return 0; +} diff --git a/sorting/cycle_sort.cpp b/sorting/cycle_sort.cpp index 2d14f399e..7700b2115 100644 --- a/sorting/cycle_sort.cpp +++ b/sorting/cycle_sort.cpp @@ -1,19 +1,22 @@ /** * @file - * @brief Implementation of [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) algorithm + * @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 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. + * 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 + * 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) */ -#include /// for std::is_sorted, std::swap -#include /// for assert -#include /// for io operations -#include /// for std::vector +#include /// for std::is_sorted, std::swap +#include /// for assert +#include /// for io operations +#include /// for std::vector /** * @namespace sorting @@ -22,9 +25,10 @@ namespace sorting { /** * @namespace cycle_sort - * @brief Functions for [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) algorithm + * @brief Functions for [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) + * algorithm */ -namespace cycle_sort { +namespace cycle_sort { /** * @brief The main function implements cycleSort * @tparam T type of array @@ -38,7 +42,8 @@ std::vector cycleSort(const std::vector &in_arr) { // initialize item T item = arr[cycle_start]; - // Count the number of elements smaller than item, this number is the correct index of item. + // 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++) { if (arr[i] < item) { @@ -71,18 +76,19 @@ std::vector cycleSort(const std::vector &in_arr) { } return arr; } -} // namespace cycle_sort -} // namespace sorting +} // namespace cycle_sort +} // namespace sorting /** * @brief Test implementations * @returns void */ static void test() { - // [506, 48, 123, 79, 0, 362, 951, 500, 0] return [0, 0, 48, 79, 123, 362, 500, 506, 951] + // [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}; 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; diff --git a/sorting/radix_sort2.cpp b/sorting/radix_sort2.cpp index f1e8be836..3d6916e16 100644 --- a/sorting/radix_sort2.cpp +++ b/sorting/radix_sort2.cpp @@ -3,14 +3,13 @@ * @brief Algorithm of [Radix sort](https://en.wikipedia.org/wiki/Radix_sort) * @author [Suyash Jaiswal](https://github.com/Suyashjaiswal) * @details - * Sort the vector of unsigned integers using radix sort i.e. sorting digit by digit - * using [Counting Sort](https://en.wikipedia.org/wiki/Counting_sort) as subroutine. - * Running time of radix sort is O(d*(n+b)) where b is the base for representing - * numbers and d in the max digits in input integers and n is number of unsigned integers. - * consider example for n = 5, aray elements = 432,234,143,332,123 - * sorting digit by digit - * sorting according to - * 1) 1st digit place + * Sort the vector of unsigned integers using radix sort i.e. sorting digit by + * digit using [Counting Sort](https://en.wikipedia.org/wiki/Counting_sort) as + * subroutine. Running time of radix sort is O(d*(n+b)) where b is the base for + * representing numbers and d in the max digits in input integers and n is + * number of unsigned integers. consider example for n = 5, aray elements = + * 432,234,143,332,123 sorting digit by digit sorting according to 1) 1st digit + * place * => 432, 332, 143, 123, 234 * * 2) 2nd digit place @@ -21,76 +20,79 @@ * * using count sort at each step, which is stable. * stable => already sorted according to previous digits. -*/ + */ /// header files +#include /// for collection of functions +#include /// for a macro called assert which can be used to verify assumptions #include /// for io operations #include /// for std::vector -#include /// for collection of functions -#include /// for a macro called assert which can be used to verify assumptions /** * @namespace sorting * @brief Sorting algorithms */ namespace sorting { - /** - * @namespace radix_sort - * @brief Functions for [Radix sort](https://en.wikipedia.org/wiki/Radix_sort) - * algorithm - */ - namespace radix_sort { - /** - * @brief Function to sort vector according to current digit using stable - * sorting. - * @param cur_digit - sort according to the cur_digit - * @param ar - vector to be sorted - * @returns std::vector sorted till ith digit - */ - std::vector step_ith(uint16_t cur_digit, const std::vector& ar) { // sorting according to current digit. - int n = ar.size(); - std::vector position(10, 0); - for (int i = 0; i < n; ++i) { - position[(ar[i] / cur_digit) % - 10]++; // counting frequency of 0-9 at cur_digit. - } - int cur = 0; - for (int i = 0; i < 10; ++i) { - int a = position[i]; - position[i] = cur; // assingning starting position of 0-9. - cur += a; - } - std::vector temp(n); - for (int i = 0; i < n; ++i) { - temp[position[(ar[i] / cur_digit) % 10]] = - ar[i]; // storing ar[i] in ar[i]'s cur_digit expected position of - // this step. - position[(ar[i] / cur_digit) % - 10]++; // incrementing ar[i]'s cur_digit position by 1, as - // current place used by ar[i]. - } - return temp; - } - /** - * @brief Function to sort vector digit by digit. - * @param ar - vector to be sorted - * @returns sorted vector - */ - std::vector radix(const std::vector& ar) { - uint64_t max_ele = *max_element(ar.begin(), ar.end()); // returns the max element. - std::vector temp = ar; - for (int i = 1; max_ele / i > 0; - i *= 10) { // loop breaks when i > max_ele because no further digits - // left to makes changes in aray. - temp = step_ith(i,temp); - } - for (uint64_t i : temp) { - std::cout << i << " "; - } - std::cout << "\n"; - return temp; - } - } // namespace radix_sort +/** + * @namespace radix_sort + * @brief Functions for [Radix sort](https://en.wikipedia.org/wiki/Radix_sort) + * algorithm + */ +namespace radix_sort { +/** + * @brief Function to sort vector according to current digit using stable + * sorting. + * @param cur_digit - sort according to the cur_digit + * @param ar - vector to be sorted + * @returns std::vector sorted till ith digit + */ +std::vector step_ith( + uint16_t cur_digit, + const std::vector& ar) { // sorting according to current digit. + int n = ar.size(); + std::vector position(10, 0); + for (int i = 0; i < n; ++i) { + position[(ar[i] / cur_digit) % + 10]++; // counting frequency of 0-9 at cur_digit. + } + int cur = 0; + for (int i = 0; i < 10; ++i) { + int a = position[i]; + position[i] = cur; // assingning starting position of 0-9. + cur += a; + } + std::vector temp(n); + for (int i = 0; i < n; ++i) { + temp[position[(ar[i] / cur_digit) % 10]] = + ar[i]; // storing ar[i] in ar[i]'s cur_digit expected position of + // this step. + position[(ar[i] / cur_digit) % + 10]++; // incrementing ar[i]'s cur_digit position by 1, as + // current place used by ar[i]. + } + return temp; +} +/** + * @brief Function to sort vector digit by digit. + * @param ar - vector to be sorted + * @returns sorted vector + */ +std::vector radix(const std::vector& ar) { + uint64_t max_ele = + *max_element(ar.begin(), ar.end()); // returns the max element. + std::vector temp = ar; + for (int i = 1; max_ele / i > 0; + i *= 10) { // loop breaks when i > max_ele because no further digits + // left to makes changes in aray. + temp = step_ith(i, temp); + } + for (uint64_t i : temp) { + std::cout << i << " "; + } + std::cout << "\n"; + return temp; +} +} // namespace radix_sort } // namespace sorting /** @@ -104,7 +106,7 @@ static void tests() { assert(std::is_sorted(ar1.begin(), ar1.end())); /// Test 2 std::vector ar2 = {213, 3214, 123, 111, 112, 142, - 133, 132, 32, 12, 113}; + 133, 132, 32, 12, 113}; ar2 = sorting::radix_sort::radix(ar2); assert(std::is_sorted(ar2.begin(), ar2.end())); } diff --git a/sorting/wiggle_sort.cpp b/sorting/wiggle_sort.cpp index 4d75a22bb..bf8574c98 100644 --- a/sorting/wiggle_sort.cpp +++ b/sorting/wiggle_sort.cpp @@ -17,89 +17,86 @@ * arr = [2,8,9,1,7], after wiggle sort arr will become equal to [8,2,9,1,7] */ -#include /// for io operations #include -#include #include #include +#include /// for io operations +#include /** * @namespace sorting * @brief Sorting algorithms */ namespace sorting { - /** - * @namespace wiggle_sort - * @brief Functions for [Wiggle Sort](https://leetcode.com/problems/wiggle-sort-ii/) algorithm - */ - namespace wiggle_sort { +/** + * @namespace wiggle_sort + * @brief Functions for [Wiggle + * Sort](https://leetcode.com/problems/wiggle-sort-ii/) algorithm + */ +namespace wiggle_sort { - /** - * - * @brief Function used for sorting the elements in wave form. - * @details - * Checking whether the even indexed elements are greater than - * their adjacent odd elements. - * Traversing all even indexed elements of the input arr. - * If current element is smaller than the previous odd element, swap them. - * If current element is smaller than the next odd element, swap them. - * - * @param arr input array (unsorted elements) - * - */ - template // this allows to have vectors of ints, double, float, etc - std::vector wiggleSort(const std::vector& arr) { +/** + * + * @brief Function used for sorting the elements in wave form. + * @details + * Checking whether the even indexed elements are greater than + * their adjacent odd elements. + * Traversing all even indexed elements of the input arr. + * If current element is smaller than the previous odd element, swap them. + * If current element is smaller than the next odd element, swap them. + * + * @param arr input array (unsorted elements) + * + */ +template // this allows to have vectors of ints, double, float, + // etc + std::vector wiggleSort(const std::vector &arr) { + uint32_t size = arr.size(); - uint32_t size = arr.size(); - - std::vector out(arr); // create a copy of input vector. this way, the original input vector does not get modified. a sorted array is is returned. - - for(int i = 0; i < size ; i +=2) { - - if(i > 0 && out[i-1] > out[i]) { - std::swap(out[i],out[i-1]); //swapping the two values - } - - if(i < size - 1 && out[i] < out[i+1]) { - std::swap(out[i],out[i+1]); //swapping the two values - } - - } - - return out; //returns the sorted vector + std::vector out( + arr); // create a copy of input vector. this way, the original input + // vector does not get modified. a sorted array is is returned. + for (int i = 0; i < size; i += 2) { + if (i > 0 && out[i - 1] > out[i]) { + std::swap(out[i], out[i - 1]); // swapping the two values } - } // namespace wiggle_sort -} // namespace sorting + + if (i < size - 1 && out[i] < out[i + 1]) { + std::swap(out[i], out[i + 1]); // swapping the two values + } + } + + return out; // returns the sorted vector +} +} // namespace wiggle_sort +} // namespace sorting /** * * @brief Utility function used for printing the elements. - * Prints elements of the array after they're sorted using wiggle sort algorithm. + * Prints elements of the array after they're sorted using wiggle sort + * algorithm. * * @param arr array containing the sorted elements * */ -template +template static void displayElements(const std::vector &arr) { - uint32_t size = arr.size(); std::cout << "Sorted elements are as follows: "; std::cout << "["; - for(int i = 0 ; i < size ; i++ ) { - - std::cout << arr[i] ; - if(i != size - 1) { - std::cout << ", " ; + for (int i = 0; i < size; i++) { + std::cout << arr[i]; + if (i != size - 1) { + std::cout << ", "; } - } - std::cout << "]"< &arr) { * @returns void */ static void test() { - - std::srand(std::time(nullptr)); // initialize random number generator + std::srand(std::time(nullptr)); // initialize random number generator std::vector data1(100); - for (auto &d: data1) { // generate random numbers between -5.0 and 4.99 + for (auto &d : data1) { // generate random numbers between -5.0 and 4.99 d = float(std::rand() % 1000 - 500) / 100.f; } @@ -119,12 +115,12 @@ static void test() { displayElements(sorted); - for(uint32_t j = 0; j < data1.size(); j+=2) { - assert(data1[j] <= data1[j+1] && data1[j+1] >= data1[j+2]); // check the validation condition + for (uint32_t j = 0; j < data1.size(); j += 2) { + assert(data1[j] <= data1[j + 1] && + data1[j + 1] >= data1[j + 2]); // check the validation condition } std::cout << "Test 1 passed\n"; - } /** Driver Code */