feat: Add ncr mod p code (#1325)

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

* Update math/ncr_modulo_p.cpp

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

* Added all functions inside a class + added more asserts

* updating DIRECTORY.md

* clang-format and clang-tidy fixes for f6df24a5

* Replace int64_t to uint64_t + add namespace + detailed documentation

* clang-format and clang-tidy fixes for e09a0579

* Add extra namespace + add const& in function arguments

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

* Update ncr_modulo_p.cpp

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

* Update math/ncr_modulo_p.cpp

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

* Update math/ncr_modulo_p.cpp

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

* Update math/ncr_modulo_p.cpp

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

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

* updating DIRECTORY.md

* clang-format and clang-tidy fixes for a8401d4b

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

View File

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

View File

@ -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";

View File

@ -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

View File

@ -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];
}
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
/**

View File

@ -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);

View File

@ -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
View File

@ -0,0 +1,150 @@
/**
* @file
* @brief This program aims at calculating [nCr modulo
* p](https://cp-algorithms.com/combinatorics/binomial-coefficients.html).
* @details nCr is defined as n! / (r! * (n-r)!) where n! represents factorial
* of n. In many cases, the value of nCr is too large to fit in a 64 bit
* integer. Hence, in competitive programming, there are many problems or
* subproblems to compute nCr modulo p where p is a given number.
* @author [Kaustubh Damania](https://github.com/KaustubhDamania)
*/
#include <cassert> /// for assert
#include <iostream> /// for io operations
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace ncr_modulo_p
* @brief Functions for [nCr modulo
* p](https://cp-algorithms.com/combinatorics/binomial-coefficients.html)
* implementation.
*/
namespace ncr_modulo_p {
/**
* @brief Class which contains all methods required for calculating nCr mod p
*/
class NCRModuloP {
private:
std::vector<uint64_t> fac{}; /// stores precomputed factorial(i) % p value
uint64_t p = 0; /// the p from (nCr % p)
public:
/** Constructor which precomputes the values of n! % mod from n=0 to size
* and stores them in vector 'fac'
* @params[in] the numbers 'size', 'mod'
*/
NCRModuloP(const uint64_t& size, const uint64_t& mod) {
p = mod;
fac = std::vector<uint64_t>(size);
fac[0] = 1;
for (int i = 1; i <= size; i++) {
fac[i] = (fac[i - 1] * i) % p;
}
}
/** Finds the value of x, y such that a*x + b*y = gcd(a,b)
*
* @params[in] the numbers 'a', 'b' and address of 'x' and 'y' from above
* equation
* @returns the gcd of a and b
*/
uint64_t gcdExtended(const uint64_t& a, const uint64_t& b, int64_t* x,
int64_t* y) {
if (a == 0) {
*x = 0, *y = 1;
return b;
}
int64_t x1 = 0, y1 = 0;
uint64_t gcd = gcdExtended(b % a, a, &x1, &y1);
*x = y1 - (b / a) * x1;
*y = x1;
return gcd;
}
/** Find modular inverse of a with m i.e. a number x such that (a*x)%m = 1
*
* @params[in] the numbers 'a' and 'm' from above equation
* @returns the modular inverse of a
*/
int64_t modInverse(const uint64_t& a, const uint64_t& m) {
int64_t x = 0, y = 0;
uint64_t g = gcdExtended(a, m, &x, &y);
if (g != 1) { // modular inverse doesn't exist
return -1;
} else {
int64_t res = ((x + m) % m);
return res;
}
}
/** Find nCr % p
*
* @params[in] the numbers 'n', 'r' and 'p'
* @returns the value nCr % p
*/
int64_t ncr(const uint64_t& n, const uint64_t& r, const uint64_t& p) {
// Base cases
if (r > n) {
return 0;
}
if (r == 1) {
return n % p;
}
if (r == 0 || r == n) {
return 1;
}
// fac is a global array with fac[r] = (r! % p)
int64_t denominator = modInverse(fac[r], p);
if (denominator < 0) { // modular inverse doesn't exist
return -1;
}
denominator = (denominator * modInverse(fac[n - r], p)) % p;
if (denominator < 0) { // modular inverse doesn't exist
return -1;
}
return (fac[n] * denominator) % p;
}
};
} // namespace ncr_modulo_p
} // namespace math
/**
* @brief Test implementations
* @param ncrObj object which contains the precomputed factorial values and
* ncr function
* @returns void
*/
static void tests(math::ncr_modulo_p::NCRModuloP ncrObj) {
// (52323 C 26161) % (1e9 + 7) = 224944353
assert(ncrObj.ncr(52323, 26161, 1000000007) == 224944353);
// 6 C 2 = 30, 30%5 = 0
assert(ncrObj.ncr(6, 2, 5) == 0);
// 7C3 = 35, 35 % 29 = 8
assert(ncrObj.ncr(7, 3, 29) == 6);
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
// populate the fac array
const uint64_t size = 1e6 + 1;
const uint64_t p = 1e9 + 7;
math::ncr_modulo_p::NCRModuloP ncrObj =
math::ncr_modulo_p::NCRModuloP(size, p);
// test 6Ci for i=0 to 7
for (int i = 0; i <= 7; i++) {
std::cout << 6 << "C" << i << " = " << ncrObj.ncr(6, i, p) << "\n";
}
tests(ncrObj); // execute the tests
std::cout << "Assertions passed\n";
return 0;
}

View File

@ -1,14 +1,16 @@
/**
* @file
* @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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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()));
}

View File

@ -17,89 +17,86 @@
* arr = [2,8,9,1,7], after wiggle sort arr will become equal to [8,2,9,1,7]
*/
#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 */