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