mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Merge branch 'master' into fix/codeql-warnings
This commit is contained in:
commit
4d357c468f
66
.vscode/settings.json
vendored
66
.vscode/settings.json
vendored
@ -1,6 +1,64 @@
|
||||
{
|
||||
"C_Cpp.clang_format_style": "{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, AlignConsecutiveMacros: true }",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.formatOnPaste": true
|
||||
"C_Cpp.clang_format_style": "{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, AlignConsecutiveMacros: true }",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"cctype": "cpp",
|
||||
"chrono": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"complex": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"map": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"set": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"fstream": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp"
|
||||
}
|
||||
}
|
||||
|
@ -2,75 +2,131 @@
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||
identity and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the overall
|
||||
community
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||
any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Publishing others' private information, such as a physical or email address,
|
||||
without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at 1anuppanwar@gmail.com, dynamitechetan@gmail.com, nikhilkala8@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
reported to the community leaders responsible for enforcement at
|
||||
hello@the-algorithms.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series of
|
||||
actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or permanent
|
||||
ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||
community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.1, available at
|
||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||
[https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
<https://www.contributor-covenant.org/faq>
|
||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||
[FAQ]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
||||
|
@ -223,12 +223,16 @@
|
||||
## Numerical Methods
|
||||
* [Bisection Method](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/bisection_method.cpp)
|
||||
* [Brent Method Extrema](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/brent_method_extrema.cpp)
|
||||
* [Composite Simpson Rule](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/composite_simpson_rule.cpp)
|
||||
* [Durand Kerner Roots](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/durand_kerner_roots.cpp)
|
||||
* [False Position](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/false_position.cpp)
|
||||
* [Fast Fourier Transform](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/fast_fourier_transform.cpp)
|
||||
* [Gaussian Elimination](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/gaussian_elimination.cpp)
|
||||
* [Golden Search Extrema](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/golden_search_extrema.cpp)
|
||||
* [Inverse Fast Fourier Transform](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/inverse_fast_fourier_transform.cpp)
|
||||
* [Lu Decompose](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/lu_decompose.cpp)
|
||||
* [Lu Decomposition](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/lu_decomposition.h)
|
||||
* [Midpoint Integral Method](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/midpoint_integral_method.cpp)
|
||||
* [Newton Raphson Method](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/newton_raphson_method.cpp)
|
||||
* [Ode Forward Euler](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/ode_forward_euler.cpp)
|
||||
* [Ode Midpoint Euler](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/ode_midpoint_euler.cpp)
|
||||
|
@ -1,22 +1,23 @@
|
||||
/**
|
||||
* @brief Check whether a given graph is bipartite or not
|
||||
* @details
|
||||
* A bipartite graph is the one whose nodes can be divided into two
|
||||
* disjoint sets in such a way that the nodes in a set are not
|
||||
* connected to each other at all, i.e. no intra-set connections.
|
||||
* The only connections that exist are that of inter-set,
|
||||
* i.e. the nodes from one set are connected to a subset of nodes
|
||||
* A bipartite graph is the one whose nodes can be divided into two
|
||||
* disjoint sets in such a way that the nodes in a set are not
|
||||
* connected to each other at all, i.e. no intra-set connections.
|
||||
* The only connections that exist are that of inter-set,
|
||||
* i.e. the nodes from one set are connected to a subset of nodes
|
||||
* in the other set.
|
||||
* In this implementation, using a graph in the form of adjacency
|
||||
* In this implementation, using a graph in the form of adjacency
|
||||
* list, check whether the given graph is a bipartite or not.
|
||||
*
|
||||
* References used: [GeeksForGeeks](https://www.geeksforgeeks.org/bipartite-graph/)
|
||||
*
|
||||
* References used:
|
||||
* [GeeksForGeeks](https://www.geeksforgeeks.org/bipartite-graph/)
|
||||
* @author [tushar2407](https://github.com/tushar2407)
|
||||
*/
|
||||
#include <iostream> /// for IO operations
|
||||
#include <queue> /// for queue data structure
|
||||
#include <vector> /// for vector data structure
|
||||
#include <cassert> /// for assert
|
||||
#include <cassert> /// for assert
|
||||
#include <iostream> /// for IO operations
|
||||
#include <queue> /// for queue data structure
|
||||
#include <vector> /// for vector data structure
|
||||
|
||||
/**
|
||||
* @namespace graph
|
||||
@ -28,62 +29,61 @@ namespace graph {
|
||||
* @param graph is a 2D matrix whose rows or the first index signify the node
|
||||
* and values in that row signify the nodes it is connected to
|
||||
* @param index is the valus of the node currently under observation
|
||||
* @param visited is the vector which stores whether a given node has been
|
||||
* @param visited is the vector which stores whether a given node has been
|
||||
* traversed or not yet
|
||||
* @returns boolean
|
||||
*/
|
||||
bool checkBipartite(
|
||||
const std::vector<std::vector<int64_t>> &graph,
|
||||
int64_t index,
|
||||
std::vector<int64_t> *visited
|
||||
)
|
||||
{
|
||||
std::queue<int64_t> q; ///< stores the neighbouring node indexes in squence
|
||||
/// of being reached
|
||||
q.push(index); /// insert the current node into the queue
|
||||
(*visited)[index] = 1; /// mark the current node as travelled
|
||||
while(q.size())
|
||||
{
|
||||
bool checkBipartite(const std::vector<std::vector<int64_t>> &graph,
|
||||
int64_t index, std::vector<int64_t> *visited) {
|
||||
std::queue<int64_t> q; ///< stores the neighbouring node indexes in squence
|
||||
/// of being reached
|
||||
q.push(index); /// insert the current node into the queue
|
||||
(*visited)[index] = 1; /// mark the current node as travelled
|
||||
while (q.size()) {
|
||||
int64_t u = q.front();
|
||||
q.pop();
|
||||
for(uint64_t i=0;i<graph[u].size();i++)
|
||||
{
|
||||
int64_t v = graph[u][i]; ///< stores the neighbour of the current node
|
||||
if(!(*visited)[v]) /// check whether the neighbour node is
|
||||
/// travelled already or not
|
||||
for (uint64_t i = 0; i < graph[u].size(); i++) {
|
||||
int64_t v =
|
||||
graph[u][i]; ///< stores the neighbour of the current node
|
||||
if (!(*visited)[v]) /// check whether the neighbour node is
|
||||
/// travelled already or not
|
||||
{
|
||||
(*visited)[v] = ((*visited)[u]==1)?-1:1; /// colour the neighbouring node with
|
||||
/// different colour than the current node
|
||||
q.push(v); /// insert the neighbouring node into the queue
|
||||
}
|
||||
else if((*visited)[v] == (*visited)[u]) /// if both the current node and its neighbour
|
||||
/// has the same state then it is not a bipartite graph
|
||||
(*visited)[v] =
|
||||
((*visited)[u] == 1)
|
||||
? -1
|
||||
: 1; /// colour the neighbouring node with
|
||||
/// different colour than the current node
|
||||
q.push(v); /// insert the neighbouring node into the queue
|
||||
} else if ((*visited)[v] ==
|
||||
(*visited)[u]) /// if both the current node and its
|
||||
/// neighbour has the same state then it
|
||||
/// is not a bipartite graph
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; /// return true when all the connected nodes of the current
|
||||
/// nodes are travelled and satisify all the above conditions
|
||||
return true; /// return true when all the connected nodes of the current
|
||||
/// nodes are travelled and satisify all the above conditions
|
||||
}
|
||||
/**
|
||||
* @brief returns true if the given graph is bipartite else returns false
|
||||
* @param graph is a 2D matrix whose rows or the first index signify the node
|
||||
* @param graph is a 2D matrix whose rows or the first index signify the node
|
||||
* and values in that row signify the nodes it is connected to
|
||||
* @returns booleans
|
||||
*/
|
||||
bool isBipartite(const std::vector<std::vector<int64_t>> &graph)
|
||||
{
|
||||
std::vector<int64_t> visited(graph.size()); ///< stores boolean values
|
||||
/// which signify whether that node had been visited or not
|
||||
|
||||
for(uint64_t i=0;i<graph.size();i++)
|
||||
{
|
||||
if(!visited[i]) /// if the current node is not visited then check
|
||||
/// whether the sub-graph of that node is a bipartite or not
|
||||
bool isBipartite(const std::vector<std::vector<int64_t>> &graph) {
|
||||
std::vector<int64_t> visited(
|
||||
graph.size()); ///< stores boolean values
|
||||
/// which signify whether that node had been visited or
|
||||
/// not
|
||||
|
||||
for (uint64_t i = 0; i < graph.size(); i++) {
|
||||
if (!visited[i]) /// if the current node is not visited then check
|
||||
/// whether the sub-graph of that node is a bipartite
|
||||
/// or not
|
||||
{
|
||||
if(!checkBipartite(graph, i, &visited))
|
||||
{
|
||||
if (!checkBipartite(graph, i, &visited)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -96,39 +96,30 @@ bool isBipartite(const std::vector<std::vector<int64_t>> &graph)
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void test()
|
||||
{
|
||||
std::vector<std::vector<int64_t>> graph = {
|
||||
{1,3},
|
||||
{0,2},
|
||||
{1,3},
|
||||
{0,2}
|
||||
};
|
||||
static void test() {
|
||||
std::vector<std::vector<int64_t>> graph = {{1, 3}, {0, 2}, {1, 3}, {0, 2}};
|
||||
|
||||
assert(graph::isBipartite(graph) == true); /// check whether the above
|
||||
/// defined graph is indeed bipartite
|
||||
assert(graph::isBipartite(graph) ==
|
||||
true); /// check whether the above
|
||||
/// defined graph is indeed bipartite
|
||||
|
||||
std::vector<std::vector<int64_t>> graph_not_bipartite = {
|
||||
{1,2,3},
|
||||
{0,2},
|
||||
{0,1,3},
|
||||
{0,2}
|
||||
};
|
||||
{1, 2, 3}, {0, 2}, {0, 1, 3}, {0, 2}};
|
||||
|
||||
assert(graph::isBipartite(graph_not_bipartite) == false); /// check whether
|
||||
/// the above defined graph is indeed bipartite
|
||||
assert(graph::isBipartite(graph_not_bipartite) ==
|
||||
false); /// check whether
|
||||
/// the above defined graph is indeed bipartite
|
||||
std::cout << "All tests have successfully passed!\n";
|
||||
}
|
||||
/**
|
||||
* @brief Main function
|
||||
* Instantitates a dummy graph of a small size with
|
||||
* Instantitates a dummy graph of a small size with
|
||||
* a few edges between random nodes.
|
||||
* On applying the algorithm, it checks if the instantiated
|
||||
* On applying the algorithm, it checks if the instantiated
|
||||
* graph is bipartite or not.
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
test(); // run self-test implementations
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,14 +9,22 @@
|
||||
/** Generate an increasingly large number of primes
|
||||
* and store in a list
|
||||
*/
|
||||
std::vector<int> primes(int max) {
|
||||
max++;
|
||||
std::vector<int> primes(size_t max) {
|
||||
std::vector<int> res;
|
||||
std::vector<bool> numbers(max, false);
|
||||
for (int i = 2; i < max; i++) {
|
||||
if (!numbers[i]) {
|
||||
for (int j = i; j < max; j += i) numbers[j] = true;
|
||||
res.push_back(i);
|
||||
std::vector<bool> is_not_prime(max + 1, false);
|
||||
for (size_t i = 2; i <= max; i++) {
|
||||
if (!is_not_prime[i]) {
|
||||
res.emplace_back(i);
|
||||
}
|
||||
for (int p : res) {
|
||||
size_t k = i * p;
|
||||
if (k > max) {
|
||||
break;
|
||||
}
|
||||
is_not_prime[k] = true;
|
||||
if (i % p == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@ -25,9 +33,9 @@ std::vector<int> primes(int max) {
|
||||
/** main function */
|
||||
int main() {
|
||||
std::cout << "Calculate primes up to:\n>> ";
|
||||
int n;
|
||||
int n = 0;
|
||||
std::cin >> n;
|
||||
std::vector<int> ans = primes(n);
|
||||
for (int i = 0; i < ans.size(); i++) std::cout << ans[i] << ' ';
|
||||
for (int p : ans) std::cout << p << ' ';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
202
numerical_methods/composite_simpson_rule.cpp
Normal file
202
numerical_methods/composite_simpson_rule.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of the Composite Simpson Rule for the approximation
|
||||
*
|
||||
* @details The following is an implementation of the Composite Simpson Rule for
|
||||
* the approximation of definite integrals. More info -> wiki:
|
||||
* https://en.wikipedia.org/wiki/Simpson%27s_rule#Composite_Simpson's_rule
|
||||
*
|
||||
* The idea is to split the interval in an EVEN number N of intervals and use as
|
||||
* interpolation points the xi for which it applies that xi = x0 + i*h, where h
|
||||
* is a step defined as h = (b-a)/N where a and b are the first and last points
|
||||
* of the interval of the integration [a, b].
|
||||
*
|
||||
* We create a table of the xi and their corresponding f(xi) values and we
|
||||
* evaluate the integral by the formula: I = h/3 * {f(x0) + 4*f(x1) + 2*f(x2) +
|
||||
* ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)}
|
||||
*
|
||||
* That means that the first and last indexed i f(xi) are multiplied by 1,
|
||||
* the odd indexed f(xi) by 4 and the even by 2.
|
||||
*
|
||||
* In this program there are 4 sample test functions f, g, k, l that are
|
||||
* evaluated in the same interval.
|
||||
*
|
||||
* Arguments can be passed as parameters from the command line argv[1] = N,
|
||||
* argv[2] = a, argv[3] = b
|
||||
*
|
||||
* N must be even number and a<b.
|
||||
*
|
||||
* In the end of the main() i compare the program's result with the one from
|
||||
* mathematical software with 2 decimal points margin.
|
||||
*
|
||||
* Add sample function by replacing one of the f, g, k, l and the assert
|
||||
*
|
||||
* @author [ggkogkou](https://github.com/ggkogkou)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cassert> /// for assert
|
||||
#include <cmath> /// for math functions
|
||||
#include <cstdint> /// for integer allocation
|
||||
#include <cstdlib> /// for std::atof
|
||||
#include <functional> /// for std::function
|
||||
#include <iostream> /// for IO operations
|
||||
#include <map> /// for std::map container
|
||||
|
||||
/**
|
||||
* @namespace numerical_methods
|
||||
* @brief Numerical algorithms/methods
|
||||
*/
|
||||
namespace numerical_methods {
|
||||
/**
|
||||
* @namespace simpson_method
|
||||
* @brief Contains the Simpson's method implementation
|
||||
*/
|
||||
namespace simpson_method {
|
||||
/**
|
||||
* @fn double evaluate_by_simpson(int N, double h, double a,
|
||||
* std::function<double (double)> func)
|
||||
* @brief Calculate integral or assert if integral is not a number (Nan)
|
||||
* @param N number of intervals
|
||||
* @param h step
|
||||
* @param a x0
|
||||
* @param func: choose the function that will be evaluated
|
||||
* @returns the result of the integration
|
||||
*/
|
||||
double evaluate_by_simpson(std::int32_t N, double h, double a,
|
||||
std::function<double(double)> func) {
|
||||
std::map<std::int32_t, double>
|
||||
data_table; // Contains the data points. key: i, value: f(xi)
|
||||
double xi = a; // Initialize xi to the starting point x0 = a
|
||||
|
||||
// Create the data table
|
||||
double temp;
|
||||
for (std::int32_t i = 0; i <= N; i++) {
|
||||
temp = func(xi);
|
||||
data_table.insert(
|
||||
std::pair<std::int32_t, double>(i, temp)); // add i and f(xi)
|
||||
xi += h; // Get the next point xi for the next iteration
|
||||
}
|
||||
|
||||
// Evaluate the integral.
|
||||
// Remember: f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)
|
||||
double evaluate_integral = 0;
|
||||
for (std::int32_t i = 0; i <= N; i++) {
|
||||
if (i == 0 || i == N)
|
||||
evaluate_integral += data_table.at(i);
|
||||
else if (i % 2 == 1)
|
||||
evaluate_integral += 4 * data_table.at(i);
|
||||
else
|
||||
evaluate_integral += 2 * data_table.at(i);
|
||||
}
|
||||
|
||||
// Multiply by the coefficient h/3
|
||||
evaluate_integral *= h / 3;
|
||||
|
||||
// If the result calculated is nan, then the user has given wrong input
|
||||
// interval.
|
||||
assert(!std::isnan(evaluate_integral) &&
|
||||
"The definite integral can't be evaluated. Check the validity of "
|
||||
"your input.\n");
|
||||
// Else return
|
||||
return evaluate_integral;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn double f(double x)
|
||||
* @brief A function f(x) that will be used to test the method
|
||||
* @param x The independent variable xi
|
||||
* @returns the value of the dependent variable yi = f(xi)
|
||||
*/
|
||||
double f(double x) { return std::sqrt(x) + std::log(x); }
|
||||
/** @brief Another test function */
|
||||
double g(double x) { return std::exp(-x) * (4 - std::pow(x, 2)); }
|
||||
/** @brief Another test function */
|
||||
double k(double x) { return std::sqrt(2 * std::pow(x, 3) + 3); }
|
||||
/** @brief Another test function*/
|
||||
double l(double x) { return x + std::log(2 * x + 1); }
|
||||
} // namespace simpson_method
|
||||
} // namespace numerical_methods
|
||||
|
||||
/**
|
||||
* \brief Self-test implementations
|
||||
* @param N is the number of intervals
|
||||
* @param h is the step
|
||||
* @param a is x0
|
||||
* @param b is the end of the interval
|
||||
* @param used_argv_parameters is 'true' if argv parameters are given and
|
||||
* 'false' if not
|
||||
*/
|
||||
static void test(std::int32_t N, double h, double a, double b,
|
||||
bool used_argv_parameters) {
|
||||
// Call the functions and find the integral of each function
|
||||
double result_f = numerical_methods::simpson_method::evaluate_by_simpson(
|
||||
N, h, a, numerical_methods::simpson_method::f);
|
||||
assert((used_argv_parameters || (result_f >= 4.09 && result_f <= 4.10)) &&
|
||||
"The result of f(x) is wrong");
|
||||
std::cout << "The result of integral f(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_f << std::endl;
|
||||
|
||||
double result_g = numerical_methods::simpson_method::evaluate_by_simpson(
|
||||
N, h, a, numerical_methods::simpson_method::g);
|
||||
assert((used_argv_parameters || (result_g >= 0.27 && result_g <= 0.28)) &&
|
||||
"The result of g(x) is wrong");
|
||||
std::cout << "The result of integral g(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_g << std::endl;
|
||||
|
||||
double result_k = numerical_methods::simpson_method::evaluate_by_simpson(
|
||||
N, h, a, numerical_methods::simpson_method::k);
|
||||
assert((used_argv_parameters || (result_k >= 9.06 && result_k <= 9.07)) &&
|
||||
"The result of k(x) is wrong");
|
||||
std::cout << "The result of integral k(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_k << std::endl;
|
||||
|
||||
double result_l = numerical_methods::simpson_method::evaluate_by_simpson(
|
||||
N, h, a, numerical_methods::simpson_method::l);
|
||||
assert((used_argv_parameters || (result_l >= 7.16 && result_l <= 7.17)) &&
|
||||
"The result of l(x) is wrong");
|
||||
std::cout << "The result of integral l(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_l << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
std::int32_t N = 16; /// Number of intervals to divide the integration
|
||||
/// interval. MUST BE EVEN
|
||||
double a = 1, b = 3; /// Starting and ending point of the integration in
|
||||
/// the real axis
|
||||
double h; /// Step, calculated by a, b and N
|
||||
|
||||
bool used_argv_parameters =
|
||||
false; // If argv parameters are used then the assert must be omitted
|
||||
// for the tst cases
|
||||
|
||||
// Get user input (by the command line parameters or the console after
|
||||
// displaying messages)
|
||||
if (argc == 4) {
|
||||
N = std::atoi(argv[1]);
|
||||
a = (double)std::atof(argv[2]);
|
||||
b = (double)std::atof(argv[3]);
|
||||
// Check if a<b else abort
|
||||
assert(a < b && "a has to be less than b");
|
||||
assert(N > 0 && "N has to be > 0");
|
||||
if (N < 16 || a != 1 || b != 3)
|
||||
used_argv_parameters = true;
|
||||
std::cout << "You selected N=" << N << ", a=" << a << ", b=" << b
|
||||
<< std::endl;
|
||||
} else
|
||||
std::cout << "Default N=" << N << ", a=" << a << ", b=" << b
|
||||
<< std::endl;
|
||||
|
||||
// Find the step
|
||||
h = (b - a) / N;
|
||||
|
||||
test(N, h, a, b, used_argv_parameters); // run self-test implementations
|
||||
|
||||
return 0;
|
||||
}
|
165
numerical_methods/fast_fourier_transform.cpp
Normal file
165
numerical_methods/fast_fourier_transform.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief [A fast Fourier transform
|
||||
* (FFT)](https://medium.com/@aiswaryamathur/understanding-fast-fouriertransform-from-scratch-to-solve-polynomial-multiplication-8018d511162f)
|
||||
* is an algorithm that computes the
|
||||
* discrete Fourier transform (DFT) of a sequence, or its inverse (IDFT).
|
||||
* @details
|
||||
* This
|
||||
* algorithm has application in use case scenario where a user wants to find points of a
|
||||
* function
|
||||
* in a short time by just using the coefficients of the polynomial
|
||||
* function.
|
||||
* It can be also used to find inverse fourier transform by just switching the
|
||||
value of omega.
|
||||
* Time complexity
|
||||
* this algorithm computes the DFT in O(nlogn) time in comparison to traditional
|
||||
O(n^2).
|
||||
* @author [Ameya Chawla](https://github.com/ameyachawlaggsipu)
|
||||
*/
|
||||
|
||||
#include <cassert> /// for assert
|
||||
#include <cmath> /// for mathematical-related functions
|
||||
#include <complex> /// for storing points and coefficents
|
||||
#include <iostream> /// for IO operations
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
/**
|
||||
* @namespace numerical_methods
|
||||
* @brief Numerical algorithms/methods
|
||||
*/
|
||||
namespace numerical_methods {
|
||||
/**
|
||||
* @brief FastFourierTransform is a recursive function which returns list of
|
||||
* complex numbers
|
||||
* @param p List of Coefficents in form of complex numbers
|
||||
* @param n Count of elements in list p
|
||||
* @returns p if n==1
|
||||
* @returns y if n!=1
|
||||
*/
|
||||
std::complex<double> *FastFourierTransform(std::complex<double> *p, uint8_t n) {
|
||||
if (n == 1) {
|
||||
return p; /// Base Case To return
|
||||
}
|
||||
|
||||
double pi = 2 * asin(1.0); /// Declaring value of pi
|
||||
|
||||
std::complex<double> om = std::complex<double>(
|
||||
cos(2 * pi / n), sin(2 * pi / n)); /// Calculating value of omega
|
||||
|
||||
auto *pe = new std::complex<double>[n / 2]; /// Coefficients of even power
|
||||
|
||||
auto *po = new std::complex<double>[n / 2]; /// Coefficients of odd power
|
||||
|
||||
int k1 = 0, k2 = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
if (j % 2 == 0) {
|
||||
pe[k1++] = p[j]; /// Assigning values of even Coefficients
|
||||
|
||||
} else
|
||||
po[k2++] = p[j]; /// Assigning value of odd Coefficients
|
||||
}
|
||||
|
||||
std::complex<double> *ye =
|
||||
FastFourierTransform(pe, n / 2); /// Recursive Call
|
||||
|
||||
std::complex<double> *yo =
|
||||
FastFourierTransform(po, n / 2); /// Recursive Call
|
||||
|
||||
auto *y = new std::complex<double>[n]; /// Final value representation list
|
||||
|
||||
k1 = 0, k2 = 0;
|
||||
|
||||
for (int i = 0; i < n / 2; i++) {
|
||||
y[i] =
|
||||
ye[k1] + pow(om, i) * yo[k2]; /// Updating the first n/2 elements
|
||||
y[i + n / 2] =
|
||||
ye[k1] - pow(om, i) * yo[k2]; /// Updating the last n/2 elements
|
||||
|
||||
k1++;
|
||||
k2++;
|
||||
}
|
||||
|
||||
if(n!=2){
|
||||
|
||||
delete[] pe;
|
||||
delete[] po;
|
||||
|
||||
}
|
||||
|
||||
delete[] ye; /// Deleting dynamic array ye
|
||||
delete[] yo; /// Deleting dynamic array yo
|
||||
return y;
|
||||
}
|
||||
|
||||
} // namespace numerical_methods
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @details
|
||||
* Declaring two test cases and checking for the error
|
||||
* in predicted and true value is less than 0.000000000001.
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
/* descriptions of the following test */
|
||||
|
||||
auto *t1 = new std::complex<double>[2]; /// Test case 1
|
||||
auto *t2 = new std::complex<double>[4]; /// Test case 2
|
||||
|
||||
t1[0] = {1, 0};
|
||||
t1[1] = {2, 0};
|
||||
t2[0] = {1, 0};
|
||||
t2[1] = {2, 0};
|
||||
t2[2] = {3, 0};
|
||||
t2[3] = {4, 0};
|
||||
|
||||
uint8_t n1 = 2;
|
||||
uint8_t n2 = 4;
|
||||
std::vector<std::complex<double>> r1 = {
|
||||
{3, 0}, {-1, 0}}; /// True Answer for test case 1
|
||||
|
||||
std::vector<std::complex<double>> r2 = {
|
||||
{10, 0}, {-2, -2}, {-2, 0}, {-2, 2}}; /// True Answer for test case 2
|
||||
|
||||
std::complex<double> *o1 = numerical_methods::FastFourierTransform(t1, n1);
|
||||
std::complex<double> *t3=o1; /// Temporary variable used to delete memory location of o1
|
||||
std::complex<double> *o2 = numerical_methods::FastFourierTransform(t2, n2);
|
||||
std::complex<double> *t4=o2; /// Temporary variable used to delete memory location of o2
|
||||
for (uint8_t i = 0; i < n1; i++) {
|
||||
assert((r1[i].real() - o1->real() < 0.000000000001) &&
|
||||
(r1[i].imag() - o1->imag() <
|
||||
0.000000000001)); /// Comparing for both real and imaginary
|
||||
/// values for test case 1
|
||||
o1++;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < n2; i++) {
|
||||
assert((r2[i].real() - o2->real() < 0.000000000001) &&
|
||||
(r2[i].imag() - o2->imag() <
|
||||
0.000000000001)); /// Comparing for both real and imaginary
|
||||
/// values for test case 2
|
||||
o2++;
|
||||
}
|
||||
|
||||
|
||||
delete[] t1;
|
||||
delete[] t2;
|
||||
delete[] t3;
|
||||
delete[] t4;
|
||||
std::cout << "All tests have successfully passed!\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @param argc commandline argument count (ignored)
|
||||
* @param argv commandline array of arguments (ignored)
|
||||
* calls automated test function to test the working of fast fourier transform.
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
|
||||
int main(int argc, char const *argv[]) {
|
||||
test(); // run self-test implementations
|
||||
// with 2 defined test cases
|
||||
return 0;
|
||||
}
|
161
numerical_methods/inverse_fast_fourier_transform.cpp
Normal file
161
numerical_methods/inverse_fast_fourier_transform.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief [An inverse fast Fourier transform
|
||||
* (IFFT)](https://www.geeksforgeeks.org/python-inverse-fast-fourier-transformation/)
|
||||
* is an algorithm that computes the inverse fourier transform.
|
||||
* @details
|
||||
* This algorithm has an application in use case scenario where a user wants find coefficients of
|
||||
* a function in a short time by just using points generated by DFT.
|
||||
* Time complexity
|
||||
* this algorithm computes the IDFT in O(nlogn) time in comparison to traditional O(n^2).
|
||||
* @author [Ameya Chawla](https://github.com/ameyachawlaggsipu)
|
||||
*/
|
||||
|
||||
#include <cassert> /// for assert
|
||||
#include <cmath> /// for mathematical-related functions
|
||||
#include <complex> /// for storing points and coefficents
|
||||
#include <iostream> /// for IO operations
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
/**
|
||||
* @namespace numerical_methods
|
||||
* @brief Numerical algorithms/methods
|
||||
*/
|
||||
namespace numerical_methods {
|
||||
/**
|
||||
* @brief InverseFastFourierTransform is a recursive function which returns list of
|
||||
* complex numbers
|
||||
* @param p List of Coefficents in form of complex numbers
|
||||
* @param n Count of elements in list p
|
||||
* @returns p if n==1
|
||||
* @returns y if n!=1
|
||||
*/
|
||||
std::complex<double> *InverseFastFourierTransform(std::complex<double> *p, uint8_t n) {
|
||||
if (n == 1) {
|
||||
return p; /// Base Case To return
|
||||
}
|
||||
|
||||
double pi = 2 * asin(1.0); /// Declaring value of pi
|
||||
|
||||
std::complex<double> om = std::complex<double>(
|
||||
cos(2 * pi / n), sin(2 * pi / n)); /// Calculating value of omega
|
||||
|
||||
om.real(om.real()/n); /// One change in comparison with DFT
|
||||
om.imag(om.imag()/n); /// One change in comparison with DFT
|
||||
|
||||
auto *pe = new std::complex<double>[n / 2]; /// Coefficients of even power
|
||||
|
||||
auto *po = new std::complex<double>[n / 2]; /// Coefficients of odd power
|
||||
|
||||
int k1 = 0, k2 = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
if (j % 2 == 0) {
|
||||
pe[k1++] = p[j]; /// Assigning values of even Coefficients
|
||||
|
||||
} else
|
||||
po[k2++] = p[j]; /// Assigning value of odd Coefficients
|
||||
}
|
||||
|
||||
std::complex<double> *ye =
|
||||
InverseFastFourierTransform(pe, n / 2); /// Recursive Call
|
||||
|
||||
std::complex<double> *yo =
|
||||
InverseFastFourierTransform(po, n / 2); /// Recursive Call
|
||||
|
||||
auto *y = new std::complex<double>[n]; /// Final value representation list
|
||||
|
||||
k1 = 0, k2 = 0;
|
||||
|
||||
for (int i = 0; i < n / 2; i++) {
|
||||
y[i] =
|
||||
ye[k1] + pow(om, i) * yo[k2]; /// Updating the first n/2 elements
|
||||
y[i + n / 2] =
|
||||
ye[k1] - pow(om, i) * yo[k2]; /// Updating the last n/2 elements
|
||||
|
||||
k1++;
|
||||
k2++;
|
||||
}
|
||||
|
||||
if(n!=2){
|
||||
|
||||
delete[] pe;
|
||||
delete[] po;
|
||||
|
||||
}
|
||||
|
||||
delete[] ye; /// Deleting dynamic array ye
|
||||
delete[] yo; /// Deleting dynamic array yo
|
||||
return y;
|
||||
}
|
||||
|
||||
} // namespace numerical_methods
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @details
|
||||
* Declaring two test cases and checking for the error
|
||||
* in predicted and true value is less than 0.000000000001.
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
/* descriptions of the following test */
|
||||
|
||||
auto *t1 = new std::complex<double>[2]; /// Test case 1
|
||||
auto *t2 = new std::complex<double>[4]; /// Test case 2
|
||||
|
||||
t1[0] = {3, 0};
|
||||
t1[1] = {-1, 0};
|
||||
t2[0] = {10, 0};
|
||||
t2[1] = {-2, -2};
|
||||
t2[2] = {-2, 0};
|
||||
t2[3] = {-2, 2};
|
||||
|
||||
uint8_t n1 = 2;
|
||||
uint8_t n2 = 4;
|
||||
std::vector<std::complex<double>> r1 = {
|
||||
{1, 0}, {2, 0}}; /// True Answer for test case 1
|
||||
|
||||
std::vector<std::complex<double>> r2 = {
|
||||
{1, 0}, {2, 0}, {3, 0}, {4, 0}}; /// True Answer for test case 2
|
||||
|
||||
std::complex<double> *o1 = numerical_methods::InverseFastFourierTransform(t1, n1);
|
||||
|
||||
std::complex<double> *o2 = numerical_methods::InverseFastFourierTransform(t2, n2);
|
||||
|
||||
for (uint8_t i = 0; i < n1; i++) {
|
||||
assert((r1[i].real() - o1[i].real() < 0.000000000001) &&
|
||||
(r1[i].imag() - o1[i].imag() <
|
||||
0.000000000001)); /// Comparing for both real and imaginary
|
||||
/// values for test case 1
|
||||
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < n2; i++) {
|
||||
assert((r2[i].real() - o2[i].real() < 0.000000000001) &&
|
||||
(r2[i].imag() - o2[i].imag() <
|
||||
0.000000000001)); /// Comparing for both real and imaginary
|
||||
/// values for test case 2
|
||||
|
||||
}
|
||||
|
||||
|
||||
delete[] t1;
|
||||
delete[] t2;
|
||||
delete[] o1;
|
||||
delete[] o2;
|
||||
std::cout << "All tests have successfully passed!\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @param argc commandline argument count (ignored)
|
||||
* @param argv commandline array of arguments (ignored)
|
||||
* calls automated test function to test the working of fast fourier transform.
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
|
||||
int main(int argc, char const *argv[]) {
|
||||
test(); // run self-test implementations
|
||||
// with 2 defined test cases
|
||||
return 0;
|
||||
}
|
199
numerical_methods/midpoint_integral_method.cpp
Normal file
199
numerical_methods/midpoint_integral_method.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief A numerical method for easy [approximation of
|
||||
* integrals](https://en.wikipedia.org/wiki/Midpoint_method)
|
||||
* @details The idea is to split the interval into N of intervals and use as
|
||||
* interpolation points the xi for which it applies that xi = x0 + i*h, where h
|
||||
* is a step defined as h = (b-a)/N where a and b are the first and last points
|
||||
* of the interval of the integration [a, b].
|
||||
*
|
||||
* We create a table of the xi and their corresponding f(xi) values and we
|
||||
* evaluate the integral by the formula: I = h * {f(x0+h/2) + f(x1+h/2) + ... +
|
||||
* f(xN-1+h/2)}
|
||||
*
|
||||
* Arguments can be passed as parameters from the command line argv[1] = N,
|
||||
* argv[2] = a, argv[3] = b. In this case if the default values N=16, a=1, b=3
|
||||
* are changed then the tests/assert are disabled.
|
||||
*
|
||||
*
|
||||
* @author [ggkogkou](https://github.com/ggkogkou)
|
||||
*/
|
||||
#include <cassert> /// for assert
|
||||
#include <cmath> /// for math functions
|
||||
#include <cstdint> /// for integer allocation
|
||||
#include <cstdlib> /// for std::atof
|
||||
#include <functional> /// for std::function
|
||||
#include <iostream> /// for IO operations
|
||||
#include <map> /// for std::map container
|
||||
|
||||
/**
|
||||
* @namespace numerical_methods
|
||||
* @brief Numerical algorithms/methods
|
||||
*/
|
||||
namespace numerical_methods {
|
||||
/**
|
||||
* @namespace midpoint_rule
|
||||
* @brief Functions for the [Midpoint
|
||||
* Integral](https://en.wikipedia.org/wiki/Midpoint_method) method
|
||||
* implementation
|
||||
*/
|
||||
namespace midpoint_rule {
|
||||
/**
|
||||
* @fn double midpoint(const std::int32_t N, const double h, const double a,
|
||||
* const std::function<double (double)>& func)
|
||||
* @brief Main function for implementing the Midpoint Integral Method
|
||||
* implementation
|
||||
* @param N is the number of intervals
|
||||
* @param h is the step
|
||||
* @param a is x0
|
||||
* @param func is the function that will be integrated
|
||||
* @returns the result of the integration
|
||||
*/
|
||||
double midpoint(const std::int32_t N, const double h, const double a,
|
||||
const std::function<double(double)>& func) {
|
||||
std::map<int, double>
|
||||
data_table; // Contains the data points, key: i, value: f(xi)
|
||||
double xi = a; // Initialize xi to the starting point x0 = a
|
||||
|
||||
// Create the data table
|
||||
// Loop from x0 to xN-1
|
||||
double temp = NAN;
|
||||
for (std::int32_t i = 0; i < N; i++) {
|
||||
temp = func(xi + h / 2); // find f(xi+h/2)
|
||||
data_table.insert(
|
||||
std::pair<std::int32_t, double>(i, temp)); // add i and f(xi)
|
||||
xi += h; // Get the next point xi for the next iteration
|
||||
}
|
||||
|
||||
// Evaluate the integral.
|
||||
// Remember: {f(x0+h/2) + f(x1+h/2) + ... + f(xN-1+h/2)}
|
||||
double evaluate_integral = 0;
|
||||
for (std::int32_t i = 0; i < N; i++) evaluate_integral += data_table.at(i);
|
||||
|
||||
// Multiply by the coefficient h
|
||||
evaluate_integral *= h;
|
||||
|
||||
// If the result calculated is nan, then the user has given wrong input
|
||||
// interval.
|
||||
assert(!std::isnan(evaluate_integral) &&
|
||||
"The definite integral can't be evaluated. Check the validity of "
|
||||
"your input.\n");
|
||||
// Else return
|
||||
return evaluate_integral;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A function f(x) that will be used to test the method
|
||||
* @param x The independent variable xi
|
||||
* @returns the value of the dependent variable yi = f(xi) = sqrt(xi) + ln(xi)
|
||||
*/
|
||||
double f(double x) { return std::sqrt(x) + std::log(x); }
|
||||
/**
|
||||
* @brief A function g(x) that will be used to test the method
|
||||
* @param x The independent variable xi
|
||||
* @returns the value of the dependent variable yi = g(xi) = e^(-xi) * (4 -
|
||||
* xi^2)
|
||||
*/
|
||||
double g(double x) { return std::exp(-x) * (4 - std::pow(x, 2)); }
|
||||
/**
|
||||
* @brief A function k(x) that will be used to test the method
|
||||
* @param x The independent variable xi
|
||||
* @returns the value of the dependent variable yi = k(xi) = sqrt(2*xi^3 + 3)
|
||||
*/
|
||||
double k(double x) { return std::sqrt(2 * std::pow(x, 3) + 3); }
|
||||
/**
|
||||
* @brief A function l(x) that will be used to test the method
|
||||
* @param x The independent variable xi
|
||||
* @returns the value of the dependent variable yi = l(xi) = xi + ln(2*xi + 1)
|
||||
*/
|
||||
double l(double x) { return x + std::log(2 * x + 1); }
|
||||
|
||||
} // namespace midpoint_rule
|
||||
} // namespace numerical_methods
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @param N is the number of intervals
|
||||
* @param h is the step
|
||||
* @param a is x0
|
||||
* @param b is the end of the interval
|
||||
* @param used_argv_parameters is 'true' if argv parameters are given and
|
||||
* 'false' if not
|
||||
*/
|
||||
static void test(std::int32_t N, double h, double a, double b,
|
||||
bool used_argv_parameters) {
|
||||
// Call midpoint() for each of the test functions f, g, k, l
|
||||
// Assert with two decimal point precision
|
||||
double result_f = numerical_methods::midpoint_rule::midpoint(
|
||||
N, h, a, numerical_methods::midpoint_rule::f);
|
||||
assert((used_argv_parameters || (result_f >= 4.09 && result_f <= 4.10)) &&
|
||||
"The result of f(x) is wrong");
|
||||
std::cout << "The result of integral f(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_f << std::endl;
|
||||
|
||||
double result_g = numerical_methods::midpoint_rule::midpoint(
|
||||
N, h, a, numerical_methods::midpoint_rule::g);
|
||||
assert((used_argv_parameters || (result_g >= 0.27 && result_g <= 0.28)) &&
|
||||
"The result of g(x) is wrong");
|
||||
std::cout << "The result of integral g(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_g << std::endl;
|
||||
|
||||
double result_k = numerical_methods::midpoint_rule::midpoint(
|
||||
N, h, a, numerical_methods::midpoint_rule::k);
|
||||
assert((used_argv_parameters || (result_k >= 9.06 && result_k <= 9.07)) &&
|
||||
"The result of k(x) is wrong");
|
||||
std::cout << "The result of integral k(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_k << std::endl;
|
||||
|
||||
double result_l = numerical_methods::midpoint_rule::midpoint(
|
||||
N, h, a, numerical_methods::midpoint_rule::l);
|
||||
assert((used_argv_parameters || (result_l >= 7.16 && result_l <= 7.17)) &&
|
||||
"The result of l(x) is wrong");
|
||||
std::cout << "The result of integral l(x) on interval [" << a << ", " << b
|
||||
<< "] is equal to: " << result_l << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
std::int32_t N =
|
||||
16; /// Number of intervals to divide the integration interval.
|
||||
/// MUST BE EVEN
|
||||
double a = 1, b = 3; /// Starting and ending point of the integration in
|
||||
/// the real axis
|
||||
double h = NAN; /// Step, calculated by a, b and N
|
||||
|
||||
bool used_argv_parameters =
|
||||
false; // If argv parameters are used then the assert must be omitted
|
||||
// for the test cases
|
||||
|
||||
// Get user input (by the command line parameters or the console after
|
||||
// displaying messages)
|
||||
if (argc == 4) {
|
||||
N = std::atoi(argv[1]);
|
||||
a = std::atof(argv[2]);
|
||||
b = std::atof(argv[3]);
|
||||
// Check if a<b else abort
|
||||
assert(a < b && "a has to be less than b");
|
||||
assert(N > 0 && "N has to be > 0");
|
||||
if (N < 4 || a != 1 || b != 3) {
|
||||
used_argv_parameters = true;
|
||||
}
|
||||
std::cout << "You selected N=" << N << ", a=" << a << ", b=" << b
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Default N=" << N << ", a=" << a << ", b=" << b
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// Find the step
|
||||
h = (b - a) / N;
|
||||
|
||||
test(N, h, a, b, used_argv_parameters); // run self-test implementations
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,97 +1,348 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation for a [Circular Linked
|
||||
* List](https://www.geeksforgeeks.org/circular-linked-list/).
|
||||
* @details A Circular Linked List is a variation on the regular linked list, in
|
||||
* which the last node has a pointer to the first node, which creates a full
|
||||
* circle. Consequently, this allows any node to be used as the starting point
|
||||
* for the list.
|
||||
* @author [Alvin](https://github.com/polarvoid)
|
||||
*/
|
||||
|
||||
struct node {
|
||||
int val;
|
||||
node *next;
|
||||
#include <cassert> /// for assert
|
||||
#include <iostream> /// for IO operations
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
/**
|
||||
* @namespace operations_on_datastructures
|
||||
* @brief Operations on Data Structures
|
||||
*/
|
||||
namespace operations_on_datastructures {
|
||||
|
||||
/**
|
||||
* @namespace circular_linked_list
|
||||
* @brief Functions for the [Circular Linked
|
||||
* List](https://www.geeksforgeeks.org/circular-linked-list/) implementation
|
||||
*/
|
||||
namespace circular_linked_list {
|
||||
|
||||
/**
|
||||
* @brief A Node struct that represents a single Node in a Binary Tree
|
||||
*/
|
||||
struct Node {
|
||||
int64_t data; ///< The value of the Node
|
||||
Node* next; ///< The Node's successor
|
||||
/**
|
||||
* @brief Creates a new Node with some initial data
|
||||
* @param _data Value of Node
|
||||
*/
|
||||
explicit Node(int64_t _data) {
|
||||
data = _data; ///< Set value of Node data
|
||||
next = nullptr; ///< Initialize successor
|
||||
}
|
||||
/**
|
||||
* @brief Creates a new Node with initial data and a successor
|
||||
* @param _data Value of Node
|
||||
* @param _next Pointer to the next Node
|
||||
*/
|
||||
explicit Node(int64_t _data, Node* _next) {
|
||||
data = _data; ///< Set value of Node data
|
||||
next = _next; ///< Initialize successor
|
||||
}
|
||||
};
|
||||
|
||||
node *start;
|
||||
/**
|
||||
* @brief A class that implements a Circular Linked List.
|
||||
*/
|
||||
class CircularLinkedList {
|
||||
private:
|
||||
Node* root; ///< Pointer to the root Node
|
||||
Node* end{}; ///< Pointer to the last Node
|
||||
|
||||
void insert(int x) {
|
||||
node *t = start;
|
||||
|
||||
if (start != NULL) {
|
||||
while (t->next != start) {
|
||||
t = t->next;
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an empty CircularLinkedList.
|
||||
*/
|
||||
CircularLinkedList() {
|
||||
root = nullptr;
|
||||
end = nullptr;
|
||||
}
|
||||
/**
|
||||
* @brief Copy constructor for CircularLinkedList.
|
||||
*/
|
||||
CircularLinkedList(const CircularLinkedList& copy) {
|
||||
erase();
|
||||
root = nullptr;
|
||||
Node* node = copy.root;
|
||||
while (node != nullptr) {
|
||||
insert(node->data);
|
||||
node = node->next;
|
||||
}
|
||||
node *n = new node;
|
||||
t->next = n;
|
||||
n->val = x;
|
||||
n->next = start;
|
||||
} else {
|
||||
node *n = new node;
|
||||
n->val = x;
|
||||
start = n;
|
||||
n->next = start;
|
||||
}
|
||||
}
|
||||
|
||||
void remove(int x) {
|
||||
node *t = start;
|
||||
node *p;
|
||||
while (t->val != x) {
|
||||
p = t;
|
||||
t = t->next;
|
||||
/**
|
||||
* @brief Move constructor for CircularLinkedList
|
||||
* @param source rvalue reference to a Circular Linked List
|
||||
*/
|
||||
CircularLinkedList(CircularLinkedList&& source) noexcept {
|
||||
root = source.root;
|
||||
end = source.end;
|
||||
source.root = nullptr;
|
||||
source.end = nullptr;
|
||||
}
|
||||
p->next = t->next;
|
||||
delete t;
|
||||
}
|
||||
|
||||
void search(int x) {
|
||||
node *t = start;
|
||||
int found = 0;
|
||||
while (t->next != start) {
|
||||
if (t->val == x) {
|
||||
cout << "\nFound";
|
||||
found = 1;
|
||||
break;
|
||||
/**
|
||||
* @brief Copy assignment operator
|
||||
* @param other Reference to a Circular Linked List
|
||||
* @returns Reference to CircularLinkedList
|
||||
*/
|
||||
CircularLinkedList& operator=(const CircularLinkedList& other) {
|
||||
erase();
|
||||
root = nullptr;
|
||||
Node* node = other.root;
|
||||
while (node != nullptr) {
|
||||
insert(node->data);
|
||||
node = node->next;
|
||||
}
|
||||
t = t->next;
|
||||
return *this;
|
||||
}
|
||||
if (found == 0) {
|
||||
cout << "\nNot Found";
|
||||
/**
|
||||
* @brief Move assignment operator
|
||||
* @param other rvalue reference to a Circular Linked List
|
||||
* @returns Reference to CircularLinkedList
|
||||
*/
|
||||
CircularLinkedList& operator=(CircularLinkedList&& other) noexcept {
|
||||
root = other.root;
|
||||
end = other.end;
|
||||
other.root = nullptr;
|
||||
other.end = nullptr;
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Cleans up memory when destroyed
|
||||
*/
|
||||
~CircularLinkedList() { erase(); }
|
||||
/**
|
||||
* Iteratively frees each node in the Circular Linked List from the heap
|
||||
*/
|
||||
void erase() {
|
||||
if (root == nullptr) {
|
||||
return;
|
||||
}
|
||||
Node* node = root;
|
||||
do {
|
||||
Node* temp = node;
|
||||
node = node->next;
|
||||
delete (temp);
|
||||
} while (node != root);
|
||||
root = nullptr;
|
||||
end = nullptr;
|
||||
}
|
||||
/**
|
||||
* @brief Inserts all the values from a vector into the Circular Linked List
|
||||
* @details Goes through each element in the vector sequentially, inserting
|
||||
* it into the list
|
||||
* @param values The vector of integer values that is to be inserted
|
||||
* @returns void
|
||||
*/
|
||||
void insert(const std::vector<int64_t>& values) {
|
||||
for (int64_t value : values) {
|
||||
insert(value);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Inserts a single value into the Circular Linked List
|
||||
* @details Creates a Node with the given value, pointing to the root Node
|
||||
* and inserts it into the list
|
||||
* @param data The integer valus to be inserted
|
||||
* @returns void
|
||||
*/
|
||||
void insert(int64_t data) {
|
||||
Node* node = new Node(data, root);
|
||||
insert(node);
|
||||
}
|
||||
/**
|
||||
* @brief Inserts a given Node into the Circular Linked List
|
||||
* @details Checks wheter the list is empty, and inserts the Node, modifying
|
||||
* the end pointer
|
||||
* @param node The Node that is to be inserted
|
||||
* @returns void
|
||||
*/
|
||||
void insert(Node* node) {
|
||||
if (root == nullptr) {
|
||||
root = node; ///< Set node as the root
|
||||
node->next = root; ///< Point node to itself
|
||||
end = root; ///< Set the end to the root
|
||||
} else {
|
||||
end->next = node; ///< Append node to the end
|
||||
node->next = root; ///< Set the next value to the root
|
||||
end = node; ///< Make end point to node
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Prints the values of the Circular Linked List, beginning from the
|
||||
* root Node
|
||||
* @details Goes through each Node from the root and prints them out in
|
||||
* order
|
||||
* @returns void
|
||||
*/
|
||||
void print() { print(root); }
|
||||
/**
|
||||
* @brief Prints the values of the Circular Linked List, beginning from a
|
||||
* given Node to be used as the root
|
||||
* @details Goes through each Node from the given Node and prints them out
|
||||
* in order. If the list is empty, it prints the message 'Empty List!'
|
||||
* @param root The Node to start at
|
||||
* @returns void
|
||||
*/
|
||||
void print(Node* root) {
|
||||
Node* temp = root;
|
||||
if (root == nullptr) {
|
||||
std::cout << "Empty List!\n";
|
||||
return;
|
||||
}
|
||||
do {
|
||||
std::cout << temp->data << " ";
|
||||
temp = temp->next;
|
||||
} while (temp != root);
|
||||
std::cout << "\n";
|
||||
}
|
||||
/**
|
||||
* @brief Returns a std::vector of the values of the Circular Linked List
|
||||
* @details Starting from the root Node, appends each value of the list to a
|
||||
* std::vector and returns it
|
||||
* @returns A std::vector of the list's values
|
||||
*/
|
||||
std::vector<int64_t> values() { return values(root); }
|
||||
/**
|
||||
* @brief Returns a std::vector of the values of the Circular Linked List,
|
||||
* beginning from a given Node
|
||||
* @details Starting from a given Node, appends each value of the list to a
|
||||
* std::vector and returns it
|
||||
* @param root The Node to start at
|
||||
* @returns A std::vector of the list's values
|
||||
*/
|
||||
std::vector<int64_t> values(Node* root) {
|
||||
std::vector<int64_t> res;
|
||||
if (root == nullptr) {
|
||||
return res; ///< Return empty vector
|
||||
}
|
||||
Node* temp = root;
|
||||
do {
|
||||
res.push_back(temp->data);
|
||||
temp = temp->next;
|
||||
} while (temp != root);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace circular_linked_list
|
||||
|
||||
} // namespace operations_on_datastructures
|
||||
|
||||
/**
|
||||
* @namespace tests
|
||||
* @brief Testcases to check Circular Linked List.
|
||||
*/
|
||||
namespace tests {
|
||||
using operations_on_datastructures::circular_linked_list::CircularLinkedList;
|
||||
using operations_on_datastructures::circular_linked_list::Node;
|
||||
/**
|
||||
* @brief A Test to check a single value
|
||||
* @returns void
|
||||
*/
|
||||
void test1() {
|
||||
std::cout << "TEST CASE 1\n";
|
||||
std::cout << "Intialized a = {2}\n";
|
||||
std::cout << "Expected result: {2}\n";
|
||||
CircularLinkedList a;
|
||||
std::vector<int64_t> res = {2};
|
||||
a.insert(2);
|
||||
assert(a.values() == res);
|
||||
a.print();
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
/**
|
||||
* @brief A Test to check a few values
|
||||
* @returns void
|
||||
*/
|
||||
void test2() {
|
||||
std::cout << "TEST CASE 2\n";
|
||||
std::cout << "Intialized a = {2, 5, 6}\n";
|
||||
std::cout << "Expected result: {2, 5, 6}\n";
|
||||
CircularLinkedList a;
|
||||
std::vector<int64_t> res = {2, 5, 6};
|
||||
a.insert(2);
|
||||
a.insert(5);
|
||||
a.insert(6);
|
||||
assert(a.values() == res);
|
||||
a.print();
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
/**
|
||||
* @brief A Test to check an input array
|
||||
* @returns void
|
||||
*/
|
||||
void test3() {
|
||||
std::cout << "TEST CASE 3\n";
|
||||
std::cout << "Intialized a = {2, 7, 8, 3, 2, 6}\n";
|
||||
std::cout << "Expected result: {2, 7, 8, 3, 2, 6}\n";
|
||||
CircularLinkedList a;
|
||||
std::vector<int64_t> res = {2, 7, 8, 3, 2, 6};
|
||||
a.insert({2, 7, 8, 3, 2, 6});
|
||||
a.print();
|
||||
assert(a.values() == res);
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
/**
|
||||
* @brief A Test to check using a specific Node as the starting point
|
||||
* @returns void
|
||||
*/
|
||||
void test4() {
|
||||
std::cout << "TEST CASE 4\n";
|
||||
std::cout << "Intialized a = {2, 5}\n";
|
||||
std::cout << "Expected result: {5, 2}\n";
|
||||
CircularLinkedList a;
|
||||
std::vector<int64_t> res = {5, 2};
|
||||
a.insert(2);
|
||||
Node* start = new Node(5); ///< Node we will start printing from
|
||||
a.insert(start);
|
||||
assert(a.values(start) == res);
|
||||
a.print(start);
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
|
||||
void show() {
|
||||
node *t = start;
|
||||
do {
|
||||
cout << t->val << "\t";
|
||||
t = t->next;
|
||||
} while (t != start);
|
||||
/**
|
||||
* @brief A Test to check an empty list
|
||||
* @returns void
|
||||
*/
|
||||
void test5() {
|
||||
std::cout << "TEST CASE 5\n";
|
||||
std::cout << "Intialized a = {}\n";
|
||||
std::cout << "Expected result: Empty List!\n";
|
||||
CircularLinkedList a;
|
||||
std::vector<int64_t> res = {};
|
||||
assert(a.values() == res);
|
||||
a.print();
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
} // namespace tests
|
||||
|
||||
/**
|
||||
* @brief Function to test the correctness of the Circular Linked List
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
tests::test1();
|
||||
tests::test2();
|
||||
tests::test3();
|
||||
tests::test4();
|
||||
tests::test5();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
int choice, x;
|
||||
do {
|
||||
cout << "\n1. Insert";
|
||||
cout << "\n2. Delete";
|
||||
cout << "\n3. Search";
|
||||
cout << "\n4. Print";
|
||||
cout << "\n\nEnter you choice : ";
|
||||
cin >> choice;
|
||||
switch (choice) {
|
||||
case 1:
|
||||
cout << "\nEnter the element to be inserted : ";
|
||||
cin >> x;
|
||||
insert(x);
|
||||
break;
|
||||
case 2:
|
||||
cout << "\nEnter the element to be removed : ";
|
||||
cin >> x;
|
||||
remove(x);
|
||||
break;
|
||||
case 3:
|
||||
cout << "\nEnter the element to be searched : ";
|
||||
cin >> x;
|
||||
search(x);
|
||||
break;
|
||||
case 4:
|
||||
show();
|
||||
break;
|
||||
}
|
||||
} while (choice != 0);
|
||||
|
||||
test(); // run self-test implementations
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user