Skip to content

[pull] master from TheAlgorithms:master #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions data_structures/segment_tree.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* @file
* @brief A data structure to quickly do operations on ranges: the [Segment Tree](https://en.wikipedia.org/wiki/Segment_tree) algorithm implementation
* @details
* Implementation of the segment tree data structre
*
* Can do point updates (updates the value of some position)
* and range queries, where it gives the value of some associative
* opperation done on a range
*
* Both of these operations take O(log N) time
* @author [Nishant Chatterjee](https://github.com/nishantc1527)
*/

#include <iostream> /// For IO operations
#include <vector> /// For std::vector
#include <algorithm> /// For std::min and std::max
#include <cassert> /// For assert

/*
* @namespace
* @brief Data structures
*/
namespace data_structures {
/**
* @brief class representation of the segment tree
* @tparam T The type of the class that goes in the datastructure
*/
template <class T>
class SegmentTree {
private:
const T ID = 0; ///< Comb(ID, x) = x
std::vector<T> t; ///< Vector to represent the tree
int size = 0; ///< Number of elements available for querying in the tree
private:
/**
* @brief Any associative function that combines x and y
* @param x The first operand
* @param y The second operand
* @return Some associative operation applied to these two values. In this case, I used addition
*/
T comb(T x, T y) {
return x + y;
}
/**
* @brief Gives the midpoint between two integers
* @param l The left endpoint
* @param r The right endpoint
* @return the middle point between them
*/
int mid(int l, int r) {
return l + (r - l) / 2;
}
/**
* @brief Helper method for update method below
* @param i The index of the current node
* @param l The leftmost node of the current node
* @param r The rightmost node of the current node
* @param pos The position to update
* @param val The value to update it to
*/
void update(int i, int l, int r, int pos, T val) {
if(l == r) t[i] = val;
else {
int m = mid(l, r);
if(pos <= m) update(i * 2, l, m, pos, val);
else update(i * 2 + 1, m + 1, r, pos, val);
t[i] = comb(t[i * 2], t[i * 2 + 1]);
}
}
/**
* @brief Helper method for range_comb method below
* @param i The current node
* @param l The leftmost node of the current node
* @param r The rightmost node of the current node
* @param tl The left endpoint of the range
* @param tr The right endpoint of the range
* @return The comb operation applied to all values between tl and tr
*/
T range_comb(int i, int l, int r, int tl, int tr) {
if(l == tl && r == tr) return t[i];
if(tl > tr) return 0;
int m = mid(l, r);
return comb(range_comb(i * 2, l, m, tl, std::min(tr, m)), range_comb(i * 2 + 1, m + 1, r, std::max(tl, m + 1), tr));
}
public:
SegmentTree(int n) : t(n * 4, ID), size(n) {}
/**
* @brief Updates a value at a certain position
* @param pos The position to update
* @param val The value to update it to
*/
void update(int pos, T val) {
update(1, 1, size, pos, val);
}
/**
* @brief Returns comb across all values between l and r
* @param l The left endpoint of the range
* @param r The right endpoint of the range
* @return The value of the comb operations
*/
T range_comb(int l, int r) {
return range_comb(1, 1, size, l, r);
}
};
} // namespace data_structures

/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
data_structures::SegmentTree<int> t(5);
t.update(1, 1);
t.update(2, 2);
t.update(3, 3);
t.update(4, 4);
t.update(5, 5);
assert(t.range_comb(1, 3) == 6); // 1 + 2 + 3 = 6
t.update(1, 3);
assert(t.range_comb(1, 3) == 8); // 3 + 2 + 3 = 8

std::cout << "All tests have successfully passed!\n";
}

/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
68 changes: 44 additions & 24 deletions math/eulers_totient_function.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/**
* @file
* @brief C++ Program to find
* [Euler's Totient](https://en.wikipedia.org/wiki/Euler%27s_totient_function)
* function
*
* @brief Implementation of [Euler's Totient](https://en.wikipedia.org/wiki/Euler%27s_totient_function)
* @description
* Euler Totient Function is also known as phi function.
* \f[\phi(n) =
* \phi\left({p_1}^{a_1}\right)\cdot\phi\left({p_2}^{a_2}\right)\ldots\f] where
Expand All @@ -23,36 +21,58 @@
* * \f$\phi(1) = 1\f$
* * \f$\phi(17501) = 15120\f$
* * \f$\phi(1420) = 560\f$
* @author [Mann Mehta](https://github.com/mann2108)
*/
#include <cstdlib>
#include <iostream>

/** Function to caculate Euler's totient phi
#include <iostream> /// for IO operations
#include <cassert> /// for assert

/**
* @brief Mathematical algorithms
* @namespace
*/
namespace math {
/**
* @brief Function to calculate Euler's Totient
* @param n the number to find the Euler's Totient of
*/
uint64_t phiFunction(uint64_t n) {
uint64_t result = n;
for (uint64_t i = 2; i * i <= n; i++) {
if (n % i == 0) {
while (n % i == 0) {
n /= i;
}
result -= result / i;
}
if (n % i != 0) continue;
while (n % i == 0) n /= i;

result -= result / i;
}
if (n > 1)
result -= result / n;
if (n > 1) result -= result / n;

return result;
}
} // namespace math

/// Main function
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
assert(math::phiFunction(1) == 1);
assert(math::phiFunction(2) == 1);
assert(math::phiFunction(10) == 4);
assert(math::phiFunction(123456) == 41088);
assert(math::phiFunction(808017424794) == 263582333856);
assert(math::phiFunction(3141592) == 1570792);
assert(math::phiFunction(27182818) == 12545904);

std::cout << "All tests have successfully passed!\n";
}

/**
* @brief Main function
* @param argc commandline argument count (ignored)
* @param argv commandline array of arguments (ignored)
* @returns 0 on exit
*/
int main(int argc, char *argv[]) {
uint64_t n;
if (argc < 2) {
std::cout << "Enter the number: ";
} else {
n = strtoull(argv[1], nullptr, 10);
}
std::cin >> n;
std::cout << phiFunction(n);
test();
return 0;
}
Loading