feat: Add ncr mod p code (#1325)

* feat: Add ncr mod p code (#1323)

* Update math/ncr_modulo_p.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Added all functions inside a class + added more asserts

* updating DIRECTORY.md

* clang-format and clang-tidy fixes for f6df24a5

* Replace int64_t to uint64_t + add namespace + detailed documentation

* clang-format and clang-tidy fixes for e09a0579

* Add extra namespace + add const& in function arguments

* clang-format and clang-tidy fixes for 8111f881

* Update ncr_modulo_p.cpp

* clang-format and clang-tidy fixes for 2ad2f721

* Update math/ncr_modulo_p.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update math/ncr_modulo_p.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update math/ncr_modulo_p.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* clang-format and clang-tidy fixes for 5b69ba5c

* updating DIRECTORY.md

* clang-format and clang-tidy fixes for a8401d4b

Co-authored-by: David Leal <halfpacho@gmail.com>
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
This commit is contained in:
Kaustubh Damania 2020-11-22 23:05:01 +05:30 committed by GitHub
parent c8ce6f404c
commit 67e26cfbae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1068 additions and 854 deletions

View File

@ -155,6 +155,7 @@
* [Modular Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_exponentiation.cpp) * [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) * [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) * [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) * [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) * [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) * [Prime Factorization](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/prime_factorization.cpp)

View File

@ -3,25 +3,27 @@
* @todo Add documentation * @todo Add documentation
* @warning The sorting algorithm is erroneous * @warning The sorting algorithm is erroneous
*/ */
#include <iostream>
#include <array> #include <array>
#include <iostream>
struct list { struct list {
std::array<int, 50> data{}; std::array<int, 50> data{};
int top = 0; int top = 0;
bool isSorted = false; bool isSorted = false;
int BinarySearch(const std::array<int, 50>& dataArr, int first, int last, int x) { int BinarySearch(const std::array<int, 50>& dataArr, int first, int last,
int x) {
if (last < first) { if (last < first) {
return -1; return -1;
} }
int mid = (first + last) / 2; int mid = (first + last) / 2;
if (dataArr[mid] == x) if (dataArr[mid] == x) {
return mid; return mid;
else if (x < dataArr[mid]) } else if (x < dataArr[mid]) {
return (BinarySearch(dataArr, first, mid - 1, x)); return (BinarySearch(dataArr, first, mid - 1, x));
else if (x > dataArr[mid]) } else if (x > dataArr[mid]) {
return (BinarySearch(dataArr, mid + 1, last, x)); return (BinarySearch(dataArr, mid + 1, last, x));
}
std::cerr << __func__ << ":" << __LINE__ << ": Undefined condition\n"; std::cerr << __func__ << ":" << __LINE__ << ": Undefined condition\n";
return -1; return -1;
@ -38,7 +40,7 @@ struct list {
} }
int Search(int x) { int Search(int x) {
int pos; int pos = 0;
if (isSorted) { if (isSorted) {
pos = BinarySearch(data, 0, top - 1, x); pos = BinarySearch(data, 0, top - 1, x);
@ -55,7 +57,7 @@ struct list {
} }
void Sort() { void Sort() {
int i, j, pos=0; int i = 0, j = 0, pos = 0;
for (i = 0; i < top; i++) { for (i = 0; i < top; i++) {
int min = data[i]; int min = data[i];
for (j = i + 1; j < top; j++) { for (j = i + 1; j < top; j++) {
@ -119,8 +121,8 @@ struct list {
int main() { int main() {
list L; list L;
int choice; int choice = 0;
int x; int x = 0;
do { do {
// Choices for operations on the list_array. // Choices for operations on the list_array.
std::cout << "\n0.Exit"; std::cout << "\n0.Exit";

View File

@ -8,16 +8,17 @@
* head of line (dequeue) and displayed. * head of line (dequeue) and displayed.
* ### Algorithm * ### Algorithm
* Values can be added by increasing the `rear` variable by 1 (which points to * 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. * 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 * Values can be removed by increasing the `front` variable by 1 (which points
* the first of the array), so it cannot reached any more. * to the first of the array), so it cannot reached any more.
* *
* @author [Pooja](https://github.com/pooja-git11) * @author [Pooja](https://github.com/pooja-git11)
* @author [Farbod Ahmadian](https://github.com/farbodahm) * @author [Farbod Ahmadian](https://github.com/farbodahm)
*/ */
#include <iostream> /// for io operations
#include <array> /// for std::array #include <array> /// for std::array
#include <iostream> /// 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
@ -30,12 +31,14 @@ namespace data_structures {
/** /**
* @namespace queue_using_array * @namespace queue_using_array
* @brief Functions for [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 { 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 { class Queue_Array {
public: public:
@ -45,7 +48,7 @@ public:
private: private:
int8_t front{-1}; ///< Index of head of the array int8_t front{-1}; ///< Index of head of the array
int8_t rear{-1}; ///< Index of tail of the array int8_t rear{-1}; ///< Index of tail of the array
std::array<int16_t, max_size> arr; ///< All stored data std::array<int16_t, max_size> arr{}; ///< All stored data
}; };
/** /**
@ -98,7 +101,6 @@ void Queue_Array::display() const {
} // namespace queue_using_array } // namespace queue_using_array
} // namespace data_structures } // namespace data_structures
/** /**
* @brief Main function * @brief Main function
* @details * @details

View File

@ -75,12 +75,13 @@ int maxKnapsackValue(const int capacity, const std::array<int, n> &weight,
int profit2 = maxValue[i - 1][j]; int profit2 = maxValue[i - 1][j];
maxValue[i][j] = std::max(profit1, profit2); maxValue[i][j] = std::max(profit1, profit2);
} else } else {
// as weight of current item is greater than allowed weight, so // as weight of current item is greater than allowed weight, so
// maxProfit will be profit obtained by excluding current item. // maxProfit will be profit obtained by excluding current item.
maxValue[i][j] = maxValue[i - 1][j]; maxValue[i][j] = maxValue[i - 1][j];
} }
} }
}
// returning maximum value // returning maximum value
return maxValue[items][capacity]; return maxValue[items][capacity];

View File

@ -1,7 +1,8 @@
/** /**
* @file * @file
* @brief [Minimum coins](https://leetcode.com/problems/coin-change/) change problem is a problem used to find the minimum number of * @brief [Minimum coins](https://leetcode.com/problems/coin-change/) change
* coins required to completely reach a target amount. * problem is a problem used to find the minimum number of coins required to
* completely reach a target amount.
* *
* @details * @details
* This problem can be solved using 2 methods: * This problem can be solved using 2 methods:
@ -17,10 +18,10 @@
* @author [Divyansh Kushwaha](https://github.com/webdesignbydivyansh) * @author [Divyansh Kushwaha](https://github.com/webdesignbydivyansh)
*/ */
#include <iostream> // for io operations
#include <vector> // for std::vector
#include <cassert> // for assert #include <cassert> // for assert
#include <climits> // for INT_MAX #include <climits> // for INT_MAX
#include <iostream> // for io operations
#include <vector> // for std::vector
/** /**
* @namespace dynamic_programming * @namespace dynamic_programming
@ -29,7 +30,8 @@
namespace dynamic_programming { namespace dynamic_programming {
/** /**
* @namespace mincoins_topdown * @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 { namespace mincoins_topdown {
/** /**
@ -42,7 +44,8 @@ namespace mincoins_topdown {
* @returns minimum number of coins * @returns minimum number of coins
*/ */
template <typename T> template <typename T>
int64_t mincoins(const T &n, const std::vector<T> &coins, const int16_t &t, std::vector<T> dp){ int64_t mincoins(const T &n, const std::vector<T> &coins, const int16_t &t,
std::vector<T> dp) {
if (n == 0) { if (n == 0) {
return 0; return 0;
} }
@ -51,7 +54,8 @@ namespace mincoins_topdown {
} }
int ans = INT_MAX; // variable to store min coins int ans = INT_MAX; // variable to store min coins
for (int i = 0; i < t; i++) { 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 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); int sub = mincoins(n - coins[i], coins, t, dp);
ans = std::min(ans, sub + 1); ans = std::min(ans, sub + 1);
} }
@ -75,7 +79,8 @@ static void test() {
std::vector<int64_t> arr1{1, 7, 10}; std::vector<int64_t> arr1{1, 7, 10};
std::vector<int64_t> dp1(n1 + 1); std::vector<int64_t> dp1(n1 + 1);
fill(dp1.begin(), dp1.end(), a1); fill(dp1.begin(), dp1.end(), a1);
assert(dynamic_programming::mincoins_topdown::mincoins(n1, arr1, t1, dp1)==3); assert(dynamic_programming::mincoins_topdown::mincoins(n1, arr1, t1, dp1) ==
3);
std::cout << "Passed\n"; std::cout << "Passed\n";
} }

View File

@ -1,26 +1,26 @@
/** /**
* @file * @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 * @details
* palindrome partitioning uses dynamic programming and goes to all the possible partitions to find the minimum * palindrome partitioning uses dynamic programming and goes to all the possible
* you are given a string and you need to give minimum number of partitions needed to divide it into a number of palindromes * partitions to find the minimum you are given a string and you need to give
* [Palindrome Partitioning] (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/) * minimum number of partitions needed to divide it into a number of palindromes
* overall time complexity O(n^2) * [Palindrome Partitioning]
* For example: example 1:- * (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/) overall time
* String : "nitik" * complexity O(n^2) For example: example 1:- String : "nitik" Output : 2 => "n
* Output : 2 => "n | iti | k" * | iti | k" For example: example 2:- String : "ababbbabbababa" Output : 3 =>
* For example: example 2:- * "aba | b | bbabb | ababa"
* String : "ababbbabbababa"
* Output : 3 => "aba | b | bbabb | ababa"
* @author [Sujay Kaushik] (https://github.com/sujaykaushik008) * @author [Sujay Kaushik] (https://github.com/sujaykaushik008)
*/ */
#include <iostream> // for io operations
#include <vector> // for std::vector
#include <algorithm> // for std::min #include <algorithm> // for std::min
#include <cassert> // for std::assert #include <cassert> // for std::assert
#include <climits> // for INT_MAX #include <climits> // for INT_MAX
#include <iostream> // for io operations
#include <vector> // for std::vector
/** /**
* @namespace dynamic_programming * @namespace dynamic_programming
@ -30,24 +30,27 @@ namespace dynamic_programming {
/** /**
* @namespace palindrome_partitioning * @namespace palindrome_partitioning
* @brief Functions for [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) algorithm * @brief Functions for [Palindrome
* Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/)
* algorithm
*/ */
namespace palindrome_partitioning { namespace palindrome_partitioning {
/** /**
* Function implementing palindrome partitioning algorithm using lookup table method. * Function implementing palindrome partitioning algorithm using lookup table
* method.
* @param str input string * @param str input string
* @returns minimum number of partitions * @returns minimum number of partitions
*/ */
int pal_part(const std::string &str) { int pal_part(const std::string &str) {
int n = str.size(); int n = str.size();
// creating lookup table for minimum number of cuts // creating lookup table for minimum number of cuts
std::vector<std::vector<int> > cuts(n, std::vector<int>(n, 0)); std::vector<std::vector<int> > cuts(n, std::vector<int>(n, 0));
// creating lookup table for palindrome checking // creating lookup table for palindrome checking
std::vector<std::vector<bool> > is_palindrome(n, std::vector<bool>(n, false)); std::vector<std::vector<bool> > is_palindrome(n,
std::vector<bool>(n, false));
// initialization // initialization
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
@ -57,22 +60,25 @@ namespace dynamic_programming {
for (int len = 2; len <= n; len++) { for (int len = 2; len <= n; len++) {
for (int start_index = 0; start_index < n - len + 1; start_index++) { for (int start_index = 0; start_index < n - len + 1; start_index++) {
int end_index = start_index + len - 1; int end_index = start_index + len - 1;
if (len == 2) { if (len == 2) {
is_palindrome[start_index][end_index] = (str[start_index] == str[end_index]); is_palindrome[start_index][end_index] =
(str[start_index] == str[end_index]);
} else { } else {
is_palindrome[start_index][end_index] = is_palindrome[start_index][end_index] =
(str[start_index] == str[end_index]) && is_palindrome[start_index + 1][end_index - 1]; (str[start_index] == str[end_index]) &&
is_palindrome[start_index + 1][end_index - 1];
} }
if (is_palindrome[start_index][end_index]) { if (is_palindrome[start_index][end_index]) {
cuts[start_index][end_index] = 0; cuts[start_index][end_index] = 0;
} else { } else {
cuts[start_index][end_index] = INT_MAX; cuts[start_index][end_index] = INT_MAX;
for (int partition = start_index; partition <= end_index - 1; partition++) { for (int partition = start_index; partition <= end_index - 1;
cuts[start_index][end_index] = std::min(cuts[start_index][end_index], partition++) {
cuts[start_index][end_index] =
std::min(cuts[start_index][end_index],
cuts[start_index][partition] + cuts[start_index][partition] +
cuts[partition + 1][end_index] + 1); cuts[partition + 1][end_index] + 1);
} }
@ -97,7 +103,9 @@ static void test() {
std::vector<int> calculated_output(3); std::vector<int> calculated_output(3);
for (int i = 0; i < 3; i++) { 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 // expected output vector

View File

@ -48,11 +48,11 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <queue>
#include <vector>
#include <map>
#include <list> #include <list>
#include <map>
#include <queue>
#include <string> #include <string>
#include <vector>
/** /**
* \namespace graph * \namespace graph
@ -63,20 +63,23 @@ namespace graph{
template <typename T> template <typename T>
class Graph { class Graph {
/** /**
* adjacency_list maps every vertex to the list of its neighbours in the order * adjacency_list maps every vertex to the list of its neighbours in the
* in which they are added. * order in which they are added.
*/ */
std::map<T, std::list<T> > adjacency_list; std::map<T, std::list<T> > adjacency_list;
public: public:
Graph(){}; Graph() = default;
;
void add_edge(T u, T v, bool bidir = true) { 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 * add_edge(u,v,bidir) is used to add an edge between node u and
* by default , bidir is made true , i.e graph is bidirectional . * node v by default , bidir is made true , i.e graph is
* It means if edge(u,v) is added then u-->v and v-->u both edges exist. * 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 * to make the graph unidirectional pass the third parameter of
* false which will * add_edge as false which will
*/ */
adjacency_list[u].push_back(v); // u-->v edge added adjacency_list[u].push_back(v); // u-->v edge added
if (bidir == true) { if (bidir == true) {
@ -85,7 +88,6 @@ namespace graph{
} }
} }
/** /**
* this function performs the breadth first search on graph and return a * this function performs the breadth first search on graph and return a
* mapping which maps the nodes to a boolean value representing whether the * mapping which maps the nodes to a boolean value representing whether the
@ -117,7 +119,8 @@ namespace graph{
/// remove the node from the queue /// remove the node from the queue
tracker.pop(); tracker.pop();
for (T const &neighbour : adjacency_list[node]) { for (T const &neighbour : adjacency_list[node]) {
/// check every vertex connected to the node which are still unvisited /// check every vertex connected to the node which are still
/// unvisited
if (!visited[neighbour]) { if (!visited[neighbour]) {
/// if the neighbour is unvisited , push it into the queue /// if the neighbour is unvisited , push it into the queue
tracker.push(neighbour); tracker.push(neighbour);
@ -130,8 +133,7 @@ namespace graph{
} }
}; };
/* Class definition ends */ /* Class definition ends */
} } // namespace graph
/** Test function */ /** Test function */
static void tests() { static void tests() {
@ -168,7 +170,8 @@ static void tests() {
g2.add_edge("Agra", "Noida", false); g2.add_edge("Agra", "Noida", false);
std::map<std::string, bool> correct_res; std::map<std::string, bool> correct_res;
std::map<std::string,bool> returned_res=g2.breadth_first_search("Kanpur"); std::map<std::string, bool> returned_res =
g2.breadth_first_search("Kanpur");
correct_res["Gorakhpur"] = false; correct_res["Gorakhpur"] = false;
correct_res["Lucknow"] = false; correct_res["Lucknow"] = false;
correct_res["Kanpur"] = true; correct_res["Kanpur"] = true;
@ -177,7 +180,6 @@ static void tests() {
correct_res["Noida"] = true; correct_res["Noida"] = true;
assert(correct_res == returned_res); assert(correct_res == returned_res);
std::cout << "Test 3 Passed..." << std::endl; std::cout << "Test 3 Passed..." << std::endl;
} }
/** Main function */ /** Main function */

View File

@ -1,5 +1,5 @@
#include <iostream>
#include <array> #include <array>
#include <iostream>
void findMinimumEdge(int INFINITY, std::array<std::array<int, 6>, 6> graph) { void findMinimumEdge(int INFINITY, std::array<std::array<int, 6>, 6> graph) {
for (int i = 0; i < graph.size(); i++) { for (int i = 0; i < graph.size(); i++) {
@ -11,14 +11,15 @@ void findMinimumEdge(int INFINITY, std::array< std::array< int ,6 >,6 > graph) {
minIndex = 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() { int main() {
constexpr int INFINITY = 99999; constexpr int INFINITY = 99999;
std::array< std::array< int ,6 >,6 >graph std::array<std::array<int, 6>, 6> graph{
{0, 4, 1, 4, INFINITY, INFINITY, 0, 4, 1, 4, INFINITY, INFINITY,
4, 0, 3, 8, 3, INFINITY, 4, 0, 3, 8, 3, INFINITY,
1, 3, 0, INFINITY, 1, INFINITY, 1, 3, 0, INFINITY, 1, INFINITY,
4, 8, INFINITY, 0, 5, 7, 4, 8, INFINITY, 0, 5, 7,

View File

@ -1,17 +1,19 @@
/** /**
* @file * @file
* @brief [Gram Schmidt Orthogonalisation Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process) * @brief [Gram Schmidt Orthogonalisation
* Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process)
* *
* @details * @details
* Takes the input of Linearly Independent Vectors, * Takes the input of Linearly Independent Vectors,
* returns vectors orthogonal to each other. * returns vectors orthogonal to each other.
* *
* ### Algorithm * ### Algorithm
* Take the first vector of given LI vectors as first vector of Orthogonal vectors. * Take the first vector of given LI vectors as first vector of Orthogonal
* Take projection of second input vector on the first vector of Orthogonal vector * vectors. Take projection of second input vector on the first vector of
* and subtract it from the 2nd LI vector. * Orthogonal vector and subtract it from the 2nd LI vector. Take projection of
* Take projection of third vector on the second vector of Othogonal vectors and subtract it from the 3rd LI vector. * third vector on the second vector of Othogonal vectors and subtract it from
* Keep repeating the above process until all the vectors in the given input array are exhausted. * the 3rd LI vector. Keep repeating the above process until all the vectors in
* the given input array are exhausted.
* *
* For Example: * For Example:
* In R2, * In R2,
@ -26,10 +28,12 @@
* @author [Akanksha Gupta](https://github.com/Akanksha-Gupta920) * @author [Akanksha Gupta](https://github.com/Akanksha-Gupta920)
*/ */
#include <iostream> /// for io operations #include <array> /// for std::array
#include <cassert> /// for assert #include <cassert> /// for assert
#include <cmath> /// for fabs #include <cmath> /// for fabs
#include <array> /// for std::array #include <iostream> /// for io operations
#include "math.h"
/** /**
* @namespace linear_algebra * @namespace linear_algebra
@ -38,19 +42,22 @@
namespace linear_algebra { namespace linear_algebra {
/** /**
* @namespace gram_schmidt * @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 { namespace gram_schmidt {
/** /**
* Dot product function. * 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 x vector 1
* @param y vector 2 * @param y vector 2
* @param c dimension of the vectors * @param c dimension of the vectors
* *
* @returns sum * @returns sum
*/ */
double dot_product(const std::array<double, 10>& x, const std::array<double, 10>& y, const int& c) { double dot_product(const std::array<double, 10>& x,
const std::array<double, 10>& y, const int& c) {
double sum = 0; double sum = 0;
for (int i = 0; i < c; ++i) { for (int i = 0; i < c; ++i) {
sum += x[i] * y[i]; sum += x[i] * y[i];
@ -60,7 +67,8 @@ double dot_product(const std::array<double, 10>& x, const std::array<double, 10>
/** /**
* Projection Function * 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 x Vector 1
* @param y Vector 2 * @param y Vector 2
@ -68,11 +76,16 @@ double dot_product(const std::array<double, 10>& x, const std::array<double, 10>
* *
* @returns factor * @returns factor
*/ */
double projection(const std::array<double, 10>& x,const std::array<double, 10>& y, double projection(const std::array<double, 10>& x,
const int& c) { const std::array<double, 10>& y, const int& c) {
double dot = dot_product(x, y, c); ///The dot product of two vectors is taken double dot =
double anorm = dot_product(y, y, c); ///The norm of the second vector is taken. dot_product(x, y, c); /// The dot product of two vectors 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. 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; return factor;
} }
@ -85,7 +98,8 @@ double projection(const std::array<double, 10>& x,const std::array<double, 10>&
* *
* @returns void * @returns void
*/ */
void display(const int& r,const int& c,const std::array<std::array<double, 10>, 20>& B) { void display(const int& r, const int& c,
const std::array<std::array<double, 10>, 20>& B) {
for (int i = 0; i < r; ++i) { for (int i = 0; i < r; ++i) {
std::cout << "Vector " << i + 1 << ": "; std::cout << "Vector " << i + 1 << ": ";
for (int j = 0; j < c; ++j) { for (int j = 0; j < c; ++j) {
@ -104,11 +118,12 @@ void display(const int& r,const int& c,const std::array<std::array<double, 10>,
* *
* @returns void * @returns void
*/ */
void gram_schmidt(int r,const int& c,const std::array<std::array<double, 10>, 20>& A, void gram_schmidt(int r, const int& c,
const std::array<std::array<double, 10>, 20>& A,
std::array<std::array<double, 10>, 20> B) { std::array<std::array<double, 10>, 20> B) {
if (c < r) { /// we check whether appropriate dimensions are given or not. if (c < r) { /// we check whether appropriate dimensions are given or not.
std::cout std::cout << "Dimension of vector is less than number of vector, hence "
<< "Dimension of vector is less than number of vector, hence \n first " "\n first "
<< c << " vectors are orthogonalised\n"; << c << " vectors are orthogonalised\n";
r = c; r = c;
} }
@ -117,29 +132,40 @@ void gram_schmidt(int r,const int& c,const std::array<std::array<double, 10>, 20
while (k <= r) { while (k <= r) {
if (k == 1) { if (k == 1) {
for (int j = 0; j < c; j++) B[0][j] = A[0][j]; ///First vector is copied as it is. for (int j = 0; j < c; j++)
B[0][j] = A[0][j]; /// First vector is copied as it is.
} }
else { else {
std::array<double, 10> all_projection{}; ///array to store projections std::array<double, 10>
all_projection{}; /// array to store projections
for (int i = 0; i < c; ++i) { for (int i = 0; i < c; ++i) {
all_projection[i] = 0; /// First initialised to zero all_projection[i] = 0; /// First initialised to zero
} }
int l = 1; int l = 1;
while (l < k) { while (l < k) {
std::array<double, 10> temp{}; ///to store previous projected array std::array<double, 10>
double factor; ///to store the factor by which the previous array will change 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); factor = projection(A[k - 1], B[l - 1], c);
for(int i = 0; i < c; ++i) for (int i = 0; i < c; ++i) {
temp[i] = B[l - 1][i] * factor; /// projected array created temp[i] = B[l - 1][i] * factor; /// projected array created
}
for (int j = 0; j < c; ++j) { 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. all_projection[j] =
all_projection[j] +
temp[j]; /// we take the projection with all the
/// previous vector and add them.
} }
l++; l++;
} }
for (int i = 0; i < c; ++i) { 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 B[k - 1][i] =
A[k - 1][i] -
all_projection[i]; /// subtract total projection vector
/// from the input vector
} }
} }
k++; k++;
@ -159,15 +185,18 @@ static void test() {
double dot1 = 0; double dot1 = 0;
linear_algebra::gram_schmidt::gram_schmidt(3, 4, a1, b1); linear_algebra::gram_schmidt::gram_schmidt(3, 4, a1, b1);
int flag = 1; int flag = 1;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i) {
for (int j = i + 1; j < 3; ++j) { for (int j = i + 1; j < 3; ++j) {
dot1 = fabs(linear_algebra::gram_schmidt::dot_product(b1[i], b1[j], 4)); dot1 = fabs(
linear_algebra::gram_schmidt::dot_product(b1[i], b1[j], 4));
if (dot1 > 0.1) { if (dot1 > 0.1) {
flag = 0; flag = 0;
break; break;
} }
} }
if (flag == 0) std::cout << "Vectors are linearly dependent\n"; }
if (flag == 0)
std::cout << "Vectors are linearly dependent\n";
assert(flag == 1); assert(flag == 1);
std::cout << "Passed Test Case 1\n "; std::cout << "Passed Test Case 1\n ";
@ -176,15 +205,18 @@ static void test() {
double dot2 = 0; double dot2 = 0;
linear_algebra::gram_schmidt::gram_schmidt(2, 2, a2, b2); linear_algebra::gram_schmidt::gram_schmidt(2, 2, a2, b2);
flag = 1; flag = 1;
for (int i = 0; i < 1; ++i) for (int i = 0; i < 1; ++i) {
for (int j = i + 1; j < 2; ++j) { for (int j = i + 1; j < 2; ++j) {
dot2 = fabs(linear_algebra::gram_schmidt::dot_product(b2[i], b2[j], 2)); dot2 = fabs(
linear_algebra::gram_schmidt::dot_product(b2[i], b2[j], 2));
if (dot2 > 0.1) { if (dot2 > 0.1) {
flag = 0; flag = 0;
break; break;
} }
} }
if (flag == 0) std::cout << "Vectors are linearly dependent\n"; }
if (flag == 0)
std::cout << "Vectors are linearly dependent\n";
assert(flag == 1); assert(flag == 1);
std::cout << "Passed Test Case 2\n"; std::cout << "Passed Test Case 2\n";
@ -193,15 +225,18 @@ static void test() {
double dot3 = 0; double dot3 = 0;
linear_algebra::gram_schmidt::gram_schmidt(2, 3, a3, b3); linear_algebra::gram_schmidt::gram_schmidt(2, 3, a3, b3);
flag = 1; flag = 1;
for (int i = 0; i < 1; ++i) for (int i = 0; i < 1; ++i) {
for (int j = i + 1; j < 2; ++j) { for (int j = i + 1; j < 2; ++j) {
dot3 = fabs(linear_algebra::gram_schmidt::dot_product(b3[i], b3[j], 3)); dot3 = fabs(
linear_algebra::gram_schmidt::dot_product(b3[i], b3[j], 3));
if (dot3 > 0.1) { if (dot3 > 0.1) {
flag = 0; flag = 0;
break; break;
} }
} }
if (flag == 0) std::cout << "Vectors are linearly dependent\n" ; }
if (flag == 0)
std::cout << "Vectors are linearly dependent\n";
assert(flag == 1); assert(flag == 1);
std::cout << "Passed Test Case 3\n"; std::cout << "Passed Test Case 3\n";
} }
@ -224,7 +259,8 @@ int main() {
{0}}; /// a 2-D array for storing orthogonalised vectors {0}}; /// a 2-D array for storing orthogonalised vectors
/// storing vectors in array A /// storing vectors in array A
for (int i = 0; i < r; ++i) { for (int i = 0; i < r; ++i) {
std::cout << "Enter vector " << i + 1 <<'\n'; ///Input of vectors is taken std::cout << "Enter vector " << i + 1
<< '\n'; /// Input of vectors is taken
for (int j = 0; j < c; ++j) { for (int j = 0; j < c; ++j) {
std::cout << "Value " << j + 1 << "th of vector: "; std::cout << "Value " << j + 1 << "th of vector: ";
std::cin >> A[i][j]; std::cin >> A[i][j];
@ -238,14 +274,17 @@ int main() {
int flag = 1; /// To check whether vectors are orthogonal or not int flag = 1; /// To check whether vectors are orthogonal or not
for (int i = 0; i < r - 1; ++i) { for (int i = 0; i < r - 1; ++i) {
for (int j = i + 1; j < r; ++j) { for (int j = i + 1; j < r; ++j) {
dot = fabs(linear_algebra::gram_schmidt::dot_product(B[i], B[j], c)); dot =
if (dot > 0.1) /// take make the process numerically stable, upper bound for the dot product take 0.1 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; flag = 0;
break; break;
} }
} }
} }
if (flag == 0) std::cout << "Vectors are linearly dependent\n"; if (flag == 0)
std::cout << "Vectors are linearly dependent\n";
return 0; return 0;
} }

View File

@ -35,7 +35,8 @@ namespace math {
* @param A martix 2 * @param A martix 2
* @returns resultant matrix * @returns resultant matrix
*/ */
math::fibonacci_sum::matrix multiply(const math::fibonacci_sum::matrix &T, const math::fibonacci_sum::matrix &A) { 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<uint64_t>(2, 0)); math::fibonacci_sum::matrix result(2, std::vector<uint64_t>(2, 0));
// multiplying matrices // multiplying matrices

View File

@ -1,18 +1,19 @@
/** /**
* @file * @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$ * @brief An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) +
* @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$ * \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$
* denotes the Least Common Multiple of the integers i and n. For n greater than or equal to 1. * @details An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) +
* The value of the sum is calculated by formula: * \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ where
* \f[ * \f$\mathrm{LCM}(i,n)\f$ denotes the Least Common Multiple of the integers i
* \sum\mathrm{LCM}(i, n) = \frac{1}{2} \left[\left(\sum (d * \mathrm{ETF}(d)) + 1\right) * n\right] * and n. For n greater than or equal to 1. The value of the sum is calculated
* \f] * by formula: \f[ \sum\mathrm{LCM}(i, n) = \frac{1}{2} \left[\left(\sum (d *
* where \mathrm{ETF}(i) represents Euler totient function of i. * \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) * @author [Chesta Mittal](https://github.com/chestamittal)
*/ */
#include <iostream> /// for std::cin and std::cout
#include <cassert> /// for assert #include <cassert> /// for assert
#include <iostream> /// for std::cin and std::cout
#include <vector> /// for std::vector #include <vector> /// for std::vector
/** /**
@ -26,7 +27,6 @@ namespace math {
* @returns int Sum of LCMs, i.e. LCM(i, num) from i = 1 to num * @returns int Sum of LCMs, i.e. LCM(i, num) from i = 1 to num
*/ */
uint64_t lcmSum(const uint16_t& num) { uint64_t lcmSum(const uint16_t& num) {
uint64_t i = 0, j = 0; uint64_t i = 0, j = 0;
std::vector<uint64_t> eulerTotient(num + 1); std::vector<uint64_t> eulerTotient(num + 1);
std::vector<uint64_t> sumOfEulerTotient(num + 1); std::vector<uint64_t> sumOfEulerTotient(num + 1);

View File

@ -1,6 +1,7 @@
/** /**
* @file * @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 * @details
* A very basic and efficient method of calculating * A very basic and efficient method of calculating
* choosing r from n different choices. * choosing r from n different choices.
@ -9,8 +10,8 @@
* @author [Tajmeet Singh](https://github.com/tjgurwara99) * @author [Tajmeet Singh](https://github.com/tjgurwara99)
*/ */
#include <iostream> /// for io operations
#include <cassert> /// for assert #include <cassert> /// for assert
#include <iostream> /// for io operations
/** /**
* @namespace math * @namespace math
@ -23,7 +24,8 @@ namespace math {
* We are calculating the ans with iterations * We are calculating the ans with iterations
* instead of calculating three different factorials. * instead of calculating three different factorials.
* Also, we are using the fact that * 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$ * \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 * @tparam T Only for integer types such as long, int_64 etc
* @param n \f$ n \f$ in \f$ \binom{n}{r} \f$ * @param n \f$ n \f$ in \f$ \binom{n}{r} \f$
* @param r \f$ r \f$ in \f$ \binom{n}{r} \f$ * @param r \f$ r \f$ in \f$ \binom{n}{r} \f$
@ -31,8 +33,9 @@ namespace math {
*/ */
template <class T> template <class T>
T n_choose_r(T n, T r) { T n_choose_r(T n, T r) {
if(r > n / 2) if (r > n / 2) {
r = n - r; // Because of the fact that nCr(n, r) == nCr(n, n - r) r = n - r; // Because of the fact that nCr(n, r) == nCr(n, n - r)
}
T ans = 1; T ans = 1;
for (int i = 1; i <= r; i++) { for (int i = 1; i <= r; i++) {
ans *= n - r + i; ans *= n - r + i;
@ -49,18 +52,17 @@ T n_choose_r(T n, T r) {
static void test() { static void test() {
// First test on 5 choose 2 // First test on 5 choose 2
uint8_t t = math::n_choose_r(5, 2); uint8_t t = math::n_choose_r(5, 2);
assert(((void)"10 is the answer but function says otherwise.\n", assert(((void)"10 is the answer but function says otherwise.\n", t == 10));
t == 10));
std::cout << "First test passes." << std::endl; std::cout << "First test passes." << std::endl;
// Second test on 5 choose 3 // Second test on 5 choose 3
t = math::n_choose_r(5, 3); t = math::n_choose_r(5, 3);
assert(((void)"10 is the answer but the function says otherwise.\n", assert(
t == 10)); ((void)"10 is the answer but the function says otherwise.\n", t == 10));
std::cout << "Second test passes." << std::endl; std::cout << "Second test passes." << std::endl;
// Third test on 3 choose 2 // Third test on 3 choose 2
t = math::n_choose_r(3, 2); t = math::n_choose_r(3, 2);
assert(((void)"3 is the answer but the function says otherwise.\n", assert(
t == 3)); ((void)"3 is the answer but the function says otherwise.\n", t == 3));
std::cout << "Third test passes." << std::endl; std::cout << "Third test passes." << std::endl;
// Fourth test on 10 choose 4 // Fourth test on 10 choose 4
t = math::n_choose_r(10, 4); t = math::n_choose_r(10, 4);

150
math/ncr_modulo_p.cpp Normal file
View File

@ -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 <cassert> /// for assert
#include <iostream> /// for io operations
#include <vector> /// 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<uint64_t> 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<uint64_t>(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;
}

View File

@ -1,14 +1,16 @@
/** /**
* @file * @file
* @brief Algorithm to find sum of binomial coefficients of a given positive integer. * @brief Algorithm to find sum of binomial coefficients of a given positive
* @details Given a positive integer n, the task is to find the sum of binomial coefficient i.e * integer.
* nC0 + nC1 + nC2 + ... + nCn-1 + nCn * @details Given a positive integer n, the task is to find the sum of binomial
* By induction, we can prove that the sum is equal to 2^n * coefficient i.e nC0 + nC1 + nC2 + ... + nCn-1 + nCn By induction, we can
* @see more on https://en.wikipedia.org/wiki/Binomial_coefficient#Sums_of_the_binomial_coefficients * 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) * @author [muskan0719](https://github.com/muskan0719)
*/ */
#include <iostream> /// for std::cin and std::cout
#include <cassert> /// for assert #include <cassert> /// for assert
#include <iostream> /// for std::cin and std::cout
/** /**
* @namespace math * @namespace math
@ -21,8 +23,7 @@ namespace math {
* @param n number * @param n number
* @return Sum of binomial coefficients of number * @return Sum of binomial coefficients of number
*/ */
uint64_t binomialCoeffSum(uint64_t n) uint64_t binomialCoeffSum(uint64_t n) {
{
// Calculating 2^n // Calculating 2^n
return (1 << n); return (1 << n);
} }
@ -33,8 +34,7 @@ namespace math {
* test cases and assert statement. * test cases and assert statement.
* @returns `void` * @returns `void`
*/ */
static void test() static void test() {
{
int test_case_1 = math::binomialCoeffSum(2); int test_case_1 = math::binomialCoeffSum(2);
assert(test_case_1 == 4); assert(test_case_1 == 4);
std::cout << "Test_case_1 Passed!" << std::endl; std::cout << "Test_case_1 Passed!" << std::endl;
@ -60,8 +60,7 @@ static void test()
* @brief Main function * @brief Main function
* @returns 0 on exit * @returns 0 on exit
*/ */
int main() int main() {
{
test(); // execute the tests test(); // execute the tests
return 0; return 0;
} }

View File

@ -46,7 +46,8 @@ static float eq(float x) {
} }
/** /**
* @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 x1,x2 values for an interval in which root is present.
@param y1,y2 values of function at x1, x2 espectively. @param y1,y2 values of function at x1, x2 espectively.
* @return root of the equation in the given interval. * @return root of the equation in the given interval.
@ -65,8 +66,7 @@ static float regula_falsi(float x1,float x2,float y1,float y2){
} }
if (y1 < y2) { if (y1 < y2) {
return x1; return x1;
} } else {
else {
return x2; return x2;
} }
} }
@ -84,21 +84,17 @@ static float regula_falsi(float x1,float x2,float y1,float y2){
void printRoot(float root, const int16_t &count) { void printRoot(float root, const int16_t &count) {
if (count == 1) { if (count == 1) {
std::cout << "Your 1st root is : " << root << std::endl; std::cout << "Your 1st root is : " << root << std::endl;
} } else if (count == 2) {
else if(count==2){
std::cout << "Your 2nd root is : " << root << std::endl; std::cout << "Your 2nd root is : " << root << std::endl;
} } else if (count == 3) {
else if(count==3){
std::cout << "Your 3rd root is : " << root << std::endl; std::cout << "Your 3rd root is : " << root << std::endl;
} } else {
else{
std::cout << "Your " << count << "th root is : " << root << std::endl; std::cout << "Your " << count << "th root is : " << root << std::endl;
} }
} }
} // namespace false_position } // namespace false_position
} // namespace numerical_methods } // namespace numerical_methods
/** /**
* @brief Main function * @brief Main function
* @returns 0 on exit * @returns 0 on exit
@ -106,11 +102,13 @@ void printRoot(float root, const int16_t &count){
int main() { int main() {
float a = 0, b = 0, i = 0, root = 0; float a = 0, b = 0, i = 0, root = 0;
int16_t count = 0; int16_t count = 0;
float range = 100000; //Range in which we have to find the root. (-range,range) float range =
100000; // Range in which we have to find the root. (-range,range)
float gap = 0.5; // interval gap. lesser the gap more the accuracy float gap = 0.5; // interval gap. lesser the gap more the accuracy
a = numerical_methods::false_position::eq((-1) * range); a = numerical_methods::false_position::eq((-1) * range);
i = ((-1) * range + gap); i = ((-1) * range + gap);
//while loop for selecting proper interval in provided range and with provided interval gap. // while loop for selecting proper interval in provided range and with
// provided interval gap.
while (i <= range) { while (i <= range) {
b = numerical_methods::false_position::eq(i); b = numerical_methods::false_position::eq(i);
if (b == 0) { if (b == 0) {
@ -118,7 +116,8 @@ int main() {
numerical_methods::false_position::printRoot(i, count); numerical_methods::false_position::printRoot(i, count);
} }
if (a * b < 0) { if (a * b < 0) {
root = numerical_methods::false_position::regula_falsi(i-gap,i,a,b); root = numerical_methods::false_position::regula_falsi(i - gap, i,
a, b);
count++; count++;
numerical_methods::false_position::printRoot(root, count); numerical_methods::false_position::printRoot(root, count);
} }

View File

@ -1,7 +1,9 @@
/** /**
* @{ * @{
* \file * \file
* \brief [Runge Kutta fourth order](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods) method implementation * \brief [Runge Kutta fourth
* order](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods) method
* implementation
* *
* \author [Rudra Prasad Das](http://github.com/rudra697) * \author [Rudra Prasad Das](http://github.com/rudra697)
* *
@ -16,9 +18,9 @@
* conditions * conditions
* There can be many such equations * There can be many such equations
*/ */
#include <cassert> /// asserting the test functions
#include <iostream> /// for io operations #include <iostream> /// for io operations
#include <vector> /// for using the vector container #include <vector> /// for using the vector container
#include <cassert> /// asserting the test functions
/** /**
* @brief The change() function is used * @brief The change() function is used
@ -28,11 +30,7 @@
* @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 * @returns the computed function value at that call
*/ */
static double change(double x, double y) static double change(double x, double y) { return ((x - y) / 2.0); }
{
return ((x - y)/2.0);
}
/** /**
* @namespace numerical_methods * @namespace numerical_methods
@ -41,26 +39,27 @@ static double change(double x, double y)
namespace numerical_methods { namespace numerical_methods {
/** /**
* @namespace runge_kutta * @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 { namespace runge_kutta {
/** /**
* @brief the Runge Kutta method finds the value of integration of a function in the given limits. * @brief the Runge Kutta method finds the value of integration of a function in
* the lower limit of integration as the initial value and the upper limit is the given x * 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_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 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 x is current iteration at which the function needs to be evaluated
* @param h is the step value * @param h is the step value
* @returns the value of y at thr required value of x from the initial conditions * @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) double rungeKutta(double init_x, const double &init_y, const double &x,
{ const double &h) {
// Count number of iterations // Count number of iterations
// using step size or // using step size or
// step height h // step height h
// n calucates the number of iterations // n calucates the number of iterations
// k1, k2, k3, k4 are the Runge Kutta variables // k1, k2, k3, k4 are the Runge Kutta variables
// used for calculation of y at each iteration // used for calculation of y at each iteration
@ -69,13 +68,10 @@ double rungeKutta(double init_x, const double &init_y, const double &x, const do
// used a vector container for the variables // used a vector container for the variables
std::vector<double> k(4, 0.0); std::vector<double> k(4, 0.0);
// Iterate for number of iterations // Iterate for number of iterations
double y = init_y; double y = init_y;
for (int i=1; i<=n; ++i) for (int i = 1; i <= n; ++i) {
{
// Apply Runge Kutta Formulas // Apply Runge Kutta Formulas
// to find next value of y // to find next value of y
k[0] = h * change(init_x, y); k[0] = h * change(init_x, y);
@ -83,7 +79,6 @@ double rungeKutta(double init_x, const double &init_y, const double &x, const do
k[2] = h * change(init_x + 0.5 * h, y + 0.5 * k[1]); k[2] = h * change(init_x + 0.5 * h, y + 0.5 * k[1]);
k[3] = h * change(init_x + h, y + k[2]); k[3] = h * change(init_x + h, y + k[2]);
// Update next value of y // Update next value of y
y += (1.0 / 6.0) * (k[0] + 2 * k[1] + 2 * k[2] + k[3]); y += (1.0 / 6.0) * (k[0] + 2 * k[1] + 2 * k[2] + k[3]);
@ -102,34 +97,37 @@ double rungeKutta(double init_x, const double &init_y, const double &x, const do
* @brief Tests to check algorithm implementation. * @brief Tests to check algorithm implementation.
* @returns void * @returns void
*/ */
static void test() static void test() {
{ std::cout << "The Runge Kutta function will be tested on the basis of "
std::cout << "The Runge Kutta function will be tested on the basis of precomputed values\n"; "precomputed values\n";
std::cout << "Test 1...." << "\n"; std::cout << "Test 1...."
double valfirst=numerical_methods::runge_kutta::rungeKutta(2,3,4,0.2); // Tests the function with pre calculated values << "\n";
double valfirst = numerical_methods::runge_kutta::rungeKutta(
2, 3, 4, 0.2); // Tests the function with pre calculated values
assert(valfirst == 3.10363932323749570); assert(valfirst == 3.10363932323749570);
std::cout << "Passed Test 1\n"; std::cout << "Passed Test 1\n";
std::cout << "Test 2...." << "\n"; std::cout << "Test 2...."
double valsec=numerical_methods::runge_kutta::rungeKutta(1,2,5,0.1); // The value of step changed << "\n";
double valsec = numerical_methods::runge_kutta::rungeKutta(
1, 2, 5, 0.1); // The value of step changed
assert(valsec == 3.40600589380261409); assert(valsec == 3.40600589380261409);
std::cout << "Passed Test 2\n"; std::cout << "Passed Test 2\n";
std::cout << "Test 3...." << "\n"; std::cout << "Test 3...."
double valthird=numerical_methods::runge_kutta::rungeKutta(-1,3,4,0.1); // Tested with negative value << "\n";
double valthird = numerical_methods::runge_kutta::rungeKutta(
-1, 3, 4, 0.1); // Tested with negative value
assert(valthird == 2.49251005860244268); assert(valthird == 2.49251005860244268);
std::cout << "Passed Test 3\n"; std::cout << "Passed Test 3\n";
} }
/** /**
* @brief Main function * @brief Main function
* @returns 0 on exit * @returns 0 on exit
*/ */
int main() int main() {
{
test(); // Execute the tests test(); // Execute the tests
return 0; return 0;
} }

View File

@ -1,11 +1,14 @@
/** /**
* @file * @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 * @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. * Cycle Sort is a sorting algorithm that works in \f$O(n^2)\f$ time in best cas
* If a element is already at its correct position, do nothing. * and works in \f$O(n^2)\f$ in worst case. If a element is already at its
* 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. * 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) * @author [TsungHan Ho](https://github.com/dalaoqi)
*/ */
@ -22,7 +25,8 @@
namespace sorting { namespace sorting {
/** /**
* @namespace cycle_sort * @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 {
/** /**
@ -38,7 +42,8 @@ std::vector<T> cycleSort(const std::vector<T> &in_arr) {
// initialize item // initialize item
T item = arr[cycle_start]; 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; int pos = cycle_start;
for (size_t i = cycle_start + 1; i < arr.size(); i++) { for (size_t i = cycle_start + 1; i < arr.size(); i++) {
if (arr[i] < item) { if (arr[i] < item) {
@ -79,7 +84,8 @@ std::vector<T> cycleSort(const std::vector<T> &in_arr) {
* @returns void * @returns void
*/ */
static void test() { 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<int> array1 = {506, 48, 123, 79, 0, 362, 951, 500, 0}; std::vector<int> array1 = {506, 48, 123, 79, 0, 362, 951, 500, 0};
std::cout << "Test 1... "; std::cout << "Test 1... ";
std::vector<int> arr1 = sorting::cycle_sort::cycleSort(array1); std::vector<int> arr1 = sorting::cycle_sort::cycleSort(array1);

View File

@ -3,14 +3,13 @@
* @brief Algorithm of [Radix sort](https://en.wikipedia.org/wiki/Radix_sort) * @brief Algorithm of [Radix sort](https://en.wikipedia.org/wiki/Radix_sort)
* @author [Suyash Jaiswal](https://github.com/Suyashjaiswal) * @author [Suyash Jaiswal](https://github.com/Suyashjaiswal)
* @details * @details
* Sort the vector of unsigned integers using radix sort i.e. sorting digit by digit * Sort the vector of unsigned integers using radix sort i.e. sorting digit by
* using [Counting Sort](https://en.wikipedia.org/wiki/Counting_sort) as subroutine. * digit using [Counting Sort](https://en.wikipedia.org/wiki/Counting_sort) as
* Running time of radix sort is O(d*(n+b)) where b is the base for representing * subroutine. Running time of radix sort is O(d*(n+b)) where b is the base for
* numbers and d in the max digits in input integers and n is number of unsigned integers. * representing numbers and d in the max digits in input integers and n is
* consider example for n = 5, aray elements = 432,234,143,332,123 * number of unsigned integers. consider example for n = 5, aray elements =
* sorting digit by digit * 432,234,143,332,123 sorting digit by digit sorting according to 1) 1st digit
* sorting according to * place
* 1) 1st digit place
* => 432, 332, 143, 123, 234 * => 432, 332, 143, 123, 234
* *
* 2) 2nd digit place * 2) 2nd digit place
@ -24,10 +23,10 @@
*/ */
/// header files /// header files
#include <iostream> /// for io operations
#include <vector> /// for std::vector
#include <algorithm> /// for collection of functions #include <algorithm> /// for collection of functions
#include <cassert> /// for a macro called assert which can be used to verify assumptions #include <cassert> /// for a macro called assert which can be used to verify assumptions
#include <iostream> /// for io operations
#include <vector> /// for std::vector
/** /**
* @namespace sorting * @namespace sorting
@ -47,7 +46,9 @@ namespace sorting {
* @param ar - vector to be sorted * @param ar - vector to be sorted
* @returns std::vector sorted till ith digit * @returns std::vector sorted till ith digit
*/ */
std::vector<uint64_t> step_ith(uint16_t cur_digit, const std::vector<uint64_t>& ar) { // sorting according to current digit. std::vector<uint64_t> step_ith(
uint16_t cur_digit,
const std::vector<uint64_t>& ar) { // sorting according to current digit.
int n = ar.size(); int n = ar.size();
std::vector<uint32_t> position(10, 0); std::vector<uint32_t> position(10, 0);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
@ -77,7 +78,8 @@ namespace sorting {
* @returns sorted vector * @returns sorted vector
*/ */
std::vector<uint64_t> radix(const std::vector<uint64_t>& ar) { std::vector<uint64_t> radix(const std::vector<uint64_t>& ar) {
uint64_t max_ele = *max_element(ar.begin(), ar.end()); // returns the max element. uint64_t max_ele =
*max_element(ar.begin(), ar.end()); // returns the max element.
std::vector<uint64_t> temp = ar; std::vector<uint64_t> temp = ar;
for (int i = 1; max_ele / i > 0; for (int i = 1; max_ele / i > 0;
i *= 10) { // loop breaks when i > max_ele because no further digits i *= 10) { // loop breaks when i > max_ele because no further digits

View File

@ -17,11 +17,11 @@
* arr = [2,8,9,1,7], after wiggle sort arr will become equal to [8,2,9,1,7] * arr = [2,8,9,1,7], after wiggle sort arr will become equal to [8,2,9,1,7]
*/ */
#include <iostream> /// for io operations
#include <algorithm> #include <algorithm>
#include <vector>
#include <cassert> #include <cassert>
#include <ctime> #include <ctime>
#include <iostream> /// for io operations
#include <vector>
/** /**
* @namespace sorting * @namespace sorting
@ -30,7 +30,8 @@
namespace sorting { namespace sorting {
/** /**
* @namespace wiggle_sort * @namespace wiggle_sort
* @brief Functions for [Wiggle Sort](https://leetcode.com/problems/wiggle-sort-ii/) algorithm * @brief Functions for [Wiggle
* Sort](https://leetcode.com/problems/wiggle-sort-ii/) algorithm
*/ */
namespace wiggle_sort { namespace wiggle_sort {
@ -47,15 +48,16 @@ namespace sorting {
* @param arr input array (unsorted elements) * @param arr input array (unsorted elements)
* *
*/ */
template<typename T> // this allows to have vectors of ints, double, float, etc template <typename T> // this allows to have vectors of ints, double, float,
// etc
std::vector<T> wiggleSort(const std::vector<T> &arr) { std::vector<T> wiggleSort(const std::vector<T> &arr) {
uint32_t size = arr.size(); uint32_t size = arr.size();
std::vector<T> out(arr); // create a copy of input vector. this way, the original input vector does not get modified. a sorted array is is returned. std::vector<T> 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) { for (int i = 0; i < size; i += 2) {
if (i > 0 && out[i - 1] > out[i]) { if (i > 0 && out[i - 1] > out[i]) {
std::swap(out[i], out[i - 1]); // swapping the two values std::swap(out[i], out[i - 1]); // swapping the two values
} }
@ -63,11 +65,9 @@ namespace sorting {
if (i < size - 1 && out[i] < out[i + 1]) { if (i < size - 1 && out[i] < out[i + 1]) {
std::swap(out[i], out[i + 1]); // swapping the two values std::swap(out[i], out[i + 1]); // swapping the two values
} }
} }
return out; // returns the sorted vector return out; // returns the sorted vector
} }
} // namespace wiggle_sort } // namespace wiggle_sort
} // namespace sorting } // namespace sorting
@ -75,14 +75,14 @@ namespace sorting {
/** /**
* *
* @brief Utility function used for printing the elements. * @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 * @param arr array containing the sorted elements
* *
*/ */
template <typename T> template <typename T>
static void displayElements(const std::vector<T> &arr) { static void displayElements(const std::vector<T> &arr) {
uint32_t size = arr.size(); uint32_t size = arr.size();
std::cout << "Sorted elements are as follows: "; std::cout << "Sorted elements are as follows: ";
@ -90,16 +90,13 @@ static void displayElements(const std::vector<T> &arr) {
std::cout << "["; std::cout << "[";
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
std::cout << arr[i]; std::cout << arr[i];
if (i != size - 1) { if (i != size - 1) {
std::cout << ", "; std::cout << ", ";
} }
} }
std::cout << "]" << std::endl; std::cout << "]" << std::endl;
} }
/** /**
@ -107,7 +104,6 @@ static void displayElements(const std::vector<T> &arr) {
* @returns void * @returns void
*/ */
static void test() { static void test() {
std::srand(std::time(nullptr)); // initialize random number generator std::srand(std::time(nullptr)); // initialize random number generator
std::vector<float> data1(100); std::vector<float> data1(100);
@ -120,11 +116,11 @@ static void test() {
displayElements(sorted); displayElements(sorted);
for (uint32_t j = 0; j < data1.size(); j += 2) { 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 assert(data1[j] <= data1[j + 1] &&
data1[j + 1] >= data1[j + 2]); // check the validation condition
} }
std::cout << "Test 1 passed\n"; std::cout << "Test 1 passed\n";
} }
/** Driver Code */ /** Driver Code */