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

@ -7,19 +7,20 @@
* values, which can be added to the end line (enqueue), removed from * values, which can be added to the end line (enqueue), removed from
* 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 *
* the first of the array), so it cannot reached any more. * 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 [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
/** /**
* @namespace data_structures * @namespace data_structures
@ -30,29 +31,31 @@ 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:
void enqueue(const int16_t&); ///< Add element to the first of the queue void enqueue(const int16_t&); ///< Add element to the first of the queue
int dequeue(); ///< Delete element from back of the queue int dequeue(); ///< Delete element from back of the queue
void display() const; ///< Show all saved data void display() const; ///< Show all saved data
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
}; };
/** /**
* @brief Adds new element to the end of the queue * @brief Adds new element to the end of the queue
* @param ele to be added 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) { if (rear == arr.size() - 1) {
std::cout << "\nStack is full"; std::cout << "\nStack is full";
} else if (front == -1 && rear == -1) { } else if (front == -1 && rear == -1) {
@ -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,10 +75,11 @@ 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];
}
} }
} }

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 <cassert> // for assert
#include <vector> // for std::vector #include <climits> // for INT_MAX
#include <cassert> // for assert #include <iostream> // for io operations
#include <climits> // for INT_MAX #include <vector> // for std::vector
/** /**
* @namespace dynamic_programming * @namespace dynamic_programming
@ -29,36 +30,39 @@
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 {
/** /**
* @brief This implementation is for finding 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 T template-type to use any kind of value
* @param n amount to be reached * @param n amount to be reached
* @param coins vector of coins * @param coins vector of coins
* @param t deontes the number of coins * @param t deontes the number of coins
* @param dp initilised to 0 * @param dp initilised to 0
* @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,
if(n==0){ std::vector<T> dp) {
return 0; 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
} }
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 mincoins_topdown
} // namespace dynamic_programming } // namespace dynamic_programming
@ -70,12 +74,13 @@ namespace mincoins_topdown {
static void test() { static void test() {
// example 1: number of coins=3 and minimum coins required=3(7,7,1) // example 1: number of coins=3 and minimum coins required=3(7,7,1)
const int64_t n1 = 15; const int64_t n1 = 15;
const int8_t t1=3, a1=0; const int8_t t1 = 3, a1 = 0;
std::cout << "\nTest 1..."; std::cout << "\nTest 1...";
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";
} }
@ -84,6 +89,6 @@ static void test() {
* @returns 0 on exit * @returns 0 on exit
*/ */
int main() { int main() {
test(); // execute the test test(); // execute the test
return 0; return 0;
} }

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
@ -28,67 +28,73 @@
*/ */
namespace dynamic_programming { 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/)
namespace palindrome_partitioning { * algorithm
*/
namespace palindrome_partitioning {
/** /**
* Function implementing palindrome partitioning algorithm using lookup table method. * Function implementing palindrome partitioning algorithm using lookup table
* @param str input string * method.
* @returns minimum number of partitions * @param str input string
*/ * @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
std::vector<std::vector<int> > cuts(n, std::vector<int>(n, 0));
// creating lookup table for minimum number of cuts // creating lookup table for palindrome checking
std::vector<std::vector<int> > cuts(n, std::vector<int>(n, 0)); std::vector<std::vector<bool> > is_palindrome(n,
std::vector<bool>(n, false));
// creating lookup table for palindrome checking // initialization
std::vector<std::vector<bool> > is_palindrome(n, std::vector<bool>(n, false)); for (int i = 0; i < n; i++) {
is_palindrome[i][i] = true;
cuts[i][i] = 0;
}
// initialization for (int len = 2; len <= n; len++) {
for (int i = 0; i < n; i++) { for (int start_index = 0; start_index < n - len + 1; start_index++) {
is_palindrome[i][i] = true; int end_index = start_index + len - 1;
cuts[i][i] = 0;
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++) { if (is_palindrome[start_index][end_index]) {
for (int start_index = 0; start_index < n - len + 1; start_index++) { cuts[start_index][end_index] = 0;
} else {
int end_index = start_index + len - 1; cuts[start_index][end_index] = INT_MAX;
for (int partition = start_index; partition <= end_index - 1;
if (len == 2) { partition++) {
is_palindrome[start_index][end_index] = (str[start_index] == str[end_index]); cuts[start_index][end_index] =
} else { std::min(cuts[start_index][end_index],
is_palindrome[start_index][end_index] = cuts[start_index][partition] +
(str[start_index] == str[end_index]) && is_palindrome[start_index + 1][end_index - 1]; 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 } // namespace dynamic_programming
/** /**
* @brief Test Function * @brief Test Function
* @return void * @return void
*/ */
static void test() { static void test() {
// custom input vector // custom input vector
std::vector<std::string> custom_input{"nitik", "ababbbabbababa", "abdc"}; std::vector<std::string> custom_input{"nitik", "ababbbabbababa", "abdc"};
@ -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,136 +48,138 @@
#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
* \brief Graph algorithms * \brief Graph algorithms
*/ */
namespace graph{ namespace graph {
/* Class Graph definition */ /* Class Graph definition */
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:
Graph(){}; public:
void add_edge(T u,T v, bool bidir=true){ 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 * 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 *
* false which will * 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){ adjacency_list[u].push_back(v); // u-->v edge added
// if graph is bidirectional if (bidir == true) {
adjacency_list[v].push_back(u); // v-->u edge added // 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
* 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 * node was traversed or not.
* node was traversed or not. */
*/ std::map<T, bool> breadth_first_search(T src) {
std::map<T,bool> breadth_first_search(T src){ /// mapping to keep track of all visited nodes
/// mapping to keep track of all visited nodes std::map<T, bool> visited;
std::map<T,bool> visited;
/// initialise every possible vertex to map to false /// initialise every possible vertex to map to false
/// initially none of the vertices are unvisited /// initially none of the vertices are unvisited
for(auto const &adjlist: adjacency_list){ for (auto const &adjlist : adjacency_list) {
visited[adjlist.first]=false; visited[adjlist.first] = false;
for(auto const &node:adjacency_list[adjlist.first]){ for (auto const &node : adjacency_list[adjlist.first]) {
visited[node]=false; visited[node] = false;
} }
} }
/// queue to store the nodes which are yet to be traversed /// queue to store the nodes which are yet to be traversed
std::queue<T> tracker; std::queue<T> tracker;
/// push the source vertex to queue to begin traversing /// push the source vertex to queue to begin traversing
tracker.push(src); tracker.push(src);
///mark the source vertex as visited /// mark the source vertex as visited
visited[src]=true; visited[src] = true;
while(!tracker.empty()){ while (!tracker.empty()) {
/// traverse the graph till no connected vertex are left /// traverse the graph till no connected vertex are left
/// extract a node from queue for further traversal /// extract a node from queue for further traversal
T node = tracker.front(); T node = tracker.front();
/// 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
if(!visited[neighbour]){ /// unvisited
/// if the neighbour is unvisited , push it into the queue if (!visited[neighbour]) {
tracker.push(neighbour); /// if the neighbour is unvisited , push it into the queue
/// mark the neighbour as visited tracker.push(neighbour);
visited[neighbour]=true; /// mark the neighbour as visited
visited[neighbour] = true;
}
} }
}
} }
return visited; return visited;
} }
}; };
/* Class definition ends */ /* Class definition ends */
} } // namespace graph
/** Test function */ /** Test function */
static void tests() { static void tests() {
/// Test 1 Begin /// Test 1 Begin
graph::Graph<int> g; graph::Graph<int> g;
std::map<int,bool> correct_result; std::map<int, bool> correct_result;
g.add_edge(0,1); g.add_edge(0, 1);
g.add_edge(1,2); g.add_edge(1, 2);
g.add_edge(2,3); g.add_edge(2, 3);
correct_result[0]=true; correct_result[0] = true;
correct_result[1]=true; correct_result[1] = true;
correct_result[2]=true; correct_result[2] = true;
correct_result[3]=true; correct_result[3] = true;
std::map<int,bool> returned_result = g.breadth_first_search(2); std::map<int, bool> returned_result = g.breadth_first_search(2);
assert(returned_result==correct_result); assert(returned_result == correct_result);
std::cout << "Test 1 Passed..." << std::endl; std::cout << "Test 1 Passed..." << std::endl;
/// Test 2 Begin /// Test 2 Begin
returned_result = g.breadth_first_search(0); returned_result = g.breadth_first_search(0);
assert(returned_result==correct_result); assert(returned_result == correct_result);
std::cout << "Test 2 Passed..." << std::endl; std::cout << "Test 2 Passed..." << std::endl;
/// Test 3 Begins /// Test 3 Begins
graph::Graph<std::string> g2; graph::Graph<std::string> g2;
g2.add_edge("Gorakhpur","Lucknow",false); g2.add_edge("Gorakhpur", "Lucknow", false);
g2.add_edge("Gorakhpur","Kanpur",false); g2.add_edge("Gorakhpur", "Kanpur", false);
g2.add_edge("Lucknow","Agra",false); g2.add_edge("Lucknow", "Agra", false);
g2.add_edge("Kanpur","Agra",false); g2.add_edge("Kanpur", "Agra", false);
g2.add_edge("Lucknow","Prayagraj",false); g2.add_edge("Lucknow", "Prayagraj", false);
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 =
correct_res["Gorakhpur"]=false; g2.breadth_first_search("Kanpur");
correct_res["Lucknow"]=false; correct_res["Gorakhpur"] = false;
correct_res["Kanpur"]=true; correct_res["Lucknow"] = false;
correct_res["Agra"]=true; correct_res["Kanpur"] = true;
correct_res["Prayagraj"]=false; correct_res["Agra"] = true;
correct_res["Noida"]=true; correct_res["Prayagraj"] = false;
assert(correct_res==returned_res); correct_res["Noida"] = true;
assert(correct_res == returned_res);
std::cout << "Test 3 Passed..." << std::endl; std::cout << "Test 3 Passed..." << std::endl;
} }
/** Main function */ /** Main function */
@ -194,7 +196,7 @@ int main() {
while (edges--) { while (edges--) {
int u = 0, v = 0; int u = 0, v = 0;
std::cin >> u >> v; std::cin >> u >> v;
g.add_edge(u,v); g.add_edge(u, v);
} }
g.breadth_first_search(0); g.breadth_first_search(0);

View File

@ -1,30 +1,31 @@
#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++) {
int min = INFINITY; int min = INFINITY;
int minIndex = 0; 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) { if (graph[i][j] != 0 && graph[i][j] < min) {
min = graph[i][j]; min = graph[i][j];
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,
INFINITY, 3, 1, 5, 0, INFINITY, INFINITY, 3, 1, 5, 0, INFINITY,
INFINITY, INFINITY, INFINITY, 7, INFINITY, 0}; INFINITY, INFINITY, INFINITY, 7, INFINITY, 0};
findMinimumEdge(INFINITY,graph); findMinimumEdge(INFINITY, graph);
return 0; return 0;
} }

View File

@ -1,20 +1,22 @@
/** /**
* @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,
* Input LI Vectors={(3,1),(2,2)} * Input LI Vectors={(3,1),(2,2)}
* then Orthogonal Vectors= {(3, 1),(-0.4, 1.2)} * then Orthogonal Vectors= {(3, 1),(-0.4, 1.2)}
* *
@ -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,29 +42,33 @@
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,
double sum = 0; const std::array<double, 10>& y, const int& c) {
for (int i = 0; i < c; ++i) { double sum = 0;
sum += x[i] * y[i]; for (int i = 0; i < c; ++i) {
} sum += x[i] * y[i];
return sum; }
return sum;
} }
/** /**
* 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,12 +76,17 @@ 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 =
return factor; 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<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,
for (int i = 0; i < r; ++i) { const std::array<std::array<double, 10>, 20>& B) {
std::cout << "Vector " << i + 1 << ": "; for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) { std::cout << "Vector " << i + 1 << ": ";
std::cout << B[i][j] << " "; 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<std::array<double, 10>,
* @param c dimension of vectors * @param c dimension of vectors
* @param A stores input of given LI vectors * @param A stores input of given LI vectors
* @param B stores orthogonalised vectors * @param B stores orthogonalised vectors
* *
* @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;
}
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.
} }
else { int k = 1;
std::array<double, 10> 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 (k <= r) {
while (l < k) { if (k == 1) {
std::array<double, 10> temp{}; ///to store previous projected array for (int j = 0; j < c; j++)
double factor; ///to store the factor by which the previous array will change B[0][j] = A[0][j]; /// First vector is copied as it is.
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++;
} else {
for (int i = 0; i < c; ++i) { std::array<double, 10>
B[k - 1][i] = A[k - 1][i] - all_projection[i]; ///subtract total projection vector from the input vector 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<double, 10>
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 gram_schmidt
} // namespace linear_algebra } // namespace linear_algebra
@ -153,57 +179,66 @@ void gram_schmidt(int r,const int& c,const std::array<std::array<double, 10>, 20
* @returns void * @returns void
*/ */
static void test() { static void test() {
std::array<std::array<double, 10>, 20> a1 = { std::array<std::array<double, 10>, 20> a1 = {
{{1, 0, 1, 0}, {1, 1, 1, 1}, {0, 1, 2, 1}}}; {{1, 0, 1, 0}, {1, 1, 1, 1}, {0, 1, 2, 1}}};
std::array<std::array<double, 10>, 20> b1 = {{0}}; std::array<std::array<double, 10>, 20> b1 = {{0}};
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(
if (dot1 > 0.1) { linear_algebra::gram_schmidt::dot_product(b1[i], b1[j], 4));
flag = 0; if (dot1 > 0.1) {
break; flag = 0;
} break;
}
}
} }
if (flag == 0) std::cout << "Vectors are linearly dependent\n"; if (flag == 0)
assert(flag == 1); std::cout << "Vectors are linearly dependent\n";
std::cout << "Passed Test Case 1\n "; assert(flag == 1);
std::cout << "Passed Test Case 1\n ";
std::array<std::array<double, 10>, 20> a2 = {{{3, 1}, {2, 2}}}; std::array<std::array<double, 10>, 20> a2 = {{{3, 1}, {2, 2}}};
std::array<std::array<double, 10>, 20> b2 = {{0}}; std::array<std::array<double, 10>, 20> b2 = {{0}};
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(
if (dot2 > 0.1) { linear_algebra::gram_schmidt::dot_product(b2[i], b2[j], 2));
flag = 0; if (dot2 > 0.1) {
break; flag = 0;
} break;
}
}
} }
if (flag == 0) std::cout << "Vectors are linearly dependent\n"; if (flag == 0)
assert(flag == 1); std::cout << "Vectors are linearly dependent\n";
std::cout << "Passed Test Case 2\n"; assert(flag == 1);
std::cout << "Passed Test Case 2\n";
std::array<std::array<double, 10>, 20> a3 = {{{1, 2, 2}, {-4, 3, 2}}}; std::array<std::array<double, 10>, 20> a3 = {{{1, 2, 2}, {-4, 3, 2}}};
std::array<std::array<double, 10>, 20> b3 = {{0}}; std::array<std::array<double, 10>, 20> b3 = {{0}};
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(
if (dot3 > 0.1) { linear_algebra::gram_schmidt::dot_product(b3[i], b3[j], 3));
flag = 0; if (dot3 > 0.1) {
break; flag = 0;
} break;
}
}
} }
if (flag == 0) std::cout << "Vectors are linearly dependent\n" ; if (flag == 0)
assert(flag == 1); std::cout << "Vectors are linearly dependent\n";
std::cout << "Passed Test Case 3\n"; assert(flag == 1);
std::cout << "Passed Test Case 3\n";
} }
/** /**
@ -211,41 +246,45 @@ static void test() {
* @return 0 on exit * @return 0 on exit
*/ */
int main() { int main() {
int r=0, c=0; int r = 0, c = 0;
test(); // perform self tests test(); // perform self tests
std::cout << "Enter the dimension of your vectors\n"; std::cout << "Enter the dimension of your vectors\n";
std::cin >> c; std::cin >> c;
std::cout << "Enter the number of vectors you will enter\n"; std::cout << "Enter the number of vectors you will enter\n";
std::cin >> r; std::cin >> r;
std::array<std::array<double, 10>, 20> std::array<std::array<double, 10>, 20>
A{}; ///a 2-D array for storing all vectors A{}; /// a 2-D array for storing all vectors
std::array<std::array<double, 10>, 20> B = { std::array<std::array<double, 10>, 20> B = {
{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
for (int j = 0; j < c; ++j) { << '\n'; /// Input of vectors is taken
std::cout << "Value " << j + 1 << "th of vector: "; for (int j = 0; j < c; ++j) {
std::cin >> A[i][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; double dot = 0;
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
flag = 0; /// bound for the dot product take 0.1
break; {
} flag = 0;
break;
}
}
} }
} if (flag == 0)
if (flag == 0) std::cout << "Vectors are linearly dependent\n"; std::cout << "Vectors are linearly dependent\n";
return 0; return 0;
} }

View File

@ -21,75 +21,76 @@
* @brief Mathematical algorithms * @brief Mathematical algorithms
*/ */
namespace math { namespace math {
/** /**
* @namespace fibonacci_sum * @namespace fibonacci_sum
* @brief Functions for the sum of the Fibonacci Sequence: \f$\mathrm{F}(n) + * @brief Functions for the sum of the Fibonacci Sequence: \f$\mathrm{F}(n) +
* \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$ * \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$
*/ */
namespace fibonacci_sum { namespace fibonacci_sum {
using matrix = std::vector<std::vector<uint64_t> >; using matrix = std::vector<std::vector<uint64_t> >;
/** /**
* Function to multiply two matrices * Function to multiply two matrices
* @param T matrix 1 * @param T matrix 1
* @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,
math::fibonacci_sum::matrix result(2, std::vector<uint64_t>(2, 0)); const math::fibonacci_sum::matrix &A) {
math::fibonacci_sum::matrix result(2, std::vector<uint64_t>(2, 0));
// multiplying matrices // multiplying matrices
result[0][0] = T[0][0]*A[0][0] + T[0][1]*A[1][0]; 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[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][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]; 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. * Function to compute A^n where A is a matrix.
* @param T matrix * @param T matrix
* @param ex power * @param ex power
* @returns resultant matrix * @returns resultant matrix
*/ */
math::fibonacci_sum::matrix power(math::fibonacci_sum::matrix T, uint64_t ex) { math::fibonacci_sum::matrix power(math::fibonacci_sum::matrix T, uint64_t ex) {
math::fibonacci_sum::matrix A{{1, 1}, {1, 0}}; math::fibonacci_sum::matrix A{{1, 1}, {1, 0}};
if (ex == 0 || ex == 1) { if (ex == 0 || ex == 1) {
return T; return T;
} }
T = power(T, ex / 2); T = power(T, ex / 2);
T = multiply(T, T); T = multiply(T, T);
if (ex & 1) { if (ex & 1) {
T = multiply(T, A); T = multiply(T, A);
} }
return T; return T;
} }
/** /**
* Function to compute sum of fibonacci sequence from 0 to n. * Function to compute sum of fibonacci sequence from 0 to n.
* @param n number * @param n number
* @returns uint64_t ans, the sum of sequence * @returns uint64_t ans, the sum of sequence
*/ */
uint64_t result(uint64_t n) { uint64_t result(uint64_t n) {
math::fibonacci_sum::matrix T{{1, 1}, {1, 0}}; math::fibonacci_sum::matrix T{{1, 1}, {1, 0}};
T = power(T, n); T = power(T, n);
uint64_t ans = T[0][1]; uint64_t ans = T[0][1];
ans = (ans - 1); ans = (ans - 1);
return ans; return ans;
} }
/** /**
* Function to compute sum of fibonacci sequence from n to m. * Function to compute sum of fibonacci sequence from n to m.
* @param n start of sequence * @param n start of sequence
* @param m end of sequence * @param m end of sequence
* @returns uint64_t the sum of sequence * @returns uint64_t the sum of sequence
*/ */
uint64_t fiboSum(uint64_t n, uint64_t m) { uint64_t fiboSum(uint64_t n, uint64_t m) {
return (result(m + 2) - result(n + 1)); return (result(m + 2) - result(n + 1));
} }
} // namespace fibonacci_sum } // namespace fibonacci_sum
} // namespace math } // namespace math
/** /**

View File

@ -1,67 +1,67 @@
/** /**
* @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
/** /**
* @namespace math * @namespace math
* @brief Mathematical algorithms * @brief Mathematical algorithms
*/ */
namespace math { namespace math {
/** /**
* Function to compute sum of euler totients in sumOfEulerTotient vector * Function to compute sum of euler totients in sumOfEulerTotient vector
* @param num input number * @param num input number
* @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);
// storing initial values in eulerTotient vector
for(i=1; i<=num; i++) {
eulerTotient[i] = i;
}
// applying totient sieve // storing initial values in eulerTotient vector
for(i=2; i<=num; i++) { for (i = 1; i <= num; i++) {
if(eulerTotient[i] == i) { 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;
} }
// 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 } // namespace math
/** /**
* Function for testing lcmSum function. * Function for testing lcmSum function.
* test cases and assert statement. * test cases and assert statement.
* @returns `void` * @returns `void`
*/ */
static void test() { static void test() {
uint64_t n = 2; uint64_t n = 2;
uint64_t test_1 = math::lcmSum(n); uint64_t test_1 = math::lcmSum(n);

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
@ -22,8 +23,9 @@ namespace math {
* @details * @details
* 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,16 +33,17 @@ 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;
ans /= i; ans /= i;
} }
return ans; return ans;
} }
} // namespace math } // namespace math
/** /**
* @brief Test implementations * @brief Test implementations
@ -48,25 +51,24 @@ 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(
assert(((void)"10 is the answer but the function says otherwise.\n", ((void)"10 is the answer but the function says otherwise.\n", t == 10));
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(
assert(((void)"3 is the answer but the function says otherwise.\n", ((void)"3 is the answer but the function says otherwise.\n", t == 3));
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); assert(((void)"210 is the answer but the function says otherwise.\n",
assert(((void)"210 is the answer but the function says otherwise.\n", t == 210));
t == 210)); std::cout << "Fourth test passes." << std::endl;
std::cout << "Fourth test passes." << std::endl;
} }
/** /**
@ -76,6 +78,6 @@ static void test() {
* @returns 0 on exit * @returns 0 on exit
*/ */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test(); // executing tests test(); // executing tests
return 0; return 0;
} }

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
@ -16,52 +18,49 @@
*/ */
namespace math { namespace math {
/** /**
* Function to calculate sum of binomial coefficients * Function to calculate sum of binomial coefficients
* @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); }
}
} // namespace math } // namespace math
/** /**
* Function for testing binomialCoeffSum function. * Function for testing binomialCoeffSum function.
* 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;
int test_case_2 = math::binomialCoeffSum(3);
int test_case_2 = math::binomialCoeffSum(3); assert(test_case_2 == 8);
assert(test_case_2==8); std::cout << "Test_case_2 Passed!" << std::endl;
std::cout<<"Test_case_2 Passed!"<<std::endl;
int test_case_3 = math::binomialCoeffSum(4);
int test_case_3 = math::binomialCoeffSum(4); assert(test_case_3 == 16);
assert(test_case_3==16); std::cout << "Test_case_3 Passed!" << std::endl;
std::cout<<"Test_case_3 Passed!"<<std::endl;
int test_case_4 = math::binomialCoeffSum(5);
int test_case_4 = math::binomialCoeffSum(5); assert(test_case_4 == 32);
assert(test_case_4==32); std::cout << "Test_case_4 Passed!" << std::endl;
std::cout<<"Test_case_4 Passed!"<<std::endl;
int test_case_5 = math::binomialCoeffSum(7);
int test_case_5 = math::binomialCoeffSum(7); assert(test_case_5 == 128);
assert(test_case_5==128); std::cout << "Test_case_5 Passed!" << std::endl;
std::cout<<"Test_case_5 Passed!"<<std::endl; }
}
/** /**
* @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

@ -5,7 +5,7 @@
* method * method
* *
* \details * \details
* First, multiple intervals are selected with the interval gap provided. * First, multiple intervals are selected with the interval gap provided.
* Separate recursive function called for every root. * Separate recursive function called for every root.
* Roots are printed Separatelt. * Roots are printed Separatelt.
* *
@ -22,8 +22,8 @@
* \author Unknown author * \author Unknown author
* \author [Samruddha Patil](https://github.com/sampatil578) * \author [Samruddha Patil](https://github.com/sampatil578)
*/ */
#include <cmath> /// for math operations #include <cmath> /// for math operations
#include <iostream> /// for io operations #include <iostream> /// for io operations
/** /**
* @namespace numerical_methods * @namespace numerical_methods
@ -37,93 +37,92 @@ namespace numerical_methods {
*/ */
namespace false_position { namespace false_position {
/** /**
* @brief This function gives the 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). * @param x value for which we have to find value of f(x).
* @return value of f(x) for given x. * @return value of f(x) for given x.
*/ */
static float eq(float 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 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.
*/ */
static float regula_falsi(float x1,float x2,float y1,float y2){ static float regula_falsi(float x1, float x2, float y1, float y2) {
float diff = x1-x2; float diff = x1 - x2;
if(diff<0){ if (diff < 0) {
diff= (-1)*diff; diff = (-1) * diff;
} }
if(diff<0.00001){ if (diff < 0.00001) {
if (y1<0) { if (y1 < 0) {
y1=-y1; y1 = -y1;
} }
if (y2<0) { if (y2 < 0) {
y2=-y2; y2 = -y2;
} }
if (y1<y2) { if (y1 < y2) {
return x1; return x1;
} } else {
else {
return x2; return x2;
} }
} }
float x3=0,y3=0; float x3 = 0, y3 = 0;
x3 = x1 - (x1-x2)*(y1)/(y1-y2); x3 = x1 - (x1 - x2) * (y1) / (y1 - y2);
y3 = eq(x3); y3 = eq(x3);
return regula_falsi(x2,x3,y2,y3); return regula_falsi(x2, x3, y2, y3);
} }
/** /**
* @brief This function prints roots of the equation. * @brief This function prints roots of the equation.
* @param root which we have to print. * @param root which we have to print.
* @param count which is count of the root in an interval [-range,range]. * @param count which is count of the root in an interval [-range,range].
*/ */
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
*/ */
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 =
float gap = 0.5; // interval gap. lesser the gap more the accuracy 100000; // Range in which we have to find the root. (-range,range)
a = numerical_methods::false_position::eq((-1)*range); float gap = 0.5; // interval gap. lesser the gap more the accuracy
i=((-1)*range + gap); a = numerical_methods::false_position::eq((-1) * range);
//while loop for selecting proper interval in provided range and with provided interval gap. i = ((-1) * range + gap);
while(i<=range){ // while loop for selecting proper interval in provided range and with
// provided interval gap.
while (i <= range) {
b = numerical_methods::false_position::eq(i); b = numerical_methods::false_position::eq(i);
if(b==0){ if (b == 0) {
count++; count++;
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);
} }
a=b; a = b;
i+=gap; i += gap;
} }
return 0; return 0;
} }

View File

@ -1,38 +1,36 @@
/** /**
* @{ * @{
* \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)
* *
* \details * \details
* It solves the unknown value of y * It solves the unknown value of y
* for a given value of x * for a given value of x
* only first order differential equations * only first order differential equations
* can be solved * can be solved
* \example * \example
* it solves \frac{\mathrm{d} y}{\mathrm{d} x}= \frac{\left ( x-y \right )}{2} * it solves \frac{\mathrm{d} y}{\mathrm{d} x}= \frac{\left ( x-y \right )}{2}
* given x for given initial * given x for given initial
* conditions * conditions
* There can be many such equations * There can be many such equations
*/ */
#include <iostream> /// for io operations #include <cassert> /// asserting the test functions
#include <vector> /// for using the vector container #include <iostream> /// for io operations
#include <cassert> /// asserting the test functions #include <vector> /// for using the vector container
/** /**
* @brief The change() function is used * @brief The change() function is used
* to return the updated iterative value corresponding * to return the updated iterative value corresponding
* to the given function * to the given function
* @param x is the value corresponding to the x coordinate * @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 * @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,95 +39,95 @@ 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
// k1, k2, k3, k4 are the Runge Kutta variables
// used for calculation of y at each iteration
auto n = static_cast<uint64_t>((x - init_x) / h);
// used a vector container for the variables
std::vector<double> 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; // n calucates the number of iterations
} // k1, k2, k3, k4 are the Runge Kutta variables
} // namespace runge_kutta // used for calculation of y at each iteration
} // namespace numerical_methods
auto n = static_cast<uint64_t>((x - init_x) / h);
// used a vector container for the variables
std::vector<double> 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. * @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";
assert(valfirst==3.10363932323749570); double valfirst = numerical_methods::runge_kutta::rungeKutta(
std::cout << "Passed Test 1\n"; 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"; std::cout << "Test 2...."
double valsec=numerical_methods::runge_kutta::rungeKutta(1,2,5,0.1); // The value of step changed << "\n";
assert(valsec==3.40600589380261409); double valsec = numerical_methods::runge_kutta::rungeKutta(
std::cout << "Passed Test 2\n"; 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 * @brief Main function
* @returns 0 on exit * @returns 0 on exit
*/ */
int main() int main() {
{ test(); // Execute the tests
return 0;
test(); // Execute the tests }
return 0;
}

View File

@ -1,19 +1,22 @@
/** /**
* @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)
*/ */
#include <algorithm> /// for std::is_sorted, std::swap #include <algorithm> /// for std::is_sorted, std::swap
#include <cassert> /// for assert #include <cassert> /// for assert
#include <iostream> /// for io operations #include <iostream> /// for io operations
#include <vector> /// for std::vector #include <vector> /// for std::vector
/** /**
* @namespace sorting * @namespace sorting
@ -22,9 +25,10 @@
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 {
/** /**
* @brief The main function implements cycleSort * @brief The main function implements cycleSort
* @tparam T type of array * @tparam T type of array
@ -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) {
@ -71,18 +76,19 @@ std::vector<T> cycleSort(const std::vector<T> &in_arr) {
} }
return arr; return arr;
} }
} // namespace cycle_sort } // namespace cycle_sort
} // namespace sorting } // namespace sorting
/** /**
* @brief Test implementations * @brief Test implementations
* @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);
assert(std::is_sorted(std::begin(arr1), std::end(arr1))); assert(std::is_sorted(std::begin(arr1), std::end(arr1)));
std::cout << "passed" << std::endl; std::cout << "passed" << std::endl;

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
@ -21,76 +20,79 @@
* *
* using count sort at each step, which is stable. * using count sort at each step, which is stable.
* stable => already sorted according to previous digits. * stable => already sorted according to previous digits.
*/ */
/// header files /// header files
#include <algorithm> /// for collection of functions
#include <cassert> /// for a macro called assert which can be used to verify assumptions
#include <iostream> /// for io operations #include <iostream> /// for io operations
#include <vector> /// for std::vector #include <vector> /// for std::vector
#include <algorithm> /// for collection of functions
#include <cassert> /// for a macro called assert which can be used to verify assumptions
/** /**
* @namespace sorting * @namespace sorting
* @brief Sorting algorithms * @brief Sorting algorithms
*/ */
namespace sorting { namespace sorting {
/** /**
* @namespace radix_sort * @namespace radix_sort
* @brief Functions for [Radix sort](https://en.wikipedia.org/wiki/Radix_sort) * @brief Functions for [Radix sort](https://en.wikipedia.org/wiki/Radix_sort)
* algorithm * algorithm
*/ */
namespace radix_sort { namespace radix_sort {
/** /**
* @brief Function to sort vector according to current digit using stable * @brief Function to sort vector according to current digit using stable
* sorting. * sorting.
* @param cur_digit - sort according to the cur_digit * @param cur_digit - sort according to the cur_digit
* @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(
int n = ar.size(); uint16_t cur_digit,
std::vector<uint32_t> position(10, 0); const std::vector<uint64_t>& ar) { // sorting according to current digit.
for (int i = 0; i < n; ++i) { int n = ar.size();
position[(ar[i] / cur_digit) % std::vector<uint32_t> position(10, 0);
10]++; // counting frequency of 0-9 at cur_digit. for (int i = 0; i < n; ++i) {
} position[(ar[i] / cur_digit) %
int cur = 0; 10]++; // counting frequency of 0-9 at cur_digit.
for (int i = 0; i < 10; ++i) { }
int a = position[i]; int cur = 0;
position[i] = cur; // assingning starting position of 0-9. for (int i = 0; i < 10; ++i) {
cur += a; int a = position[i];
} position[i] = cur; // assingning starting position of 0-9.
std::vector<uint64_t> temp(n); cur += a;
for (int i = 0; i < n; ++i) { }
temp[position[(ar[i] / cur_digit) % 10]] = std::vector<uint64_t> temp(n);
ar[i]; // storing ar[i] in ar[i]'s cur_digit expected position of for (int i = 0; i < n; ++i) {
// this step. temp[position[(ar[i] / cur_digit) % 10]] =
position[(ar[i] / cur_digit) % ar[i]; // storing ar[i] in ar[i]'s cur_digit expected position of
10]++; // incrementing ar[i]'s cur_digit position by 1, as // this step.
// current place used by ar[i]. position[(ar[i] / cur_digit) %
} 10]++; // incrementing ar[i]'s cur_digit position by 1, as
return temp; // 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 * @brief Function to sort vector digit by digit.
*/ * @param ar - vector to be sorted
std::vector<uint64_t> radix(const std::vector<uint64_t>& ar) { * @returns sorted vector
uint64_t max_ele = *max_element(ar.begin(), ar.end()); // returns the max element. */
std::vector<uint64_t> temp = ar; std::vector<uint64_t> radix(const std::vector<uint64_t>& ar) {
for (int i = 1; max_ele / i > 0; uint64_t max_ele =
i *= 10) { // loop breaks when i > max_ele because no further digits *max_element(ar.begin(), ar.end()); // returns the max element.
// left to makes changes in aray. std::vector<uint64_t> temp = ar;
temp = step_ith(i,temp); for (int i = 1; max_ele / i > 0;
} i *= 10) { // loop breaks when i > max_ele because no further digits
for (uint64_t i : temp) { // left to makes changes in aray.
std::cout << i << " "; temp = step_ith(i, temp);
} }
std::cout << "\n"; for (uint64_t i : temp) {
return temp; std::cout << i << " ";
} }
} // namespace radix_sort std::cout << "\n";
return temp;
}
} // namespace radix_sort
} // namespace sorting } // namespace sorting
/** /**
@ -104,7 +106,7 @@ static void tests() {
assert(std::is_sorted(ar1.begin(), ar1.end())); assert(std::is_sorted(ar1.begin(), ar1.end()));
/// Test 2 /// Test 2
std::vector<uint64_t> ar2 = {213, 3214, 123, 111, 112, 142, std::vector<uint64_t> ar2 = {213, 3214, 123, 111, 112, 142,
133, 132, 32, 12, 113}; 133, 132, 32, 12, 113};
ar2 = sorting::radix_sort::radix(ar2); ar2 = sorting::radix_sort::radix(ar2);
assert(std::is_sorted(ar2.begin(), ar2.end())); assert(std::is_sorted(ar2.begin(), ar2.end()));
} }

View File

@ -17,89 +17,86 @@
* 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
* @brief Sorting algorithms * @brief Sorting algorithms
*/ */
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 {
/** /**
* *
* @brief Function used for sorting the elements in wave form. * @brief Function used for sorting the elements in wave form.
* @details * @details
* Checking whether the even indexed elements are greater than * Checking whether the even indexed elements are greater than
* their adjacent odd elements. * their adjacent odd elements.
* Traversing all even indexed elements of the input arr. * 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 previous odd element, swap them.
* If current element is smaller than the next odd element, swap them. * If current element is smaller than the next odd element, swap them.
* *
* @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,
std::vector<T> wiggleSort(const std::vector<T>& arr) { // etc
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
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. // 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
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. * @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: ";
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,11 +104,10 @@ 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);
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; d = float(std::rand() % 1000 - 500) / 100.f;
} }
@ -119,12 +115,12 @@ 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 */