From 17c374dc149e6b1bcdbe109db886124724268a40 Mon Sep 17 00:00:00 2001 From: David Leal Date: Mon, 24 Jul 2023 18:49:51 -0600 Subject: [PATCH 01/74] [feat/docs/fix]: improve the Dijkstra algorithm (#2508) Originally initiated in #2490. Co-authored-by: Mark Matthew Vergara --- greedy_algorithms/dijkstra.cpp | 205 ++++++++++++++++++++++----------- 1 file changed, 140 insertions(+), 65 deletions(-) diff --git a/greedy_algorithms/dijkstra.cpp b/greedy_algorithms/dijkstra.cpp index e4450379c5d..9df9af30c0c 100644 --- a/greedy_algorithms/dijkstra.cpp +++ b/greedy_algorithms/dijkstra.cpp @@ -1,23 +1,52 @@ -#include -#include - -using namespace std; - -// Wrapper class for storing a graph +/** + * @file + * @brief [Dijkstra](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) algorithm + * implementation + * @details + * _Quote from Wikipedia._ + * + * **Dijkstra's algorithm** is an algorithm for finding the + * shortest paths between nodes in a weighted graph, which may represent, for + * example, road networks. It was conceived by computer scientist Edsger W. + * Dijkstra in 1956 and published three years later. + * + * @author [David Leal](https://github.com/Panquesito7) + * @author [Arpan Jain](https://github.com/arpanjain97) + */ + +#include /// for assert +#include /// for INT_MAX +#include /// for IO operations +#include /// for std::vector + +/** + * @namespace + * @brief Greedy Algorithms + */ +namespace greedy_algorithms { +/** + * @brief + */ +/** + * @brief Wrapper class for storing a graph + */ class Graph { public: - int vertexNum; - int **edges; - - // Constructs a graph with V vertices and E edges - Graph(const int V) { - // initializes the array edges. - this->edges = new int *[V]; + int vertexNum = 0; + std::vector> edges{}; + + /** + * @brief Constructs a graph + * @param V number of vertices of the graph + */ + explicit Graph(const int V) { + // Initialize the array edges + this->edges = std::vector>(V, std::vector(V, 0)); for (int i = 0; i < V; i++) { - edges[i] = new int[V]; + edges[i] = std::vector(V, 0); } - // fills the array with zeros. + // Fills the array with zeros for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { edges[i][j] = 0; @@ -27,13 +56,28 @@ class Graph { this->vertexNum = V; } - // Adds the given edge to the graph - void addEdge(int src, int dst, int weight) { + /** + * @brief Adds an edge to the graph + * @param src the graph the edge should be added to + * @param dst the position where the edge should be added to + * @param weight the weight of the edge that should be added + * @returns void + */ + void add_edge(int src, int dst, int weight) { this->edges[src][dst] = weight; } }; -// Utility function to find minimum distance vertex in mdist -int minDistance(int mdist[], bool vset[], int V) { + +/** + * @brief Utility function that finds + * the vertex with the minimum distance in `mdist`. + * + * @param mdist array of distances to each vertex + * @param vset array indicating inclusion in the shortest path tree + * @param V the number of vertices in the graph + * @returns index of the vertex with the minimum distance + */ +int minimum_distance(std::vector mdist, std::vector vset, int V) { int minVal = INT_MAX, minInd = 0; for (int i = 0; i < V; i++) { if (!vset[i] && (mdist[i] < minVal)) { @@ -45,27 +89,42 @@ int minDistance(int mdist[], bool vset[], int V) { return minInd; } -// Utility function to print distances -void print(int dist[], int V) { - cout << "\nVertex Distance" << endl; +/** + * @brief Utility function to print the distances to vertices. + * + * This function prints the distances to each vertex in a tabular format. If the + * distance is equal to INT_MAX, it is displayed as "INF". + * + * @param dist An array representing the distances to each vertex. + * @param V The number of vertices in the graph. + * @return void + */ +void print(std::vector dist, int V) { + std::cout << "\nVertex Distance\n"; for (int i = 0; i < V; i++) { - if (dist[i] < INT_MAX) - cout << i << "\t" << dist[i] << endl; - else - cout << i << "\tINF" << endl; + if (dist[i] < INT_MAX) { + std::cout << i << "\t" << dist[i] << "\n"; + } + else { + std::cout << i << "\tINF" << "\n"; + } } } -// The main function that finds the shortest path from given source -// to all other vertices using Dijkstra's Algorithm.It doesn't work on negative -// weights -void Dijkstra(Graph graph, int src) { +/** + * @brief The main function that finds the shortest path from given source + * to all other vertices using Dijkstra's Algorithm. + * @note This doesn't work on negative weights. + * @param graph the graph to be processed + * @param src the source of the given vertex + * @returns void + */ +void dijkstra(Graph graph, int src) { int V = graph.vertexNum; - int mdist[V]; // Stores updated distances to vertex - bool vset[V]; // vset[i] is true if the vertex i included - // in the shortest path tree + std::vector mdist{}; // Stores updated distances to the vertex + std::vector vset{}; // `vset[i]` is true if the vertex `i` is included in the shortest path tree - // Initialise mdist and vset. Set distance of source as zero + // Initialize `mdist and `vset`. Set distance of source as zero for (int i = 0; i < V; i++) { mdist[i] = INT_MAX; vset[i] = false; @@ -73,9 +132,9 @@ void Dijkstra(Graph graph, int src) { mdist[src] = 0; - // iterate to find shortest path + // iterate to find the shortest path for (int count = 0; count < V - 1; count++) { - int u = minDistance(mdist, vset, V); + int u = minimum_distance(mdist, vset, V); vset[u] = true; @@ -89,36 +148,52 @@ void Dijkstra(Graph graph, int src) { print(mdist, V); } +} // namespace greedy_algorithms -// Driver Function -int main() { - int V, E, gsrc; - int src, dst, weight; - cout << "Enter number of vertices: "; - cin >> V; - cout << "Enter number of edges: "; - cin >> E; - Graph G(V); - for (int i = 0; i < E; i++) { - cout << "\nEdge " << i + 1 << "\nEnter source: "; - cin >> src; - cout << "Enter destination: "; - cin >> dst; - cout << "Enter weight: "; - cin >> weight; - - // makes sure source and destionation are in the proper bounds. - if (src >= 0 && src < V && dst >= 0 && dst < V) { - G.addEdge(src, dst, weight); - } else { - cout << "source and/or destination out of bounds" << endl; - i--; - continue; - } - } - cout << "\nEnter source:"; - cin >> gsrc; - Dijkstra(G, gsrc); +/** + * @brief Self-test implementations + * @returns void + */ +static void tests() { + greedy_algorithms::Graph graph(8); + + // 1st test. + graph.add_edge(6, 2, 4); + graph.add_edge(2, 6, 4); + assert(graph.edges[6][2] == 4); + + // 2nd test. + graph.add_edge(0, 1, 1); + graph.add_edge(1, 0, 1); + + assert(graph.edges[0][1] == 1); + + // 3rd test. + graph.add_edge(0, 2, 7); + graph.add_edge(2, 0, 7); + graph.add_edge(1, 2, 1); + graph.add_edge(2, 1, 1); + + assert(graph.edges[0][2] == 7); + + // 4th test. + graph.add_edge(1, 3, 3); + graph.add_edge(3, 1, 3); + graph.add_edge(1, 4, 2); + graph.add_edge(4, 1, 2); + graph.add_edge(2, 3, 2); + + assert(graph.edges[1][3] == 3); + + std::cout << "All tests have successfully passed!\n"; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + tests(); // run self-test implementations return 0; } From 2c68b68ca6e55b0838f779e8e6bf7ec75ecfae15 Mon Sep 17 00:00:00 2001 From: David Leal Date: Mon, 24 Jul 2023 18:52:45 -0600 Subject: [PATCH 02/74] fix: add missing namespace in Dijkstra --- greedy_algorithms/dijkstra.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/greedy_algorithms/dijkstra.cpp b/greedy_algorithms/dijkstra.cpp index 9df9af30c0c..739182daf12 100644 --- a/greedy_algorithms/dijkstra.cpp +++ b/greedy_algorithms/dijkstra.cpp @@ -25,8 +25,10 @@ */ namespace greedy_algorithms { /** - * @brief + * @namespace + * @brief Functions for the [Dijkstra](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) algorithm implementation */ +namespace dijkstra { /** * @brief Wrapper class for storing a graph */ @@ -112,7 +114,7 @@ void print(std::vector dist, int V) { } /** - * @brief The main function that finds the shortest path from given source + * @brief The main function that finds the shortest path from a given source * to all other vertices using Dijkstra's Algorithm. * @note This doesn't work on negative weights. * @param graph the graph to be processed @@ -124,7 +126,7 @@ void dijkstra(Graph graph, int src) { std::vector mdist{}; // Stores updated distances to the vertex std::vector vset{}; // `vset[i]` is true if the vertex `i` is included in the shortest path tree - // Initialize `mdist and `vset`. Set distance of source as zero + // Initialize `mdist and `vset`. Set the distance of the source as zero for (int i = 0; i < V; i++) { mdist[i] = INT_MAX; vset[i] = false; @@ -148,6 +150,7 @@ void dijkstra(Graph graph, int src) { print(mdist, V); } +} // namespace dijkstra } // namespace greedy_algorithms /** @@ -155,7 +158,7 @@ void dijkstra(Graph graph, int src) { * @returns void */ static void tests() { - greedy_algorithms::Graph graph(8); + greedy_algorithms::dijkstra::Graph graph(8); // 1st test. graph.add_edge(6, 2, 4); From 6daf7015e31d079ae5896bb20719e46ccf8dd821 Mon Sep 17 00:00:00 2001 From: David Leal Date: Fri, 4 Aug 2023 15:06:36 -0600 Subject: [PATCH 03/74] chore: run directory workflow daily --- .github/workflows/directory_writer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index 3264c0324be..48f71505cdf 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -10,7 +10,7 @@ on: # │ │ │ │ │ # │ │ │ │ │ # * * * * * - - cron: '0 0 * * 1' + - cron: '0 0 * * *' jobs: build: if: github.repository == 'TheAlgorithms/C-Plus-Plus' # We only need this to run in our repository. From f49369065c13e6cfee906de9dd0f5a6443f524e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 11:35:38 -0600 Subject: [PATCH 04/74] docs: update DIRECTORY.md (#2521) Co-authored-by: github-actions[bot] --- DIRECTORY.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 05ad073afcc..bda68918d88 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -20,7 +20,7 @@ * [Count Of Trailing Ciphers In Factorial N](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp) * [Find Non Repeating Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/find_non_repeating_number.cpp) * [Hamming Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/hamming_distance.cpp) - * [next higher number with same number of set bits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp) + * [Next Higher Number With Same Number Of Set Bits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp) * [Power Of 2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/power_of_2.cpp) * [Set Kth Bit](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/set_kth_bit.cpp) * [Travelling Salesman Using Bit Manipulation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/travelling_salesman_using_bit_manipulation.cpp) @@ -79,6 +79,7 @@ * [Test Queue](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/test_queue.cpp) * [Test Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/test_stack.cpp) * [Test Stack Students](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/test_stack_students.cpp) + * [Treap](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/treap.cpp) * [Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/tree.cpp) * [Tree 234](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/tree_234.cpp) * [Trie Modern](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/trie_modern.cpp) @@ -213,6 +214,7 @@ * [Integral Approximation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/integral_approximation.cpp) * [Integral Approximation2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/integral_approximation2.cpp) * [Inv Sqrt](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/inv_sqrt.cpp) + * [Iterative Factorial](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/iterative_factorial.cpp) * [Large Factorial](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/large_factorial.cpp) * [Large Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/large_number.h) * [Largest Power](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/largest_power.cpp) @@ -391,6 +393,7 @@ * [Wiggle Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/wiggle_sort.cpp) ## Strings + * [Boyer Moore](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/boyer_moore.cpp) * [Brute Force String Searching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/brute_force_string_searching.cpp) * [Horspool](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/horspool.cpp) * [Knuth Morris Pratt](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/knuth_morris_pratt.cpp) From 23b133ae1eac4ad7e94e74da140d462180738413 Mon Sep 17 00:00:00 2001 From: David Leal Date: Wed, 6 Sep 2023 11:37:12 -0600 Subject: [PATCH 05/74] fix: GitHub Actions bot username on Awesome Workflow --- .github/workflows/awesome_workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index 32555bbbd29..a0b83987bfd 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Git Specs run: | git config --global user.name github-actions[bot] - git config --global user.email 'github-actions@users.noreply.github.com' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' - name: Filename Formatter run: | wget https://raw.githubusercontent.com/TheAlgorithms/scripts/main/filename_formatter.sh From 6376bf46aff52a1944d4efcd5ae884b39119cd34 Mon Sep 17 00:00:00 2001 From: David Leal Date: Wed, 27 Sep 2023 12:34:55 -0600 Subject: [PATCH 06/74] chore: add `workflow_dispatch` in directory workflow --- .github/workflows/directory_writer.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index 48f71505cdf..dbb5449c6b0 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -11,6 +11,7 @@ on: # │ │ │ │ │ # * * * * * - cron: '0 0 * * *' + workflow_dispatch: jobs: build: if: github.repository == 'TheAlgorithms/C-Plus-Plus' # We only need this to run in our repository. From 6cd283950b5dfb2f85cd3abc9513c840400926b7 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Tue, 16 Jan 2024 02:38:58 +0100 Subject: [PATCH 07/74] chore: update `actions/checkout` to `v4` (#2530) --- .github/workflows/awesome_workflow.yml | 4 ++-- .github/workflows/codeql.yml | 2 +- .github/workflows/directory_writer.yml | 2 +- .github/workflows/gh-pages.yml | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index a0b83987bfd..ffb5478778a 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -8,7 +8,7 @@ jobs: name: Code Formatter runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-python@v4 @@ -56,7 +56,7 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - run: | diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 16da8867bf5..2b40ac59304 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index dbb5449c6b0..bb3b8395607 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -17,7 +17,7 @@ jobs: if: github.repository == 'TheAlgorithms/C-Plus-Plus' # We only need this to run in our repository. runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build directory diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 134c04bb13d..b795dcadb56 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -8,7 +8,7 @@ jobs: build: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install requirements @@ -19,7 +19,7 @@ jobs: - name: build run: cmake --build build -t doc - name: gh-pages - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: "gh-pages" clean: false From 08900b8c983b861ddd9c2e1efe7bf0bdd53beb4a Mon Sep 17 00:00:00 2001 From: David Leal Date: Mon, 15 Jan 2024 20:02:44 -0600 Subject: [PATCH 08/74] chore: update copyright notice to 2024 --- LICENSE | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index 2897d02e2a0..6912623e775 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,5 @@ -MIT License - -Copyright (c) 2016-2022 TheAlgorithms and contributors +The MIT License +Copyright (c) 2016-2024 TheAlgorithms and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 2dadbf73f41f2ac2e2c4a96f8116638cec17a07f Mon Sep 17 00:00:00 2001 From: David Leal Date: Mon, 12 Feb 2024 20:03:19 +0000 Subject: [PATCH 09/74] chore: remove unnecessary prints in `games/memory_game.cpp` --- games/memory_game.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/games/memory_game.cpp b/games/memory_game.cpp index 9283340ae89..fc92a2e5079 100644 --- a/games/memory_game.cpp +++ b/games/memory_game.cpp @@ -373,8 +373,6 @@ int main() { ///< (previous answered values do not count). std::cout << "\tMEMORY GAME\n"; - std::cout << std::boolalpha; - std::cout << std::is_literal_type::value; do { std::cout << "\n1. 4x2 (1)"; From 8a368240e20b4bbacb67e1ec2283900396b3ef4c Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Fri, 30 Aug 2024 19:20:08 +0200 Subject: [PATCH 10/74] fix: remove memory leak `iterative_factorial.cpp` (#2535) * fix: remove memory leak * tests: check properly if `math::iterativeFactorial` throws --- math/iterative_factorial.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/math/iterative_factorial.cpp b/math/iterative_factorial.cpp index 00cdb18fda4..12f6afe06a0 100644 --- a/math/iterative_factorial.cpp +++ b/math/iterative_factorial.cpp @@ -46,7 +46,7 @@ namespace math { */ uint64_t iterativeFactorial(uint8_t n) { if (n > 20) { - throw new std::invalid_argument("Maximum n value is 20"); + throw std::invalid_argument("Maximum n value is 20"); } // 1 because it is the identity number of multiplication. @@ -101,12 +101,14 @@ static void test() { std::cout << "Exception test \n" "Input: 21 \n" "Expected output: Exception thrown \n"; + + bool wasExceptionThrown = false; try { math::iterativeFactorial(21); - } catch (std::invalid_argument* e) { - std::cout << "Exception thrown successfully \nContent: " << e->what() - << "\n"; + } catch (const std::invalid_argument&) { + wasExceptionThrown = true; } + assert(wasExceptionThrown); std::cout << "All tests have passed successfully.\n"; } From e139ee952fefbce85ad1ef8704c28bac3fd44824 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Fri, 30 Aug 2024 19:30:06 +0200 Subject: [PATCH 11/74] fix: add and use function `deleteList` to remove memory leak (#2534) Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- .../get_size_of_linked_list.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/operations_on_datastructures/get_size_of_linked_list.cpp b/operations_on_datastructures/get_size_of_linked_list.cpp index 84f8db07fb8..3c0457d3f73 100644 --- a/operations_on_datastructures/get_size_of_linked_list.cpp +++ b/operations_on_datastructures/get_size_of_linked_list.cpp @@ -16,6 +16,20 @@ int getSize(Node *root) { return 1 + getSize(root->next); } +/* + * @brief This function dealocates memory related to the given list + * It recursively deletes all of the nodes of the input list. + * @param room the root/head of the input list + * @warning Plese note that the memory for each node has to be alocated using new. + */ +void deleteList(Node *const root) { + if (root != NULL) + { + deleteList(root->next); + delete root; + } +} + int main() { Node *myList = new Node(0, NULL); // Initializes the LinkedList Node *temp = myList; @@ -31,6 +45,8 @@ int main() { std::cout << getSize(myList) << std::endl << getSize(secondList) << std::endl << getSize(thirdList) << std::endl; + deleteList(secondList); + deleteList(myList); return 0; } From 435f1eded487a4d0af50b91402b5fcd32718a5d2 Mon Sep 17 00:00:00 2001 From: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Date: Fri, 30 Aug 2024 23:07:19 +0530 Subject: [PATCH 12/74] chore: Make CI builds parallel (#2714) * chore: make ci builds parallel * chore: fix specification of job number * chore: use 4 as a limit for parallel builds * fix: remove parallel from linting --- .github/workflows/awesome_workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index ffb5478778a..70dd717fa33 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -61,7 +61,7 @@ jobs: submodules: true - run: | cmake -B ./build -S . - cmake --build build + cmake --build build --parallel 4 - name: Label on PR fail uses: actions/github-script@v6 if: ${{ failure() && matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' }} From 9e44b6807038b9f8a25bfa3772fea2548f19c900 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Fri, 30 Aug 2024 20:05:30 +0200 Subject: [PATCH 13/74] fix: remove memory leak (#2532) Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- sorting/library_sort.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sorting/library_sort.cpp b/sorting/library_sort.cpp index c9cba88d8c4..33f151b296d 100644 --- a/sorting/library_sort.cpp +++ b/sorting/library_sort.cpp @@ -69,6 +69,11 @@ void librarySort(int *index, int n) { index_pos_for_output++; } } + delete[] numbered; + delete[] gaps; + for (int i = 0; i < 2; ++i) { + delete[] library[i]; + } } int main() { From 519d37f6bcfe0fd6997351685487ba5ee5a6af94 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Fri, 30 Aug 2024 20:12:15 +0200 Subject: [PATCH 14/74] fix: remove memory issues (#2533) Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- sorting/counting_sort.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sorting/counting_sort.cpp b/sorting/counting_sort.cpp index 1fbfc0fa3a3..8daeeab6b43 100644 --- a/sorting/counting_sort.cpp +++ b/sorting/counting_sort.cpp @@ -27,6 +27,9 @@ int *Counting_Sort(int Arr[], int N) { int *Sorted_Arr = new int[N]; int *Count = new int[max - min + 1]; + for (int i = 0; i < max - min + 1; ++i) { + Count[i] = 0; + } for (int i = 0; i < N; i++) Count[Arr[i] - min]++; @@ -37,6 +40,7 @@ int *Counting_Sort(int Arr[], int N) { Count[Arr[i] - min]--; } + delete[] Count; return Sorted_Arr; } @@ -51,6 +55,7 @@ int main() { Sorted_Arr = Counting_Sort(Arr, N); cout << "\n\t Sorted Array = "; Print(Sorted_Arr, N); + delete[] Sorted_Arr; cout << endl; return 0; From 7fc338d0fdb75590da946ff99e38883cfb89772b Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sat, 31 Aug 2024 02:33:44 +0200 Subject: [PATCH 15/74] fix: use `GITHUB_ACTOR` in `git config` (#2673) --- .github/workflows/gh-pages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index b795dcadb56..3384cf859bf 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -25,8 +25,8 @@ jobs: clean: false - name: Move & Commit files run: | - git config --global user.name github-actions - git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com' + git config --global user.name "$GITHUB_ACTOR" + git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com" git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY rm -rf d* && rm *.html && rm *.svg && rm *.map && rm *.md5 && rm *.png && rm *.js && rm *.css git add . From 8bde3ea612448b0d5fdbd2f092429e86de03ca62 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sat, 31 Aug 2024 02:37:42 +0200 Subject: [PATCH 16/74] fix: remove memory leak in `sublist_search.cpp` (#2541) Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- search/sublist_search.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/search/sublist_search.cpp b/search/sublist_search.cpp index 9f854ce5702..0954173d20c 100644 --- a/search/sublist_search.cpp +++ b/search/sublist_search.cpp @@ -90,6 +90,20 @@ Node *makeLinkedList(const std::vector &data) { return head; } +/* + * @brief This function dealocates memory related to the given list + * It recursively deletes all of the nodes of the input list. + * @param room the root/head of the input list + * @warning Plese note that the memory for each node has to be alocated using + * new. + */ +void deleteList(Node *const root) { + if (root != NULL) { + deleteList(root->next); + delete root; + } +} + /** * @brief Main searching function * @param sublist A linked list which is supposed to be searched in mainList. @@ -217,8 +231,8 @@ class TestCases { log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" "~"); - delete (sublistLL); - delete (mainlistLL); + deleteList(mainlistLL); + deleteList(sublistLL); } /** @@ -270,6 +284,9 @@ class TestCases { log("[PASS] : TEST CASE 2 PASS!"); log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" "~"); + + deleteList(mainlistLL); + deleteList(sublistLL); } /** @@ -318,6 +335,9 @@ class TestCases { log("[PASS] : TEST CASE 3 PASS!"); log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" "~"); + + deleteList(mainlistLL); + deleteList(sublistLL); } }; @@ -366,5 +386,8 @@ int main(int argc, char *argv[]) { } else { std::cout << "[FALSE] - sublist NOT found in main list\n"; } + + deleteList(mainlistLL); + deleteList(sublistLL); return 0; } From af72fab013cc448c74b79a2981f3ceee957f9eae Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sat, 31 Aug 2024 02:42:39 +0200 Subject: [PATCH 17/74] fix: make interface of `NCRModuloP` fail-safe (#2469) * fix: set proper size of fac * style: use std::size_t as a type of loop counter * style: use uint64_t as a type of loop counter * fix: remove p from the argument list of NCRModuloP::ncr * refactor: add utils namespace * refactor: use references in gcdExtended * refactor: add NCRModuloP::computeFactorialsMod * style: make NCRModuloP::ncr const * test: reorganize tests * test: add missing test cases * refactor: simplify logic * style: make example object const * style: use auto * style: use int64_t to avoid narrowing conversions * docs: update explanation why to import iostream * docs: remove `p` from docstr of `NCRModuloP::ncr` * docs: udpate doc-strs and add example() * Apply suggestions from code review Co-authored-by: David Leal * dosc: add missing docs * feat: display message when all tests pass Co-authored-by: David Leal * style: initialize `NCRModuloP::p` with `0` Co-authored-by: David Leal --------- Co-authored-by: David Leal Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- math/ncr_modulo_p.cpp | 211 +++++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 83 deletions(-) diff --git a/math/ncr_modulo_p.cpp b/math/ncr_modulo_p.cpp index 03aecf67e88..cbf5e9e1a00 100644 --- a/math/ncr_modulo_p.cpp +++ b/math/ncr_modulo_p.cpp @@ -10,7 +10,7 @@ */ #include /// for assert -#include /// for io operations +#include /// for std::cout #include /// for std::vector /** @@ -25,71 +25,95 @@ namespace math { * implementation. */ namespace ncr_modulo_p { + /** - * @brief Class which contains all methods required for calculating nCr mod p + * @namespace utils + * @brief this namespace contains the definitions of the functions called from + * the class math::ncr_modulo_p::NCRModuloP */ -class NCRModuloP { - private: - std::vector 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(size); - fac[0] = 1; - for (int i = 1; i <= size; i++) { - fac[i] = (fac[i - 1] * i) % p; - } +namespace utils { +/** + * @brief finds the values x and y such that a*x + b*y = gcd(a,b) + * + * @param[in] a the first input of the gcd + * @param[in] a the second input of the gcd + * @param[out] x the Bézout coefficient of a + * @param[out] y the Bézout coefficient of b + * @return the gcd of a and b + */ +int64_t gcdExtended(const int64_t& a, const int64_t& b, int64_t& x, + int64_t& y) { + if (a == 0) { + x = 0; + y = 1; + return b; } - /** 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; + const int64_t gcd = gcdExtended(b % a, a, x1, y1); - int64_t x1 = 0, y1 = 0; - uint64_t gcd = gcdExtended(b % a, a, &x1, &y1); + x = y1 - (b / a) * x1; + y = x1; + return gcd; +} - *x = y1 - (b / a) * x1; - *y = x1; - return gcd; +/** Find modular inverse of a modulo m i.e. a number x such that (a*x)%m = 1 + * + * @param[in] a the number for which the modular inverse is queried + * @param[in] m the modulus + * @return the inverce of a modulo m, if it exists, -1 otherwise + */ +int64_t modInverse(const int64_t& a, const int64_t& m) { + int64_t x = 0, y = 0; + const int64_t g = gcdExtended(a, m, x, y); + if (g != 1) { // modular inverse doesn't exist + return -1; + } else { + return ((x + m) % m); } +} +} // namespace utils +/** + * @brief Class which contains all methods required for calculating nCr mod p + */ +class NCRModuloP { + private: + const int64_t p = 0; /// the p from (nCr % p) + const std::vector + fac; /// stores precomputed factorial(i) % p value - /** 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 + /** + * @brief computes the array of values of factorials reduced modulo mod + * @param max_arg_val argument of the last factorial stored in the result + * @param mod value of the divisor used to reduce factorials + * @return vector storing factorials of the numbers 0, ..., max_arg_val + * reduced modulo mod */ - 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; + static std::vector computeFactorialsMod(const int64_t& max_arg_val, + const int64_t& mod) { + auto res = std::vector(max_arg_val + 1); + res[0] = 1; + for (int64_t i = 1; i <= max_arg_val; i++) { + res[i] = (res[i - 1] * i) % mod; } + return res; } - /** Find nCr % p - * - * @params[in] the numbers 'n', 'r' and 'p' - * @returns the value nCr % p + public: + /** + * @brief constructs an NCRModuloP object allowing to compute (nCr)%p for + * inputs from 0 to size */ - int64_t ncr(const uint64_t& n, const uint64_t& r, const uint64_t& p) { + NCRModuloP(const int64_t& size, const int64_t& p) + : p(p), fac(computeFactorialsMod(size, p)) {} + + /** + * @brief computes nCr % p + * @param[in] n the number of objects to be chosen + * @param[in] r the number of objects to choose from + * @return the value nCr % p + */ + int64_t ncr(const int64_t& n, const int64_t& r) const { // Base cases if (r > n) { return 0; @@ -101,50 +125,71 @@ class NCRModuloP { 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 + const auto denominator = (fac[r] * fac[n - r]) % p; + const auto denominator_inv = utils::modInverse(denominator, p); + if (denominator_inv < 0) { // modular inverse doesn't exist return -1; } - return (fac[n] * denominator) % p; + return (fac[n] * denominator_inv) % p; } }; } // namespace ncr_modulo_p } // namespace math /** - * @brief Test implementations - * @param ncrObj object which contains the precomputed factorial values and - * ncr function - * @returns void + * @brief tests math::ncr_modulo_p::NCRModuloP */ -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); +static void tests() { + struct TestCase { + const int64_t size; + const int64_t p; + const int64_t n; + const int64_t r; + const int64_t expected; + + TestCase(const int64_t size, const int64_t p, const int64_t n, + const int64_t r, const int64_t expected) + : size(size), p(p), n(n), r(r), expected(expected) {} + }; + const std::vector test_cases = { + TestCase(60000, 1000000007, 52323, 26161, 224944353), + TestCase(20, 5, 6, 2, 30 % 5), + TestCase(100, 29, 7, 3, 35 % 29), + TestCase(1000, 13, 10, 3, 120 % 13), + TestCase(20, 17, 1, 10, 0), + TestCase(45, 19, 23, 1, 23 % 19), + TestCase(45, 19, 23, 0, 1), + TestCase(45, 19, 23, 23, 1), + TestCase(20, 9, 10, 2, -1)}; + for (const auto& tc : test_cases) { + assert(math::ncr_modulo_p::NCRModuloP(tc.size, tc.p).ncr(tc.n, tc.r) == + tc.expected); + } + + std::cout << "\n\nAll tests have successfully passed!\n"; } /** - * @brief Main function - * @returns 0 on exit + * @brief example showing the usage of the math::ncr_modulo_p::NCRModuloP class */ -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 +void example() { + const int64_t size = 1e6 + 1; + const int64_t p = 1e9 + 7; + + // the ncrObj contains the precomputed values of factorials modulo p for + // values from 0 to size + const auto ncrObj = math::ncr_modulo_p::NCRModuloP(size, p); + + // having the ncrObj we can efficiently query the values of (n C r)%p + // note that time of the computation does not depend on size for (int i = 0; i <= 7; i++) { - std::cout << 6 << "C" << i << " = " << ncrObj.ncr(6, i, p) << "\n"; + std::cout << 6 << "C" << i << " mod " << p << " = " << ncrObj.ncr(6, i) + << "\n"; } - tests(ncrObj); // execute the tests - std::cout << "Assertions passed\n"; +} + +int main() { + tests(); + example(); return 0; } From 4a03c62dd37ed54a2f1b0208d4bd10df0e354e43 Mon Sep 17 00:00:00 2001 From: Tim Lander <5424257+VirtualTim@users.noreply.github.com> Date: Sat, 31 Aug 2024 08:55:29 +0800 Subject: [PATCH 18/74] Fix compilation failure with gcc >= 13 (#2702) For testing - https://godbolt.org/z/6WWh3zs9G Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- math/extended_euclid_algorithm.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/math/extended_euclid_algorithm.cpp b/math/extended_euclid_algorithm.cpp index 9fdc9692ef1..cc2eacac8e3 100644 --- a/math/extended_euclid_algorithm.cpp +++ b/math/extended_euclid_algorithm.cpp @@ -11,6 +11,7 @@ */ #include // for swap function #include +#include /** * function to update the coefficients per iteration From 1f5828eadfbe27c33a8f7c865a0d19664a2f1782 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 31 Aug 2024 04:05:53 +0300 Subject: [PATCH 19/74] fix: fix deprecation warning for macOS (#2711) Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- sorting/bogo_sort.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sorting/bogo_sort.cpp b/sorting/bogo_sort.cpp index 62fbef48ed6..749eaddd065 100644 --- a/sorting/bogo_sort.cpp +++ b/sorting/bogo_sort.cpp @@ -18,6 +18,7 @@ #include #include #include +#include /** @@ -50,8 +51,10 @@ std::array shuffle (std::array arr) { template std::array randomized_bogosort (std::array arr) { // Untill array is not sorted + std::random_device random_device; + std::mt19937 generator(random_device()); while (!std::is_sorted(arr.begin(), arr.end())) { - std::random_shuffle(arr.begin(), arr.end());// Shuffle the array + std::shuffle(arr.begin(), arr.end(), generator);// Shuffle the array } return arr; } From c84c7da30fabd49715ce3345af8c8eb60bf68a50 Mon Sep 17 00:00:00 2001 From: David Leal Date: Fri, 30 Aug 2024 19:23:37 -0600 Subject: [PATCH 20/74] [fix/docs]: improve the Jump Game algorithm (#2514) * [fix/docs]: improve the Jump Game algorithm * fix: pass `index` by reference and `const` it * fix: use previous algorithm * chore: apply suggestions from code review Co-authored-by: Caeden Perelli-Harris Co-authored-by: Piotr Idzik --------- Co-authored-by: Caeden Perelli-Harris Co-authored-by: Piotr Idzik Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- greedy_algorithms/jump_game.cpp | 74 +++++++++++++++++++++++++++++++++ greedy_algorithms/jumpgame.cpp | 68 ------------------------------ 2 files changed, 74 insertions(+), 68 deletions(-) create mode 100644 greedy_algorithms/jump_game.cpp delete mode 100644 greedy_algorithms/jumpgame.cpp diff --git a/greedy_algorithms/jump_game.cpp b/greedy_algorithms/jump_game.cpp new file mode 100644 index 00000000000..4bf126bc783 --- /dev/null +++ b/greedy_algorithms/jump_game.cpp @@ -0,0 +1,74 @@ +/** + * @file + * @brief [Jumping Game](https://leetcode.com/problems/jump-game/) + * algorithm implementation + * @details + * + * Given an array of non-negative integers, you are initially positioned at the + * first index of the array. Each element in the array represents your maximum + * jump length at that position. Determine if you are able to reach the last + * index. This solution takes in input as a vector and output as a boolean to + * check if you can reach the last position. We name the indices good and bad + * based on whether we can reach the destination if we start at that position. + * We initialize the last index as lastPos. + * Here, we start from the end of the array and check if we can ever reach the + * first index. We check if the sum of the index and the maximum jump count + * given is greater than or equal to the lastPos. If yes, then that is the last + * position you can reach starting from the back. After the end of the loop, if + * we reach the lastPos as 0, then the destination can be reached from the start + * position. + * + * @author [Rakshaa Viswanathan](https://github.com/rakshaa2000) + * @author [David Leal](https://github.com/Panquesito7) + */ + +#include /// for assert +#include /// for std::cout +#include /// for std::vector + +/** + * @namespace + * @brief Greedy Algorithms + */ +namespace greedy_algorithms { +/** + * @brief Checks whether the given element (default is `1`) can jump to the last + * index. + * @param nums array of numbers containing the maximum jump (in steps) from that + * index + * @returns true if the index can be reached + * @returns false if the index can NOT be reached + */ +bool can_jump(const std::vector &nums) { + size_t lastPos = nums.size() - 1; + for (size_t i = lastPos; i != static_cast(-1); i--) { + if (i + nums[i] >= lastPos) { + lastPos = i; + } + } + return lastPos == 0; +} +} // namespace greedy_algorithms + +/** + * @brief Function to test the above algorithm + * @returns void + */ +static void test() { + assert(greedy_algorithms::can_jump(std::vector({4, 3, 1, 0, 5}))); + assert(!greedy_algorithms::can_jump(std::vector({3, 2, 1, 0, 4}))); + assert(greedy_algorithms::can_jump(std::vector({5, 9, 4, 7, 15, 3}))); + assert(!greedy_algorithms::can_jump(std::vector({1, 0, 5, 8, 12}))); + assert(greedy_algorithms::can_jump(std::vector({2, 1, 4, 7}))); + + std::cout << "All tests have successfully passed!\n"; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/greedy_algorithms/jumpgame.cpp b/greedy_algorithms/jumpgame.cpp deleted file mode 100644 index 8a890319154..00000000000 --- a/greedy_algorithms/jumpgame.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file - * @brief Implementation of an algorithm to solve the [jumping game]((https://leetcode.com/problems/jump-game/)) problem - * @details - * **Problem statement:** Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index. - * This solution takes in input as a vector and output as a boolean to check if you can reach the last position. - * We name the indices good and bad based on whether we can reach the destination if we start at that position. - * We initialize the last index as lastPos. - * Here, we start from the end of the array and check if we can ever reach the first index. - * We check if the sum of the index and the maximum jump count given is greater than or equal to the lastPos. - * If yes, then that is the last position you can reach starting from the back. - * After the end of the loop, if we reach the lastPos as 0, then the destination can be reached from the start position. - * @author [Rakshaa Viswanathan](https://github.com/rakshaa2000) -*/ - -#include -#include -#include - - - /** - * @brief This function implements the above algorithm - * @param array of numbers containing the maximum jump (in steps) from that index - * @returns bool value whether final index can be reached or not - */ -bool canJump(const std::vector &nums) { - auto lastPos = nums.size() - 1; - for (auto i = nums.size() - 1; i >= 0; i--) { - if (i + nums[i] >= lastPos) { - lastPos = i; - } - } - return lastPos == 0; -} - - -/** - * @brief Function to test above algorithm - * @returns void - */ -static void test(){ - // Test 1 - std::vector num1={4,3,1,0,5}; - assert(canJump(num1)==true); - std::cout<<"Input: "; - for(auto i: num1){ - std::cout< num2={3,2,1,0,4}; - assert(canJump(num2)==false); - std::cout<<"Input: "; - for(auto i: num2){ - std::cout< Date: Sat, 31 Aug 2024 13:05:55 +0900 Subject: [PATCH 21/74] refactor: fix typo in neural_network.cpp (#2689) intialize -> initialize Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- machine_learning/neural_network.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/machine_learning/neural_network.cpp b/machine_learning/neural_network.cpp index 978d658b456..7e20f7a4022 100644 --- a/machine_learning/neural_network.cpp +++ b/machine_learning/neural_network.cpp @@ -136,7 +136,7 @@ class DenseLayer { * @param neurons number of neurons * @param activation activation function for layer * @param kernel_shape shape of kernel - * @param random_kernel flag for whether to intialize kernel randomly + * @param random_kernel flag for whether to initialize kernel randomly */ DenseLayer(const int &neurons, const std::string &activation, const std::pair &kernel_shape, @@ -502,7 +502,7 @@ class NeuralNetwork { auto start = std::chrono::high_resolution_clock::now(); // Start clock double loss = 0, - acc = 0; // Intialize performance metrics with zero + acc = 0; // Initialize performance metrics with zero // For each starting index of batch for (size_t batch_start = 0; batch_start < X.size(); batch_start += batch_size) { @@ -515,7 +515,7 @@ class NeuralNetwork { // They will be averaged and applied to kernel std::vector>> gradients; gradients.resize(this->layers.size()); - // First intialize gradients to zero + // First initialize gradients to zero for (size_t i = 0; i < gradients.size(); i++) { zeroes_initialization( gradients[i], get_shape(this->layers[i].kernel)); @@ -606,7 +606,7 @@ class NeuralNetwork { void evaluate(const std::vector>> &X, const std::vector>> &Y) { std::cout << "INFO: Evaluation Started" << std::endl; - double acc = 0, loss = 0; // intialize performance metrics with zero + double acc = 0, loss = 0; // initialize performance metrics with zero for (size_t i = 0; i < X.size(); i++) { // For every sample in input // Get predictions std::vector> pred = From 9702903a12a0bfe30382c01584e368fa29ae2691 Mon Sep 17 00:00:00 2001 From: SOZEL <80200848+TruongNhanNguyen@users.noreply.github.com> Date: Sat, 31 Aug 2024 16:38:24 +0700 Subject: [PATCH 22/74] Implement Trapped RainWater (#2716) * chore: add `trapped_rainwater.cpp` to DIRECTORY.md * feat: implement Trapped Rain Water algorithm * chore: add links to the trapped rain water problem * chore(docs): remove Trapped Rain Water dir * ref: add edges tests * doc: adding Sozel as author * doc: includes documentatino * ref: use `unsigned int` for height of walls * fix: use fixed-width integers instead of unsigned int * chore: rearrange included libraries --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- dynamic_programming/trapped_rainwater.cpp | 104 ++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 dynamic_programming/trapped_rainwater.cpp diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp new file mode 100644 index 00000000000..8ac80835180 --- /dev/null +++ b/dynamic_programming/trapped_rainwater.cpp @@ -0,0 +1,104 @@ +/** + * @file + * @brief Implementation of the [Trapped Rainwater + * Problem](https://www.geeksforgeeks.org/trapping-rain-water/) + * @details + * This implementation calculates the amount of rainwater that can be trapped + * between walls represented by an array of heights. + * @author [SOZEL](https://github.com/TruongNhanNguyen) + */ + +#include /// For std::min and std::max +#include /// For assert +#include /// For std::size_t +#include /// For integral typedefs +#include /// For std::vector + +/* + * @namespace + * @brief Dynamic Programming Algorithms + */ +namespace dynamic_programming { +/** + * @brief Function to calculate the trapped rainwater + * @param heights Array representing the heights of walls + * @return The amount of trapped rainwater + */ +uint32_t trappedRainwater(const std::vector& heights) { + std::size_t n = heights.size(); + if (n <= 2) + return 0; // No water can be trapped with less than 3 walls + + std::vector leftMax(n), rightMax(n); + + // Calculate the maximum height of wall to the left of each wall + leftMax[0] = heights[0]; + for (std::size_t i = 1; i < n; ++i) { + leftMax[i] = std::max(leftMax[i - 1], heights[i]); + } + + // Calculate the maximum height of wall to the right of each wall + rightMax[n - 1] = heights[n - 1]; + for (std::size_t i = n - 2; i < n; --i) { + rightMax[i] = std::max(rightMax[i + 1], heights[i]); + } + + // Calculate the trapped rainwater between walls + uint32_t trappedWater = 0; + for (std::size_t i = 0; i < n; ++i) { + trappedWater += + std::max(0u, std::min(leftMax[i], rightMax[i]) - heights[i]); + } + + return trappedWater; +} + +} // namespace dynamic_programming + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + std::vector test_basic = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; + assert(dynamic_programming::trappedRainwater(test_basic) == 6); + + std::vector test_peak_under_water = {3, 0, 2, 0, 4}; + assert(dynamic_programming::trappedRainwater(test_peak_under_water) == 7); + + std::vector test_bucket = {5, 1, 5}; + assert(dynamic_programming::trappedRainwater(test_bucket) == 4); + + std::vector test_skewed_bucket = {4, 1, 5}; + assert(dynamic_programming::trappedRainwater(test_skewed_bucket) == 3); + + std::vector test_empty = {}; + assert(dynamic_programming::trappedRainwater(test_empty) == 0); + + std::vector test_flat = {0, 0, 0, 0, 0}; + assert(dynamic_programming::trappedRainwater(test_flat) == 0); + + std::vector test_no_trapped_water = {1, 1, 2, 4, 0, 0, 0}; + assert(dynamic_programming::trappedRainwater(test_no_trapped_water) == 0); + + std::vector test_single_elevation = {5}; + assert(dynamic_programming::trappedRainwater(test_single_elevation) == 0); + + std::vector test_two_point_elevation = {5, 1}; + assert(dynamic_programming::trappedRainwater(test_two_point_elevation) == + 0); + + std::vector test_large_elevation_map_difference = {5, 1, 6, 1, + 7, 1, 8}; + assert(dynamic_programming::trappedRainwater( + test_large_elevation_map_difference) == 15); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} From 502a953e23443c8b3fee07e3d2c37fa6e07017b4 Mon Sep 17 00:00:00 2001 From: Yancey <135342560+Yancey2023@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:17:49 +0800 Subject: [PATCH 23/74] feat: let KMP algorithm return index (#2713) * fix: KMP algorithm (#2712) * feat: let the KMP algorithm return index and add more tests. * feat: format code * Update strings/knuth_morris_pratt.cpp * update knuth_morris_pratt.cpp --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- strings/knuth_morris_pratt.cpp | 117 +++++++++++++++++---------------- 1 file changed, 60 insertions(+), 57 deletions(-) diff --git a/strings/knuth_morris_pratt.cpp b/strings/knuth_morris_pratt.cpp index 41be1561a6a..e266d2c179c 100644 --- a/strings/knuth_morris_pratt.cpp +++ b/strings/knuth_morris_pratt.cpp @@ -1,95 +1,98 @@ /** - * \file - * \brief The [Knuth-Morris-Pratt + * @file + * @brief The [Knuth-Morris-Pratt * Algorithm](https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm) for * finding a pattern within a piece of text with complexity O(n + m) - * + * @details * 1. Preprocess pattern to identify any suffixes that are identical to * prefixes. This tells us where to continue from if we get a mismatch between a * character in our pattern and the text. * 2. Step through the text one character at a time and compare it to a * character in the pattern updating our location within the pattern if * necessary + * @author [Yancey](https://github.com/Yancey2023) */ -#include -#ifdef _MSC_VER -#include // use this for MS Visual C++ -#else -#include -#endif -#include +#include /// for assert +#include /// for IO operations +#include /// for std::string +#include /// for std::vector -/** \namespace string_search - * \brief String search algorithms +/** + * @namespace string_search + * @brief String search algorithms */ namespace string_search { /** - * Generate the partial match table aka failure function for a pattern to + * @brief Generate the partial match table aka failure function for a pattern to * search. - * \param[in] pattern text for which to create the partial match table - * \returns the partial match table as a vector array + * @param pattern text for which to create the partial match table + * @returns the partial match table as a vector array */ -std::vector getFailureArray(const std::string &pattern) { - int pattern_length = pattern.size(); - std::vector failure(pattern_length + 1); - failure[0] = -1; - int j = -1; - +std::vector getFailureArray(const std::string &pattern) { + size_t pattern_length = pattern.size(); + std::vector failure(pattern_length + 1); + failure[0] = std::string::npos; + size_t j = std::string::npos; for (int i = 0; i < pattern_length; i++) { - while (j != -1 && pattern[j] != pattern[i]) { + while (j != std::string::npos && pattern[j] != pattern[i]) { j = failure[j]; } - j++; - failure[i + 1] = j; + failure[i + 1] = ++j; } return failure; } /** - * KMP algorithm to find a pattern in a text - * \param[in] pattern string pattern to search - * \param[in] text text in which to search - * \returns `true` if pattern was found - * \returns `false` if pattern was not found + * @brief KMP algorithm to find a pattern in a text + * @param pattern string pattern to search + * @param text text in which to search + * @returns the starting index of the pattern if found + * @returns `std::string::npos` if not found */ -bool kmp(const std::string &pattern, const std::string &text) { - int text_length = text.size(), pattern_length = pattern.size(); - std::vector failure = getFailureArray(pattern); - - int k = 0; - for (int j = 0; j < text_length; j++) { - while (k != -1 && pattern[k] != text[j]) { +size_t kmp(const std::string &pattern, const std::string &text) { + if (pattern.empty()) { + return 0; + } + std::vector failure = getFailureArray(pattern); + size_t text_length = text.size(); + size_t pattern_length = pattern.size(); + size_t k = 0; + for (size_t j = 0; j < text_length; j++) { + while (k != std::string::npos && pattern[k] != text[j]) { k = failure[k]; } - k++; - if (k == pattern_length) - return true; + if (++k == pattern_length) { + return j - k + 1; + } } - return false; + return std::string::npos; } } // namespace string_search using string_search::kmp; -/** Main function */ -int main() { - std::string text = "alskfjaldsabc1abc1abc12k23adsfabcabc"; - std::string pattern = "abc1abc12l"; - - if (kmp(pattern, text) == true) { - std::cout << "Found" << std::endl; - } else { - std::cout << "Not Found" << std::endl; - } +/** + * @brief self-test implementations + * @returns void + */ +static void tests() { + assert(kmp("abc1abc12l", "alskfjaldsabc1abc1abc12k2") == std::string::npos); + assert(kmp("bca", "abcabc") == 1); + assert(kmp("World", "helloWorld") == 5); + assert(kmp("c++", "his_is_c++") == 7); + assert(kmp("happy", "happy_coding") == 0); + assert(kmp("", "pattern is empty") == 0); - text = "abcabc"; - pattern = "bca"; - if (kmp(pattern, text) == true) { - std::cout << "Found" << std::endl; - } else { - std::cout << "Not Found" << std::endl; - } + // this lets the user know that the tests have passed + std::cout << "All KMP algorithm tests have successfully passed!\n"; +} +/* + * @brief Main function + * @returns 0 on exit + */ +int main() { + tests(); return 0; } From fe41cf4d1131580e9b45fe1c8e8e4ced88a567e9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 09:54:27 +0530 Subject: [PATCH 24/74] docs: update DIRECTORY.md (#2718) Co-authored-by: github-actions[bot] Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- DIRECTORY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index bda68918d88..b78662887c2 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -119,6 +119,7 @@ * [Searching Of Element In Dynamic Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/searching_of_element_in_dynamic_array.cpp) * [Shortest Common Supersequence](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/shortest_common_supersequence.cpp) * [Subset Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/subset_sum.cpp) + * [Trapped Rainwater](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/trapped_rainwater.cpp) * [Tree Height](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/tree_height.cpp) * [Word Break](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/word_break.cpp) @@ -161,7 +162,7 @@ * [Boruvkas Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/boruvkas_minimum_spanning_tree.cpp) * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/dijkstra.cpp) * [Huffman](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/huffman.cpp) - * [Jumpgame](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/jumpgame.cpp) + * [Jump Game](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/jump_game.cpp) * [Knapsack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/knapsack.cpp) * [Kruskals Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/kruskals_minimum_spanning_tree.cpp) * [Prims Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/prims_minimum_spanning_tree.cpp) From 54a20b447efbdf56da7f331de7469e86d50f7dd5 Mon Sep 17 00:00:00 2001 From: SOZEL <80200848+TruongNhanNguyen@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:37:27 +0700 Subject: [PATCH 25/74] Rework on Stack Array Data Structure (#2683) * ref: rework on stack array data structure - The `Stack` class is placed within the `data_structures` namespace - The destructor is added to the Stack class to ensure memory deallocation - Comments are added to the member functions to describe their purpose - The self-test function is provided, which demonstrates the usage of the Stack class * chore(docs): add `namespace` docstring * chore: add `std::out_of_range` exception and test cases when stack is empty * ref: add `full` and `empty` methods * ref: improve stack array implementation - Use TOS instead of stack index - Add tests for overflow and underflow * fix: remove comparision to true from asserts * chore: remove `stack.hpp` * fix: revert * Update data_structures/stack_using_array.cpp * docs: add namespace comment * chore: remove redundant line in docstring of `empty` method --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- data_structures/stack_using_array.cpp | 215 ++++++++++++++++++++------ 1 file changed, 166 insertions(+), 49 deletions(-) diff --git a/data_structures/stack_using_array.cpp b/data_structures/stack_using_array.cpp index 8483d6ad77c..73feaf445cc 100644 --- a/data_structures/stack_using_array.cpp +++ b/data_structures/stack_using_array.cpp @@ -1,62 +1,179 @@ -#include +#include /// For std::assert +#include /// For std::cout +#include /// For std::unique_ptr +#include /// For std::out_of_range -int *stack; -int stack_idx = 0, stack_size; +/** + * @namespace + * @brief data_structures + */ +namespace data_structures { +/** + * @brief Class representation of a stack + * @tparam T The type of the elements in the stack + */ +template +class Stack { + private: + std::unique_ptr stack; ///< Smart pointer to the stack array + int stackSize; ///< Maximum size of the stack + int stackIndex; ///< Index pointing to the top element of the stack -void push(int x) { - if (stack_idx == stack_size) { - std::cout << "\nOverflow"; - } else { - stack[stack_idx++] = x; + public: + /** + * @brief Constructs a new Stack object + * + * @param size Maximum size of the stack + */ + Stack(int size) : stackSize(size), stackIndex(-1), stack(new T[size]) {} + + /** + * @brief Checks if the stack is full + * + * @return true if the stack is full, false otherwise + */ + bool full() const { return stackIndex == stackSize - 1; } + + /** + * @brief Checks if the stack is empty + * @return true if the stack is empty, false otherwise + */ + bool empty() const { return stackIndex == -1; } + + /** + * @brief Pushes an element onto the stack + * + * @param element Element to push onto the stack + */ + void push(T element) { + if (full()) { + throw std::out_of_range("Stack overflow"); + } else { + stack[++stackIndex] = element; + } } -} -void pop() { - if (stack_idx == 0) { - std::cout << "\nUnderflow"; - } else { - std::cout << "\n" << stack[--stack_idx] << " deleted"; + /** + * @brief Pops an element from the stack + * + * @return The popped element + * @throws std::out_of_range if the stack is empty + */ + T pop() { + if (empty()) { + throw std::out_of_range("Stack underflow"); + } + return stack[stackIndex--]; + } + + /** + * @brief Displays all elements in the stack + */ + void show() const { + for (int i = 0; i <= stackIndex; i++) { + std::cout << stack[i] << "\n"; + } } -} -void show() { - for (int i = 0; i < stack_idx; i++) { - std::cout << stack[i] << "\n"; + /** + * @brief Displays the topmost element of the stack + * + * @return The topmost element of the stack + * @throws std::out_of_range if the stack is empty + */ + T topmost() const { + if (empty()) { + throw std::out_of_range("Stack underflow"); + } + return stack[stackIndex]; } -} -void topmost() { std::cout << "\nTopmost element: " << stack[stack_idx - 1]; } -void bottom() { std::cout << "\nBottom element: " << stack[0]; } // If we need access to first element without using pop command -int main() { - std::cout << "\nEnter stack_size of stack : "; - std::cin >> stack_size; - stack = new int[stack_size]; - int ch, x; - do { - std::cout << "\n0. Exit"; - std::cout << "\n1. Push"; - std::cout << "\n2. Pop"; - std::cout << "\n3. Print"; - std::cout << "\n4. Print topmost element:"; - std::cout << "\n5. Print Bottom element:"; - std::cout << "\nEnter Your Choice : "; - std::cin >> ch; - if (ch == 1) { - std::cout << "\nInsert : "; - std::cin >> x; - push(x); - } else if (ch == 2) { - pop(); - } else if (ch == 3) { - show(); - } else if (ch == 4) { - topmost(); - } else if(ch == 5) { - bottom(); + /** + * @brief Displays the bottom element of the stack + * + * @return The bottom element of the stack + * @throws std::out_of_range if the stack is empty + */ + T bottom() const { + if (empty()) { + throw std::out_of_range("Stack underflow"); } - } while (ch != 0); + return stack[0]; + } +}; +} // namespace data_structures + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + data_structures::Stack stack(5); + + // Test empty and full operations + assert(stack.empty()); + assert(!stack.full()); - delete[] stack; + // Test pushing elements and checking topmost + stack.push(10); + assert(stack.topmost() == 10); + stack.push(20); + assert(stack.topmost() == 20); + + stack.push(30); + stack.push(40); + stack.push(50); + assert(stack.full()); + + // Test stack overflow + try { + stack.push(60); + } catch (const std::out_of_range& e) { + assert(std::string(e.what()) == "Stack overflow"); + } + + // Test popping elements + assert(stack.pop() == 50); + assert(stack.pop() == 40); + assert(stack.pop() == 30); + + // Check topmost and bottom elements + assert(stack.topmost() == 20); + assert(stack.bottom() == 10); + + assert(stack.pop() == 20); + assert(stack.pop() == 10); + + assert(stack.empty()); + assert(!stack.full()); + + // Test stack underflow + try { + stack.pop(); + } catch (const std::out_of_range& e) { + assert(std::string(e.what()) == "Stack underflow"); + } + + try { + stack.topmost(); + } catch (const std::out_of_range& e) { + assert(std::string(e.what()) == "Stack underflow"); + } + + try { + stack.bottom(); + } catch (const std::out_of_range& e) { + assert(std::string(e.what()) == "Stack underflow"); + } +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + std::cout << "All tests passed!" << std::endl; return 0; } From 52db277fb686a3232abdff9dd4e76ca999328418 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Mon, 2 Sep 2024 01:03:19 +0200 Subject: [PATCH 26/74] fix: remove memory leak from `iterative_tree_traversals.cpp` (#2720) --- others/iterative_tree_traversals.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/others/iterative_tree_traversals.cpp b/others/iterative_tree_traversals.cpp index 0f9713b0451..11fa1814688 100644 --- a/others/iterative_tree_traversals.cpp +++ b/others/iterative_tree_traversals.cpp @@ -180,6 +180,25 @@ std::vector BinaryTree::inOrderIterative(Node *root) { } return result; } +void deleteAll(Node *root) { + if (root) { + std::stack stack; + stack.push(root); + + while (!stack.empty()) { + const Node *current = stack.top(); + stack.pop(); + + if (current->right) { + stack.push(current->right); + } + if (current->left) { + stack.push(current->left); + } + delete current; + } + } +} } // namespace iterative_tree_traversals } // namespace others @@ -396,5 +415,7 @@ int main() { test6(binaryTree, root); // run inorder-iterative test on negative values std::cout << "\nIn-order test on-negative value Passed!" << std::endl; + deleteAll(root); + return 0; } From db182d55217384912d7e837917d1dbc3ede45637 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Mon, 2 Sep 2024 02:12:33 +0300 Subject: [PATCH 27/74] fix: fix bug in timSort (#2692) * fix: fix bug in timSort * Apply suggestions from code review Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Fix * Update sorting/tim_sort.cpp * Add const --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- sorting/tim_sort.cpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/sorting/tim_sort.cpp b/sorting/tim_sort.cpp index 94f5aa230b3..a9ef0459c0e 100644 --- a/sorting/tim_sort.cpp +++ b/sorting/tim_sort.cpp @@ -1,6 +1,8 @@ // C++ program to perform TimSort. #include +#include #include +#include const int RUN = 32; @@ -8,7 +10,7 @@ const int RUN = 32; // atmost RUN void insertionSort(int arr[], int left, int right) { for (int i = left + 1; i <= right; i++) { - int temp = arr[i]; + const int temp = arr[i]; int j = i - 1; while (arr[j] > temp && j >= left) { arr[j + 1] = arr[j]; @@ -21,7 +23,7 @@ void insertionSort(int arr[], int left, int right) { // merge function merges the sorted runs void merge(int arr[], int l, int m, int r) { // original array is broken in two parts, left and right array - int len1 = m - l + 1, len2 = r - m; + const int len1 = m - l + 1, len2 = r - m; int *left = new int[len1], *right = new int[len2]; for (int i = 0; i < len1; i++) left[i] = arr[l + i]; for (int i = 0; i < len2; i++) right[i] = arr[m + 1 + i]; @@ -74,8 +76,8 @@ void timSort(int arr[], int n) { for (int left = 0; left < n; left += 2 * size) { // find ending point of left sub array // mid+1 is starting point of right sub array - int mid = left + size - 1; - int right = std::min((left + 2 * size - 1), (n - 1)); + const int mid = std::min((left + size - 1), (n - 1)); + const int right = std::min((left + 2 * size - 1), (n - 1)); // merge sub array arr[left.....mid] & arr[mid+1....right] merge(arr, left, mid, right); @@ -89,10 +91,29 @@ void printArray(int arr[], int n) { std::cout << std::endl; } +/** + * @brief self-test implementation + * @returns void + */ +void tests() { + // Case: array of length 65 + constexpr int N = 65; + int arr[N]; + + std::iota(arr, arr + N, 0); + std::reverse(arr, arr + N); + assert(!std::is_sorted(arr, arr + N)); + + timSort(arr, N); + assert(std::is_sorted(arr, arr + N)); +} + // Driver program to test above function int main() { + tests(); // run self test implementations + int arr[] = {5, 21, 7, 23, 19}; - int n = sizeof(arr) / sizeof(arr[0]); + const int n = sizeof(arr) / sizeof(arr[0]); printf("Given Array is\n"); printArray(arr, n); From b6108e494dbd9ef05926fc5e8bc7f60147445ecb Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:42:26 +0200 Subject: [PATCH 28/74] fix: remove memory leak from `recursive_tree_traversal.cpp` (#2721) --- others/recursive_tree_traversal.cpp | 121 +++++++++++++++++----------- 1 file changed, 73 insertions(+), 48 deletions(-) diff --git a/others/recursive_tree_traversal.cpp b/others/recursive_tree_traversal.cpp index ef2720101f4..d80b24a7eed 100644 --- a/others/recursive_tree_traversal.cpp +++ b/others/recursive_tree_traversal.cpp @@ -52,6 +52,7 @@ */ #include /// for assert +#include /// for std::uint64_t #include /// for I/O operations #include /// for vector @@ -76,9 +77,9 @@ namespace recursive_tree_traversals { * @param right follow up right subtree. */ struct Node { - uint64_t data = 0; ///< The value/key of the node. - struct Node *left{}; ///< struct pointer to left subtree. - struct Node *right{}; ///< struct pointer to right subtree. + std::uint64_t data = 0; ///< The value/key of the node. + struct Node *left{}; ///< struct pointer to left subtree. + struct Node *right{}; ///< struct pointer to right subtree. }; /** * @brief BT used to make the entire structure of the binary tree and the @@ -86,23 +87,24 @@ struct Node { */ class BT { public: - std::vector + std::vector inorder_result; // vector to store the inorder traversal of the tree. - std::vector + std::vector preorder_result; // vector to store the preorder traversal of the tree. - std::vector postorder_result; // vector to store the preorder - // traversal of the tree. + std::vector + postorder_result; // vector to store the preorder + // traversal of the tree. Node *createNewNode( - uint64_t); // function that will create new node for insertion. + std::uint64_t); // function that will create new node for insertion. - std::vector inorder( + std::vector inorder( Node *); // function that takes root of the tree as an argument and // returns its inorder traversal. - std::vector preorder( + std::vector preorder( Node *); // function that takes root of the tree as an argument and // returns its preorder traversal. - std::vector postorder( + std::vector postorder( Node *); // function that takes root of the tree as an argument and // returns its postorder traversal. }; @@ -113,7 +115,7 @@ class BT { * @param data value that a particular node will contain. * @return pointer to the newly created node with assigned data. */ -Node *BT::createNewNode(uint64_t data) { +Node *BT::createNewNode(std::uint64_t data) { Node *node = new Node(); node->data = data; node->left = node->right = nullptr; @@ -127,7 +129,7 @@ Node *BT::createNewNode(uint64_t data) { * @param root head/root node of a tree * @return result that is containing the inorder traversal of a tree **/ -std::vector BT::inorder(Node *root) { +std::vector BT::inorder(Node *root) { if (root == nullptr) { // return if the current node is empty return {}; } @@ -147,7 +149,7 @@ std::vector BT::inorder(Node *root) { * @param root head/root node of a tree * @return result that is containing the preorder traversal of a tree */ -std::vector BT::preorder(Node *root) { +std::vector BT::preorder(Node *root) { if (root == nullptr) { // if the current node is empty return {}; } @@ -167,7 +169,7 @@ std::vector BT::preorder(Node *root) { * @param root head/root node of a tree * @return result that is containing the postorder traversal of a tree */ -std::vector BT::postorder(Node *root) { +std::vector BT::postorder(Node *root) { if (root == nullptr) { // if the current node is empty return {}; } @@ -180,6 +182,14 @@ std::vector BT::postorder(Node *root) { return postorder_result; } +void deleteAll(const Node *const root) { + if (root) { + deleteAll(root->left); + deleteAll(root->right); + delete root; + } +} + } // namespace recursive_tree_traversals } // namespace others @@ -200,17 +210,23 @@ void test1() { root->left->right->right = obj1.createNewNode(11); root->right->right->left = obj1.createNewNode(4); - std::vector actual_result_inorder{2, 7, 5, 6, 11, 2, 5, 4, 9}; - std::vector actual_result_preorder{2, 7, 2, 6, 5, 11, 5, 9, 4}; - std::vector actual_result_postorder{2, 5, 11, 6, 7, 4, 9, 5, 2}; - std::vector result_inorder; ///< result stores the inorder - ///< traversal of the binary tree - std::vector result_preorder; ///< result stores the preorder - ///< traversal of the binary tree - std::vector result_postorder; ///< result stores the postorder - ///< traversal of the binary tree - - uint64_t size = actual_result_inorder.size(); + std::vector actual_result_inorder{2, 7, 5, 6, 11, + 2, 5, 4, 9}; + std::vector actual_result_preorder{2, 7, 2, 6, 5, + 11, 5, 9, 4}; + std::vector actual_result_postorder{2, 5, 11, 6, 7, + 4, 9, 5, 2}; + std::vector + result_inorder; ///< result stores the inorder + ///< traversal of the binary tree + std::vector + result_preorder; ///< result stores the preorder + ///< traversal of the binary tree + std::vector + result_postorder; ///< result stores the postorder + ///< traversal of the binary tree + + std::uint64_t size = actual_result_inorder.size(); // Calling inorder() function by passing a root node, // and storing the inorder traversal in result_inorder. @@ -240,6 +256,7 @@ void test1() { std::cout << "Passed!" << std::endl; std::cout << std::endl; + deleteAll(root); } /** @@ -257,17 +274,20 @@ void test2() { root->right->left->left = obj2.createNewNode(7); root->right->left->right = obj2.createNewNode(8); - std::vector actual_result_inorder{4, 2, 1, 7, 5, 8, 3, 6}; - std::vector actual_result_preorder{1, 2, 4, 3, 5, 7, 8, 6}; - std::vector actual_result_postorder{4, 2, 7, 8, 5, 6, 3, 1}; - std::vector result_inorder; ///< result stores the inorder - ///< traversal of the binary tree - std::vector result_preorder; ///< result stores the preorder - ///< traversal of the binary tree - std::vector result_postorder; ///< result stores the postorder - ///< traversal of the binary tree - - uint64_t size = actual_result_inorder.size(); + std::vector actual_result_inorder{4, 2, 1, 7, 5, 8, 3, 6}; + std::vector actual_result_preorder{1, 2, 4, 3, 5, 7, 8, 6}; + std::vector actual_result_postorder{4, 2, 7, 8, 5, 6, 3, 1}; + std::vector + result_inorder; ///< result stores the inorder + ///< traversal of the binary tree + std::vector + result_preorder; ///< result stores the preorder + ///< traversal of the binary tree + std::vector + result_postorder; ///< result stores the postorder + ///< traversal of the binary tree + + std::uint64_t size = actual_result_inorder.size(); // Calling inorder() function by passing a root node, // and storing the inorder traversal in result_inorder. @@ -297,6 +317,7 @@ void test2() { std::cout << "Passed!" << std::endl; std::cout << std::endl; + deleteAll(root); } /** @@ -311,17 +332,20 @@ void test3() { root->left->left = obj3.createNewNode(4); root->left->right = obj3.createNewNode(5); - std::vector actual_result_inorder{4, 2, 5, 1, 3}; - std::vector actual_result_preorder{1, 2, 4, 5, 3}; - std::vector actual_result_postorder{4, 5, 2, 3, 1}; - std::vector result_inorder; ///< result stores the inorder - ///< traversal of the binary tree - std::vector result_preorder; ///< result stores the preorder - ///< traversal of the binary tree - std::vector result_postorder; ///< result stores the postorder - ///< traversal of the binary tree - - uint64_t size = actual_result_inorder.size(); + std::vector actual_result_inorder{4, 2, 5, 1, 3}; + std::vector actual_result_preorder{1, 2, 4, 5, 3}; + std::vector actual_result_postorder{4, 5, 2, 3, 1}; + std::vector + result_inorder; ///< result stores the inorder + ///< traversal of the binary tree + std::vector + result_preorder; ///< result stores the preorder + ///< traversal of the binary tree + std::vector + result_postorder; ///< result stores the postorder + ///< traversal of the binary tree + + std::uint64_t size = actual_result_inorder.size(); // Calling inorder() function by passing a root node, // and storing the inorder traversal in result_inorder. @@ -352,6 +376,7 @@ void test3() { std::cout << "Passed!" << std::endl; std::cout << std::endl; + deleteAll(root); } /** From c652c4f2378275dc32c387148c2eaaf49b3f7bd7 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:44:49 +0200 Subject: [PATCH 29/74] fix: stack buffer underflow in `tim_sort.cpp` (#2722) --- sorting/tim_sort.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sorting/tim_sort.cpp b/sorting/tim_sort.cpp index a9ef0459c0e..03ccf3808e0 100644 --- a/sorting/tim_sort.cpp +++ b/sorting/tim_sort.cpp @@ -12,7 +12,7 @@ void insertionSort(int arr[], int left, int right) { for (int i = left + 1; i <= right; i++) { const int temp = arr[i]; int j = i - 1; - while (arr[j] > temp && j >= left) { + while (j >= left && arr[j] > temp) { arr[j + 1] = arr[j]; j--; } @@ -92,7 +92,7 @@ void printArray(int arr[], int n) { } /** - * @brief self-test implementation + * @brief self-test implementation * @returns void */ void tests() { @@ -110,7 +110,7 @@ void tests() { // Driver program to test above function int main() { - tests(); // run self test implementations + tests(); // run self test implementations int arr[] = {5, 21, 7, 23, 19}; const int n = sizeof(arr) / sizeof(arr[0]); From 490974eeb32f989b19b277acee3366bfead686d9 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Wed, 4 Sep 2024 02:01:30 +0200 Subject: [PATCH 30/74] fix: memory leak in `median_search2.cpp` (#2723) --- search/median_search2.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/search/median_search2.cpp b/search/median_search2.cpp index 2e9b04f9f10..bec6959d838 100644 --- a/search/median_search2.cpp +++ b/search/median_search2.cpp @@ -73,6 +73,13 @@ ListNode* middleNode(ListNode* head) { return (fastptr->next) ? slowptr->next : slowptr; } + +void deleteAll(const ListNode* const head) { + if (head) { + deleteAll(head->next); + delete head; + } +} } // namespace median_search2 } // namespace search @@ -98,6 +105,7 @@ static void test() { ListNode* median = search::median_search2::middleNode(head1); assert(3 == median->val); // 3 is the value of the median node. + search::median_search2::deleteAll(head1); std::cout << "test case:1 passed\n"; // Test case # 2 @@ -118,14 +126,9 @@ static void test() { ListNode* median1 = search::median_search2::middleNode(head2); assert(4 == median1->val); // 4 is the value of the median node. + search::median_search2::deleteAll(head2); std::cout << "test case:2 passed\n"; - delete head1; - delete temp; - - delete head2; - delete temp2; - std::cout << "--All tests passed--\n"; } From ef209dfab3622b6aafc7b41115de2c5c13b8944d Mon Sep 17 00:00:00 2001 From: Sebastian Skonieczny <58781463+sebe324@users.noreply.github.com> Date: Wed, 4 Sep 2024 16:44:41 -0700 Subject: [PATCH 31/74] Added Iterative Quick Sort (#2684) * feat: Added iterative quick sort using stack * fix: Forgot to add @param for sort function * Update sorting/quick_sort_iterative.cpp * Update sorting/quick_sort_iterative.cpp * Update sorting/quick_sort_iterative.cpp * style: space b/w for and comment * Update sorting/quick_sort_iterative.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update sorting/quick_sort_iterative.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * fixed namespace error --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- sorting/quick_sort_iterative.cpp | 132 +++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 sorting/quick_sort_iterative.cpp diff --git a/sorting/quick_sort_iterative.cpp b/sorting/quick_sort_iterative.cpp new file mode 100644 index 00000000000..da506c9c024 --- /dev/null +++ b/sorting/quick_sort_iterative.cpp @@ -0,0 +1,132 @@ +/** + * @file + * @brief Quick Sort without recursion. This method uses the stack instead. + * Both recursive and iterative implementations have O(n log n) best case + * and O(n^2) worst case. + * @details + * https://stackoverflow.com/questions/12553238/quicksort-iterative-or-recursive + * https://en.wikipedia.org/wiki/Quicksort + * https://www.geeksforgeeks.org/iterative-quick-sort/ + * @author [Sebe324](https://github.com/sebe324) + */ + +#include /// for std::cout +#include /// for std::vector +#include /// for std::stack +#include /// for std::is_sorted +#include /// for assert + + +/** + * @namespace sorting + * @brief Sorting algorithms + */ +namespace sorting { +/** + * @brief The partition function sorts the array from + * start to end and uses the last element as the pivot. + * @param arr the array to be sorted + * @param start starting index + * @param end ending index + * @return int next index of the pivot + */ +int partition(std::vector &arr, int start, int end) +{ + int pivot = arr[end]; + int index = start - 1; + + for (int j = start; j < end; j++) { + if (arr[j] <= pivot) { + std::swap(arr[++index], arr[j]); + } + } + + std::swap(arr[index + 1], arr[end]); + return index + 1; +} + +/** + * @brief The main sorting function + * @details The iterative quick sort uses + * the stack instead of recursion for saving + * and restoring the environment between calls. + * It does not need the end and start params, because + * it is not recursive. + * @param arr array to be sorted + * @return void + */ +void iterativeQuickSort(std::vector &arr) +{ + std::stack stack; + int start = 0; + int end = arr.size()-1; + stack.push(start); + stack.push(end); + + while(!stack.empty()) + { + end = stack.top(); + stack.pop(); + start = stack.top(); + stack.pop(); + + int pivotIndex = partition(arr,start,end); + + if(pivotIndex -1 > start) + { + stack.push(start); + stack.push(pivotIndex-1); + } + + if(pivotIndex+1 case1={100,534,1000000,553,10,61,2000,238,2756,9,12,56,30}; + std::cout<<"TEST 1\n"; + std::cout<<"Before: \n"; + for(auto x : case1) std::cout< case2={-10,-2,-5,-2,-3746,-785,-123, -452, -32456}; + std::cout<<"TEST 2\n"; + std::cout<<"Before: \n"; + for(auto x : case2) std::cout< Date: Thu, 5 Sep 2024 01:54:16 +0200 Subject: [PATCH 32/74] style: add missing `const` in `bloom_filter.cpp` (#2724) Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- data_structures/bloom_filter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/bloom_filter.cpp b/data_structures/bloom_filter.cpp index 8ce1a0c78a1..e2f7372e0c4 100644 --- a/data_structures/bloom_filter.cpp +++ b/data_structures/bloom_filter.cpp @@ -228,13 +228,13 @@ static void test_bloom_filter_string() { 10, {data_structures::hashDJB2, data_structures::hashStr}); std::vector toCheck{"hello", "world", "!"}; std::vector toFalse{"false", "world2", "!!!"}; - for (auto& x : toCheck) { + for (const auto& x : toCheck) { filter.add(x); } - for (auto& x : toFalse) { + for (const auto& x : toFalse) { assert(filter.contains(x) == false); } - for (auto& x : toCheck) { + for (const auto& x : toCheck) { assert(filter.contains(x)); } } From d74f4d33ea84ef2ff618f09d592aa05effecb3d1 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Wed, 11 Sep 2024 03:25:42 +0200 Subject: [PATCH 33/74] fix: memory leak in `huffman.cpp` (#2728) --- greedy_algorithms/huffman.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/greedy_algorithms/huffman.cpp b/greedy_algorithms/huffman.cpp index 21c8295f3dd..a63007422dd 100644 --- a/greedy_algorithms/huffman.cpp +++ b/greedy_algorithms/huffman.cpp @@ -23,6 +23,14 @@ struct MinHeapNode { } }; +void deleteAll(const MinHeapNode* const root) { + if (root) { + deleteAll(root->left); + deleteAll(root->right); + delete root; + } +} + // For comparison of // two heap nodes (needed in min heap) struct compare { @@ -85,6 +93,7 @@ void HuffmanCodes(char data[], int freq[], int size) { // Print Huffman codes using // the Huffman tree built above printCodes(minHeap.top(), ""); + deleteAll(minHeap.top()); } // Driver program to test above functions From 7828b8e238ecff9b13f2ac4c4b863ece0e917981 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:30:09 +0200 Subject: [PATCH 34/74] fix: memory leak in `morrisinorder.cpp` (#2729) --- data_structures/morrisinorder.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/data_structures/morrisinorder.cpp b/data_structures/morrisinorder.cpp index f1f9e068c9f..c667ccf13fa 100644 --- a/data_structures/morrisinorder.cpp +++ b/data_structures/morrisinorder.cpp @@ -81,6 +81,14 @@ void morrisInorder(Btree *root) { } } +void deleteAll(const Btree *const root) { + if (root) { + deleteAll(root->left); + deleteAll(root->right); + delete root; + } +} + int main() { // Testing morrisInorder funtion Btree *root = NULL; @@ -88,5 +96,6 @@ int main() { for (i = 1; i <= 7; i++) insert(&root, i); cout << "Morris Inorder: "; morrisInorder(root); + deleteAll(root); return 0; } From b169269c941ee9771db32186a290d13e66a2d923 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Fri, 13 Sep 2024 04:32:43 +0200 Subject: [PATCH 35/74] fix: remove memory leak from `reverse_binary_tree.cpp` (#2730) --- .../reverse_binary_tree.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/operations_on_datastructures/reverse_binary_tree.cpp b/operations_on_datastructures/reverse_binary_tree.cpp index 46b742efcb0..613744b3e49 100644 --- a/operations_on_datastructures/reverse_binary_tree.cpp +++ b/operations_on_datastructures/reverse_binary_tree.cpp @@ -91,6 +91,9 @@ class BinaryTree { return pivot; } + BinaryTree(const BinaryTree&) = delete; + BinaryTree& operator=(const BinaryTree&) = delete; + public: /** * @brief Creates a BinaryTree with a root pointing to NULL. @@ -100,6 +103,21 @@ class BinaryTree { * @brief Creates a BinaryTree with a root with an initial value. */ explicit BinaryTree(int64_t data) { root = new Node(data); } + + ~BinaryTree() { + std::vector nodes; + nodes.emplace_back(root); + while (!nodes.empty()) { + const auto cur_node = nodes.back(); + nodes.pop_back(); + if (cur_node) { + nodes.emplace_back(cur_node->left); + nodes.emplace_back(cur_node->right); + delete cur_node; + } + } + } + /** * @brief Adds a new Node to the Binary Tree */ From 920b6d4e81c041f03b385a1f042f0260d4be3e50 Mon Sep 17 00:00:00 2001 From: Monalisa0311 <100229305+Monalisa0311@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:23:29 +0530 Subject: [PATCH 36/74] Added test cases in greedy_algorithms\kruskals_minimum_spanning_tree.cpp (#2727) * Added test cases in greedy_algorithms\kruskals_minimum_spanning_tree.cpp * Update kruskals_minimum_spanning_tree.cpp test case1 & 2 changed * Update kruskals_minimum_spanning_tree.cpp test-case1 changed * Update kruskals_minimum_spanning_tree.cpp All test case formatting changes * Update kruskals_minimum_spanning_tree.cpp unit-32 test case added * Update kruskals_minimum_spanning_tree.cpp added new line * Update kruskals_minimum_spanning_tree.cpp Formatting changed * Update kruskals_minimum_spanning_tree.cpp move infinity valued inside test --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- .../kruskals_minimum_spanning_tree.cpp | 147 ++++++++++++++++-- 1 file changed, 133 insertions(+), 14 deletions(-) diff --git a/greedy_algorithms/kruskals_minimum_spanning_tree.cpp b/greedy_algorithms/kruskals_minimum_spanning_tree.cpp index 7925eb0373e..ed7fc831657 100644 --- a/greedy_algorithms/kruskals_minimum_spanning_tree.cpp +++ b/greedy_algorithms/kruskals_minimum_spanning_tree.cpp @@ -20,6 +20,8 @@ #include /// for array #include /// for IO operations +#include /// for numeric limits +#include /// for uint32_t /** * @namespace @@ -32,14 +34,19 @@ namespace greedy_algorithms { * @param graph The graph that will be used to find the edge * @returns void */ -template -void findMinimumEdge(const int &infinity, - const std::array, 6> &graph) { +template +void findMinimumEdge(const T &infinity, + const std::array, M> &graph) { + if (N != M) { + std::cout << "\nWrong input passed. Provided array has dimensions " << N + << "x" << M << ". Please provide a square matrix.\n"; + return; + } for (int i = 0; i < graph.size(); i++) { int min = infinity; int minIndex = 0; for (int j = 0; j < graph.size(); j++) { - if (graph[i][j] != 0 && graph[i][j] < min) { + if (i != j && graph[i][j] != 0 && graph[i][j] < min) { min = graph[i][j]; minIndex = j; } @@ -50,20 +57,132 @@ void findMinimumEdge(const int &infinity, } } // namespace greedy_algorithms +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + /** + * define a large value for int + * define a large value for float + * define a large value for double + * define a large value for uint32_t + */ + constexpr int INFINITY_INT = std::numeric_limits::max(); + constexpr float INFINITY_FLOAT = std::numeric_limits::max(); + constexpr double INFINITY_DOUBLE = std::numeric_limits::max(); + constexpr uint32_t INFINITY_UINT32 = UINT32_MAX; + + // Test case with integer values + std::cout << "\nTest Case 1 :\n"; + std::array, 6> graph1{ + 0, 4, 1, 4, INFINITY_INT, INFINITY_INT, + 4, 0, 3, 8, 3, INFINITY_INT, + 1, 3, 0, INFINITY_INT, 1, INFINITY_INT, + 4, 8, INFINITY_INT, 0, 5, 7, + INFINITY_INT, 3, 1, 5, 0, INFINITY_INT, + INFINITY_INT, INFINITY_INT, INFINITY_INT, 7, INFINITY_INT, 0}; + greedy_algorithms::findMinimumEdge(INFINITY_INT, graph1); + + // Test case with floating values + std::cout << "\nTest Case 2 :\n"; + std::array, 3> graph2{ + 0.0f, 2.5f, INFINITY_FLOAT, + 2.5f, 0.0f, 3.2f, + INFINITY_FLOAT, 3.2f, 0.0f}; + greedy_algorithms::findMinimumEdge(INFINITY_FLOAT, graph2); + + // Test case with double values + std::cout << "\nTest Case 3 :\n"; + std::array, 5> graph3{ + 0.0, 10.5, INFINITY_DOUBLE, 6.7, 3.3, + 10.5, 0.0, 8.1, 15.4, INFINITY_DOUBLE, + INFINITY_DOUBLE, 8.1, 0.0, INFINITY_DOUBLE, 7.8, + 6.7, 15.4, INFINITY_DOUBLE, 0.0, 9.9, + 3.3, INFINITY_DOUBLE, 7.8, 9.9, 0.0}; + greedy_algorithms::findMinimumEdge(INFINITY_DOUBLE, graph3); + + // Test Case with negative weights + std::cout << "\nTest Case 4 :\n"; + std::array, 3> graph_neg{ + 0, -2, 4, + -2, 0, 3, + 4, 3, 0}; + greedy_algorithms::findMinimumEdge(INFINITY_INT, graph_neg); + + // Test Case with Self-Loops + std::cout << "\nTest Case 5 :\n"; + std::array, 3> graph_self_loop{ + 2, 1, INFINITY_INT, + INFINITY_INT, 0, 4, + INFINITY_INT, 4, 0}; + greedy_algorithms::findMinimumEdge(INFINITY_INT, graph_self_loop); + + // Test Case with no edges + std::cout << "\nTest Case 6 :\n"; + std::array, 4> no_edges{ + 0, INFINITY_INT, INFINITY_INT, INFINITY_INT, + INFINITY_INT, 0, INFINITY_INT, INFINITY_INT, + INFINITY_INT, INFINITY_INT, 0, INFINITY_INT, + INFINITY_INT, INFINITY_INT, INFINITY_INT, 0}; + greedy_algorithms::findMinimumEdge(INFINITY_INT, no_edges); + + // Test Case with a non-connected graph + std::cout << "\nTest Case 7:\n"; + std::array, 4> partial_graph{ + 0, 2, INFINITY_INT, 6, + 2, 0, 3, INFINITY_INT, + INFINITY_INT, 3, 0, 4, + 6, INFINITY_INT, 4, 0}; + greedy_algorithms::findMinimumEdge(INFINITY_INT, partial_graph); + + // Test Case with Directed weighted graph. The Krushkal algorithm does not give + // optimal answer + std::cout << "\nTest Case 8:\n"; + std::array, 4> directed_graph{ + 0, 3, 7, INFINITY_INT, // Vertex 0 has edges to Vertex 1 and Vertex 2 + INFINITY_INT, 0, 2, 5, // Vertex 1 has edges to Vertex 2 and Vertex 3 + INFINITY_INT, INFINITY_INT, 0, 1, // Vertex 2 has an edge to Vertex 3 + INFINITY_INT, INFINITY_INT, INFINITY_INT, 0}; // Vertex 3 has no outgoing edges + greedy_algorithms::findMinimumEdge(INFINITY_INT, directed_graph); + + // Test case with wrong input passed + std::cout << "\nTest Case 9:\n"; + std::array, 3> graph9{ + 0, 5, 5, 5, + 5, 0, 5, 5, + 5, 5, 5, 5}; + greedy_algorithms::findMinimumEdge(INFINITY_INT, graph9); + + // Test case with all the same values between every edge + std::cout << "\nTest Case 10:\n"; + std::array, 5> graph10{ + 0, 5, 5, 5, 5, + 5, 0, 5, 5, 5, + 5, 5, 0, 5, 5, + 5, 5, 5, 0, 5, + 5, 5, 5, 5, 0}; + greedy_algorithms::findMinimumEdge(INFINITY_INT, graph10); + + // Test Case with uint32_t values + std::cout << "\nTest Case 11 :\n"; + std::array, 4> graph_uint32{ + 0, 5, INFINITY_UINT32, 9, + 5, 0, 2, INFINITY_UINT32, + INFINITY_UINT32, 2, 0, 6, + 9, INFINITY_UINT32, 6, 0}; + greedy_algorithms::findMinimumEdge(INFINITY_UINT32, graph_uint32); + + std::cout << "\nAll tests have successfully passed!\n"; +} + /** * @brief Main function * @returns 0 on exit */ + int main() { - constexpr int INFINITY = 99999; - std::array, 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}; - - greedy_algorithms::findMinimumEdge(INFINITY, graph); + test(); // run Self-test implementation return 0; } + From 8df7a884f501ca650d08d9942fe3b6e47545592a Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sat, 14 Sep 2024 01:39:03 +0200 Subject: [PATCH 37/74] fix: remove memory leak from `circular_queue_using_linked_list.cpp` (#2731) --- .../circular_queue_using_linked_list.cpp | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/data_structures/circular_queue_using_linked_list.cpp b/data_structures/circular_queue_using_linked_list.cpp index 3d92b3b3ebe..41b55926430 100644 --- a/data_structures/circular_queue_using_linked_list.cpp +++ b/data_structures/circular_queue_using_linked_list.cpp @@ -5,11 +5,21 @@ struct node { struct node* next; }; class Queue { - node* front=nullptr; - node* rear=nullptr; + node* front = nullptr; + node* rear = nullptr; -public: - Queue() = default; + Queue(const Queue&) = delete; + Queue& operator=(const Queue&) = delete; + + public: + Queue() = default; + ~Queue() { + while (front) { + dequeue(); + } + } + + private: void createNode(int val) { auto* nn = new node; nn->data = val; @@ -17,13 +27,13 @@ class Queue { front = nn; rear = nn; } + + public: void enqueue(int val) { if (front == nullptr || rear == nullptr) { createNode(val); - } - else { - node* nn; - nn = new node; + } else { + node* nn = new node; nn->data = val; rear->next = nn; nn->next = front; @@ -31,23 +41,29 @@ class Queue { } } void dequeue() { - node* n; - n = front; - if (n) { + if (front == nullptr) { + return; + } + const node* const n = front; + if (front == rear) { + front = nullptr; + rear = nullptr; + } else { front = front->next; - delete n; + rear->next = front; } + delete n; } void traverse() { - node* ptr; - ptr = front; - if (ptr) { - do { - std::cout << ptr->data << " "; - ptr = ptr->next; - } while (ptr != rear->next); - std::cout << front->data << std::endl; + if (front == nullptr) { + return; } + const node* ptr = front; + do { + std::cout << ptr->data << ' '; + ptr = ptr->next; + } while (ptr != front); + std::cout << '\n'; } }; int main(void) { From a0b7dee79ec0523534bee9b0131bb60b1e0d76fe Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sun, 15 Sep 2024 10:54:44 +0200 Subject: [PATCH 38/74] style: lint `huffman.cpp` (#2733) --- greedy_algorithms/huffman.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/greedy_algorithms/huffman.cpp b/greedy_algorithms/huffman.cpp index a63007422dd..a520d683010 100644 --- a/greedy_algorithms/huffman.cpp +++ b/greedy_algorithms/huffman.cpp @@ -34,16 +34,15 @@ void deleteAll(const MinHeapNode* const root) { // For comparison of // two heap nodes (needed in min heap) struct compare { - bool operator()(MinHeapNode* l, MinHeapNode* r) - - { - return (l->freq > r->freq); + bool operator()(const MinHeapNode* const l, + const MinHeapNode* const r) const { + return l->freq > r->freq; } }; // Prints huffman codes from // the root of Huffman Tree. -void printCodes(struct MinHeapNode* root, string str) { +void printCodes(struct MinHeapNode* root, const string& str) { if (!root) return; @@ -56,8 +55,8 @@ void printCodes(struct MinHeapNode* root, string str) { // The main function that builds a Huffman Tree and // print codes by traversing the built Huffman Tree -void HuffmanCodes(char data[], int freq[], int size) { - struct MinHeapNode *left, *right, *top; +void HuffmanCodes(const char data[], const int freq[], int size) { + struct MinHeapNode *left, *right; // Create a min heap & inserts all characters of data[] priority_queue, compare> minHeap; @@ -82,7 +81,7 @@ void HuffmanCodes(char data[], int freq[], int size) { // of this new node. Add this node // to the min heap '$' is a special value // for internal nodes, not used - top = new MinHeapNode('$', left->freq + right->freq); + auto* const top = new MinHeapNode('$', left->freq + right->freq); top->left = left; top->right = right; From 9374b003198ef1c800704fa094bb3746de5d32d9 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:24:35 +0200 Subject: [PATCH 39/74] style: add missing `const` in `median_search2.cpp` (#2734) --- search/median_search2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/search/median_search2.cpp b/search/median_search2.cpp index bec6959d838..d10fe9cbf0e 100644 --- a/search/median_search2.cpp +++ b/search/median_search2.cpp @@ -103,7 +103,7 @@ static void test() { } temp->next = nullptr; - ListNode* median = search::median_search2::middleNode(head1); + const ListNode* const median = search::median_search2::middleNode(head1); assert(3 == median->val); // 3 is the value of the median node. search::median_search2::deleteAll(head1); std::cout << "test case:1 passed\n"; @@ -124,7 +124,7 @@ static void test() { } temp2->next = nullptr; - ListNode* median1 = search::median_search2::middleNode(head2); + const ListNode* const median1 = search::median_search2::middleNode(head2); assert(4 == median1->val); // 4 is the value of the median node. search::median_search2::deleteAll(head2); std::cout << "test case:2 passed\n"; From f789e3bb9e0f8c321e0de0cb482acf11580281bd Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sun, 29 Sep 2024 15:54:02 +0200 Subject: [PATCH 40/74] style: cleanup `catalan_numbers.cpp` (#2740) * style: cleanup `catalan_numbers.cpp` * docs: update file level docs * style: use `std::transform_reduce` --- dynamic_programming/catalan_numbers.cpp | 134 +++++++++++++----------- 1 file changed, 70 insertions(+), 64 deletions(-) diff --git a/dynamic_programming/catalan_numbers.cpp b/dynamic_programming/catalan_numbers.cpp index f5edaa916eb..c99ea00265c 100644 --- a/dynamic_programming/catalan_numbers.cpp +++ b/dynamic_programming/catalan_numbers.cpp @@ -1,75 +1,81 @@ -/** Print all the Catalan numbers from 0 to n, n being the user input. - - * A Catalan number satifies the following two properties: - * C(0) = C(1) = 1; C(n) = sum(C(i).C(n-i-1)), from i = 0 to n-1 +/** + * @file + * @brief Provides utilities to compute Catalan numbers using dynamic + programming. + * A Catalan numbers satisfy these recurrence relations: + * C(0) = C(1) = 1; C(n) = sum(C(i).C(n-i-1)), for i = 0 to n-1 * Read more about Catalan numbers here: https://en.wikipedia.org/wiki/Catalan_number + https://oeis.org/A000108/ */ -#include -using namespace std; - -int *cat; // global array to hold catalan numbers - -unsigned long int catalan_dp(int n) { - /** Using the tabulation technique in dynamic programming, - this function computes the first `n+1` Catalan numbers - - Parameter - --------- - n: The number of catalan numbers to be computed. +#include /// for assert +#include /// for std::uint64_t +#include /// for std::size_t +#include /// for std::transform_reduce +#include /// for std::vector - Returns - ------- - cat[n]: An array containing the first `n+1` Catalan numbers - */ - - // By definition, the first two Catalan numbers are 1 - cat[0] = cat[1] = 1; - - // Compute the remaining numbers from index 2 to index n, using tabulation - for (int i = 2; i <= n; i++) { - cat[i] = 0; - for (int j = 0; j < i; j++) - cat[i] += cat[j] * cat[i - j - 1]; // applying the definition here +/** + * @brief computes and caches Catalan numbers + */ +class catalan_numbers { + using value_type = std::uint64_t; + std::vector known{1, 1}; + + value_type compute_next() { + return std::transform_reduce(known.begin(), known.end(), known.rbegin(), + static_cast(), std::plus<>(), + std::multiplies<>()); } - // Return the result - return cat[n]; -} - -int main(int argc, char *argv[]) { - int n; - cout << "Enter n: "; - cin >> n; - - cat = new int[n + 1]; - - cout << "Catalan numbers from 0 to " << n << " are:\n"; - for (int i = 0; i <= n; i++) { - cout << "catalan (" << i << ") = " << catalan_dp(i) << endl; - // NOTE: Since `cat` is a global array, calling `catalan_dp` - // repeatedly will not recompute the the values already computed - // as in case of pre-computed values, the array will simply return them, - // instead of recomputing them. + void add() { known.push_back(this->compute_next()); } + + public: + /** + * @brief computes the n-th Catalan number and updates the cache. + * @return the n-th Catalan number + */ + value_type get(std::size_t n) { + while (known.size() <= n) { + this->add(); + } + return known[n]; } - - return 0; +}; + +void test_catalan_numbers_up_to_20() { + // data verified with https://oeis.org/A000108/ + catalan_numbers cn; + assert(cn.get(0) == 1ULL); + assert(cn.get(1) == 1ULL); + assert(cn.get(2) == 2ULL); + assert(cn.get(3) == 5ULL); + assert(cn.get(4) == 14ULL); + assert(cn.get(5) == 42ULL); + assert(cn.get(6) == 132ULL); + assert(cn.get(7) == 429ULL); + assert(cn.get(8) == 1430ULL); + assert(cn.get(9) == 4862ULL); + assert(cn.get(10) == 16796ULL); + assert(cn.get(11) == 58786ULL); + assert(cn.get(12) == 208012ULL); + assert(cn.get(13) == 742900ULL); + assert(cn.get(14) == 2674440ULL); + assert(cn.get(15) == 9694845ULL); + assert(cn.get(16) == 35357670ULL); + assert(cn.get(17) == 129644790ULL); + assert(cn.get(18) == 477638700ULL); + assert(cn.get(19) == 1767263190ULL); + assert(cn.get(20) == 6564120420ULL); } -/** Sample Test Case: - -$ cd "Dynamic Programming" -$ g++ Catalan-Numbers.cpp -$ ./a.exe - -Enter n: 5 -Catalan numbers from 0 to 5 are: -catalan (0) = 1 -catalan (1) = 1 -catalan (2) = 2 -catalan (3) = 5 -catalan (4) = 14 -catalan (5) = 42 +void test_catalan_numbers_25() { + // data verified with https://oeis.org/A000108/ + catalan_numbers cn; + assert(cn.get(25) == 4861946401452ULL); +} -*/ +int main() { + test_catalan_numbers_up_to_20(); + test_catalan_numbers_25(); +} From cde1672dca14968f9e914258bed495ff70b475f8 Mon Sep 17 00:00:00 2001 From: Nguyen Phuc Chuong <72879387+hollowcrust@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:09:03 +0800 Subject: [PATCH 41/74] feat: Create gray_code.cpp (#2750) * Create gray_code.cpp * Update gray_code.cpp Remove extra lines, add bit_manipulation and gray_code namespaces, add negative number test --- bit_manipulation/gray_code.cpp | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 bit_manipulation/gray_code.cpp diff --git a/bit_manipulation/gray_code.cpp b/bit_manipulation/gray_code.cpp new file mode 100644 index 00000000000..952758dea23 --- /dev/null +++ b/bit_manipulation/gray_code.cpp @@ -0,0 +1,113 @@ +/** + * @brief Program to generate n-bit [Gray + * code](https://en.wikipedia.org/wiki/Gray_code) + * + * @details + * Gray code is a binary numeral system + * where consecutive values differ in exactly 1 bit. + * The following code offers one of many possible Gray codes + * given some pre-determined number of bits. + */ + +#include /// for gray code representation +#include /// for assert +#include /// for IO operations +#include /// for vector data structure + +/** + * @namespace bit_manipulation + * @brief Bit manipulation algorithms + */ +namespace bit_manipulation { +/** + * @namespace gray_code + * @brief Generate n-bit Gray code + */ +namespace gray_code { +/** + * @brief The main function to generate n-bit Gray code + * + * @param n Number of bits + * @return A vector that stores the n-bit Gray code + */ +std::vector> gray_code_generation(int n) { + std::vector> gray_code = {}; // Initialise empty vector + + // No Gray codes for non-positive values of n + if (n <= 0) { + return gray_code; + } + + int total_codes = 1 << n; // Number of n-bit gray codes + + for (int i = 0; i < total_codes; i++) { + int gray_num = i ^ (i >> 1); // Gray code formula + gray_code.push_back(std::bitset<32>(gray_num)); // Store the value + } + + return gray_code; +} +} // namespace gray_code +} // namespace bit_manipulation + +/** + * @brief Self-test implementation + * + * @returns void + */ +static void test() { + std::vector> gray_code_negative_1 = {}; + + std::vector> gray_code_0 = {}; + + std::vector> gray_code_1 = { + std::bitset<32>(0), std::bitset<32>(1) + }; + + std::vector> gray_code_2 = { + std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2) + }; + + std::vector> gray_code_3 = { + std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2), + std::bitset<32>(6), std::bitset<32>(7), std::bitset<32>(5), std::bitset<32>(4) + }; + + std::vector> gray_code_4 = { + std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2), + std::bitset<32>(6), std::bitset<32>(7), std::bitset<32>(5), std::bitset<32>(4), + std::bitset<32>(12), std::bitset<32>(13), std::bitset<32>(15), std::bitset<32>(14), + std::bitset<32>(10), std::bitset<32>(11), std::bitset<32>(9), std::bitset<32>(8) + }; + + std::vector> gray_code_5 = { + std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2), + std::bitset<32>(6), std::bitset<32>(7), std::bitset<32>(5), std::bitset<32>(4), + std::bitset<32>(12), std::bitset<32>(13), std::bitset<32>(15), std::bitset<32>(14), + std::bitset<32>(10), std::bitset<32>(11), std::bitset<32>(9), std::bitset<32>(8), + std::bitset<32>(24), std::bitset<32>(25), std::bitset<32>(27), std::bitset<32>(26), + std::bitset<32>(30), std::bitset<32>(31), std::bitset<32>(29), std::bitset<32>(28), + std::bitset<32>(20), std::bitset<32>(21), std::bitset<32>(23), std::bitset<32>(22), + std::bitset<32>(18), std::bitset<32>(19), std::bitset<32>(17), std::bitset<32>(16) + }; + + // invalid values for n + assert(bit_manipulation::gray_code::gray_code_generation(-1) == gray_code_negative_1); + assert(bit_manipulation::gray_code::gray_code_generation(0) == gray_code_0); + + // valid values for n + assert(bit_manipulation::gray_code::gray_code_generation(1) == gray_code_1); + assert(bit_manipulation::gray_code::gray_code_generation(2) == gray_code_2); + assert(bit_manipulation::gray_code::gray_code_generation(3) == gray_code_3); + assert(bit_manipulation::gray_code::gray_code_generation(4) == gray_code_4); + assert(bit_manipulation::gray_code::gray_code_generation(5) == gray_code_5); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); //Run self-test implementation + return 0; +} From 901f231d592ddc7fa41c2f809adb3fd6cc620927 Mon Sep 17 00:00:00 2001 From: B Karthik <115967163+BKarthik7@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:48:54 +0530 Subject: [PATCH 42/74] feat: Added gale_shapley.cpp in greedy_algorithms (#2743) * Added gale_shapley.cpp in greedy_algorithms * Added gale_shapley.cpp in greedy_algorithms * Genralized GaleShapley with reviewed change * fix: added description * fix: fixed nameing of namespace * fix: reviewed changes * fix: reviewed changes * TestCase Empty vector * function description * Update greedy_algorithms/gale_shapley.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/gale_shapley.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Change type * typechange with header documentation --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- greedy_algorithms/gale_shapley.cpp | 129 +++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 greedy_algorithms/gale_shapley.cpp diff --git a/greedy_algorithms/gale_shapley.cpp b/greedy_algorithms/gale_shapley.cpp new file mode 100644 index 00000000000..ddc6298fa44 --- /dev/null +++ b/greedy_algorithms/gale_shapley.cpp @@ -0,0 +1,129 @@ +/** + * @file + * @brief [Gale Shapley Algorithm](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) + * @details + * This implementation utilizes the Gale-Shapley algorithm to find stable matches. + * + * **Gale Shapley Algorithm** aims to find a stable matching between two equally sized + * sets of elements given an ordinal preference for each element. The algorithm was + * introduced by David Gale and Lloyd Shapley in 1962. + * + * Reference: + * [Wikipedia](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) + * [Wikipedia](https://en.wikipedia.org/wiki/Stable_matching_problem) + * + * @author [B Karthik](https://github.com/BKarthik7) + */ + +#include /// for std::u32int_t +#include /// for std::vector +#include /// for std::find +#include /// for assert + +/** + * @namespace + * @brief Greedy Algorithms + */ +namespace greedy_algorithms { +/** + * @namespace + * @brief Functions for the Gale-Shapley Algorithm + */ +namespace stable_matching { +/** + * @brief The main function that finds the stable matching between two sets of elements + * using the Gale-Shapley Algorithm. + * @note This doesn't work on negative preferences. the preferences should be continuous integers starting from + * 0 to number of preferences - 1. + * @param primary_preferences the preferences of the primary set should be a 2D vector + * @param secondary_preferences the preferences of the secondary set should be a 2D vector + * @returns matches the stable matching between the two sets + */ +std::vector gale_shapley(const std::vector>& secondary_preferences, const std::vector>& primary_preferences) { + std::uint32_t num_elements = secondary_preferences.size(); + std::vector matches(num_elements, -1); + std::vector is_free_primary(num_elements, true); + std::vector proposal_index(num_elements, 0); // Tracks the next secondary to propose for each primary + + while (true) { + int free_primary_index = -1; + + // Find the next free primary + for (std::uint32_t i = 0; i < num_elements; i++) { + if (is_free_primary[i]) { + free_primary_index = i; + break; + } + } + + // If no free primary is found, break the loop + if (free_primary_index == -1) break; + + // Get the next secondary to propose + std::uint32_t secondary_to_propose = primary_preferences[free_primary_index][proposal_index[free_primary_index]]; + proposal_index[free_primary_index]++; + + // Get the current match of the secondary + std::uint32_t current_match = matches[secondary_to_propose]; + + // If the secondary is free, match them + if (current_match == -1) { + matches[secondary_to_propose] = free_primary_index; + is_free_primary[free_primary_index] = false; + } else { + // Determine if the current match should be replaced + auto new_proposer_rank = std::find(secondary_preferences[secondary_to_propose].begin(), + secondary_preferences[secondary_to_propose].end(), + free_primary_index); + auto current_match_rank = std::find(secondary_preferences[secondary_to_propose].begin(), + secondary_preferences[secondary_to_propose].end(), + current_match); + + // If the new proposer is preferred over the current match + if (new_proposer_rank < current_match_rank) { + matches[secondary_to_propose] = free_primary_index; + is_free_primary[free_primary_index] = false; + is_free_primary[current_match] = true; // Current match is now free + } + } + } + + return matches; +} +} // namespace stable_matching +} // namespace greedy_algorithms + +/** + * @brief Self-test implementations + * @returns void + */ +static void tests() { + // Test Case 1 + std::vector> primary_preferences = {{0, 1, 2, 3}, {2, 1, 3, 0}, {1, 2, 0, 3}, {3, 0, 1, 2}}; + std::vector> secondary_preferences = {{1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; + assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({0, 2, 1, 3})); + + // Test Case 2 + primary_preferences = {{0, 2, 1, 3}, {2, 3, 0, 1}, {3, 1, 2, 0}, {2, 1, 0, 3}}; + secondary_preferences = {{1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; + assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({0, 3, 1, 2})); + + // Test Case 3 + primary_preferences = {{0, 1, 2}, {2, 1, 0}, {1, 2, 0}}; + secondary_preferences = {{1, 0, 2}, {2, 0, 1}, {0, 2, 1}}; + assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({0, 2, 1})); + + // Test Case 4 + primary_preferences = {}; + secondary_preferences = {}; + assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({})); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + tests(); // Run self-test implementations + return 0; +} From c56496d9f28d8db478dc663aebc96fa7b657f67f Mon Sep 17 00:00:00 2001 From: Divyansh-jain2 <142875929+Divyansh-jain2@users.noreply.github.com> Date: Fri, 4 Oct 2024 22:33:44 +0530 Subject: [PATCH 43/74] chore: use M_PI instead of PI parameter (#2747) * changed PI variable value from 3.14 to M_PI * changed PI variable to M_PI * changed the degree_to_radians function * comments removed * docs: remove pi param * fix: typo in function name * changed degree to degrees --------- Co-authored-by: [Divyansh Jain] <[jdivyansh51@gmail.com]> Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- physics/ground_to_ground_projectile_motion.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/physics/ground_to_ground_projectile_motion.cpp b/physics/ground_to_ground_projectile_motion.cpp index f2551935e74..af362c524a4 100644 --- a/physics/ground_to_ground_projectile_motion.cpp +++ b/physics/ground_to_ground_projectile_motion.cpp @@ -10,6 +10,7 @@ */ #include /// for assert() +#define _USE_MATH_DEFINES #include /// for std::pow(), std::sin(), and std::cos() #include /// for IO operations @@ -27,11 +28,12 @@ namespace ground_to_ground_projectile_motion { /** * @brief Convert radians to degrees * @param radian Angle in radians - * @param PI The definition of the constant PI * @returns Angle in degrees */ -double degrees_to_radians(double radian, double PI = 3.14) { - return (radian * (PI / 180)); + +double degrees_to_radians(double degrees){ + double radians = degrees * (M_PI / 180); + return radians; } /** From 51be6aad33255e5f3fe201294875659dde4a18dc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 23:52:19 +0530 Subject: [PATCH 44/74] docs: update DIRECTORY.md (#2754) Co-authored-by: github-actions[bot] --- DIRECTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index b78662887c2..79eb258c16f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -19,6 +19,7 @@ * [Count Of Set Bits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/count_of_set_bits.cpp) * [Count Of Trailing Ciphers In Factorial N](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp) * [Find Non Repeating Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/find_non_repeating_number.cpp) + * [Gray Code](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/gray_code.cpp) * [Hamming Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/hamming_distance.cpp) * [Next Higher Number With Same Number Of Set Bits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp) * [Power Of 2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/power_of_2.cpp) @@ -161,6 +162,7 @@ ## Greedy Algorithms * [Boruvkas Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/boruvkas_minimum_spanning_tree.cpp) * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/dijkstra.cpp) + * [Gale Shapley](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/gale_shapley.cpp) * [Huffman](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/huffman.cpp) * [Jump Game](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/jump_game.cpp) * [Knapsack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/knapsack.cpp) @@ -377,6 +379,7 @@ * [Pigeonhole Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/pigeonhole_sort.cpp) * [Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/quick_sort.cpp) * [Quick Sort 3](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/quick_sort_3.cpp) + * [Quick Sort Iterative](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/quick_sort_iterative.cpp) * [Radix Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/radix_sort.cpp) * [Radix Sort2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/radix_sort2.cpp) * [Random Pivot Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/random_pivot_quick_sort.cpp) From 0ecb6bd28a8a6b5ffc0edcad34ac036647d2259f Mon Sep 17 00:00:00 2001 From: jiya <122276932+jiya10208@users.noreply.github.com> Date: Sat, 5 Oct 2024 08:08:23 +0530 Subject: [PATCH 45/74] docs: reword binary search (#2752) * Update binary_search.cpp making some correction in the theory of binary search * Update search/binary_search.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- search/binary_search.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/search/binary_search.cpp b/search/binary_search.cpp index 5e455dd17e3..bed938b290c 100644 --- a/search/binary_search.cpp +++ b/search/binary_search.cpp @@ -4,8 +4,8 @@ * algorithm](https://en.wikipedia.org/wiki/Binary_search_algorithm) * @details * Binary search is a search algorithm that finds the position of a target value - * within a sorted array. Binary search compares the target value to the middle - * element of the array. If they are not equal, the half in which the target + * within a sorted array.Just like looking for a word in a dictionary, in binary search we compare the target value to the middle + * element of the array. If they are not equal, then the half in which the target * cannot lie is eliminated and the search continues on the remaining half, * again taking the middle element to compare to the target value, and repeating * this until the target value is found. If the search ends with the remaining @@ -13,7 +13,7 @@ * * ### Implementation * - * Binary search works on sorted arrays. Binary search begins by comparing an + * Binary search works on sorted arrays. It begins by comparing an * element in the middle of the array with the target value. If the target value * matches the element, its position in the array is returned. If the target * value is less than the element, the search continues in the lower half of @@ -28,6 +28,7 @@ * Worst-case time complexity O(log n) * Best-case time complexity O(1) * Average time complexity O(log n) + * space complexity 0(1) * Worst-case space complexity 0(1) * * @author [Lajat Manekar](https://github.com/Lazeeez) From 60093d70ab46eba45cc89b652986bec3bfdbdd9d Mon Sep 17 00:00:00 2001 From: Amine Ghoussaini <54037376+aminegh20@users.noreply.github.com> Date: Sat, 5 Oct 2024 15:52:02 +0300 Subject: [PATCH 46/74] feat: add duval's algorithm (#2725) * feat: Add Duval's algorithm for the lexicographically smallest rotation in a sequence. * fixes. * fixes. --- strings/duval.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 strings/duval.cpp diff --git a/strings/duval.cpp b/strings/duval.cpp new file mode 100644 index 00000000000..9304da0c06f --- /dev/null +++ b/strings/duval.cpp @@ -0,0 +1,118 @@ +/** + * @file duval.cpp + * @brief Implementation of [Duval's algorithm](https://en.wikipedia.org/wiki/Lyndon_word). + * + * @details + * Duval's algorithm is an algorithm to find the lexicographically smallest + * rotation of a string. It is based on the concept of Lyndon words. + * Lyndon words are defined as the lexicographically smallest string in a + * rotation equivalence class. A rotation equivalence class is a set of strings + * that can be obtained by rotating a string. For example, the rotation + * equivalence class of "abc" is {"abc", "bca", "cab"}. The lexicographically + * smallest string in this class is "abc". + * + * Duval's algorithm works by iterating over the string and finding the + * smallest rotation of the string that is a Lyndon word. This is done by + * comparing the string with its suffixes and finding the smallest suffix that + * is lexicographically smaller than the string. This suffix is then added to + * the result and the process is repeated with the remaining string. + * The algorithm has a time complexity of O(n) where n is the length of the + * string. + * + * @note While Lyndon words are described in the context of strings, + * Duval's algorithm can be used to find the lexicographically smallest cyclic + * shift of any sequence of comparable elements. + * + * @author [Amine Ghoussaini](https://github.com/aminegh20) +*/ + +#include /// for std::array +#include /// for assert +#include /// for std::size_t +#include /// for std::deque +#include /// for std::cout and std::endl +#include /// for std::string +#include /// for std::vector + +/** + * @brief string manipulation algorithms + * @namespace + */ +namespace string { +/** + * @brief Find the lexicographically smallest cyclic shift of a sequence. + * @tparam T type of the sequence + * @param s the sequence + * @returns the 0-indexed position of the least cyclic shift of the sequence + */ +template +size_t duval(const T& s) { + size_t n = s.size(); + size_t i = 0, ans = 0; + while (i < n) { + ans = i; + size_t j = i + 1, k = i; + while (j < (n + n) && s[j % n] >= s[k % n]) { + if (s[k % n] < s[j % n]) { + k = i; + } else { + k++; + } + j++; + } + while (i <= k) { + i += j - k; + } + } + return ans; + // returns 0-indexed position of the least cyclic shift +} + +} // namespace string + +/** + * @brief self test implementation + * returns void + */ +static void test() { + using namespace string; + + // Test 1 + std::string s1 = "abcab"; + assert(duval(s1) == 3); + + // Test 2 + std::string s2 = "011100"; + assert(duval(s2) == 4); + + // Test 3 + std::vector v = {5, 2, 1, 3, 4}; + assert(duval(v) == 2); + + // Test 4 + std::array a = {1, 2, 3, 4, 5}; + assert(duval(a) == 0); + + // Test 5 + std::deque d = {'a', 'z', 'c', 'a', 'b'}; + assert(duval(d) == 3); + + // Test 6 + std::string s3; + assert(duval(s3) == 0); + + // Test 7 + std::vector v2 = {5, 2, 1, 3, -4}; + assert(duval(v2) == 4); + + std::cout << "All tests passed!" << std::endl; +} + +/** + * @brief main function + * @returns 0 on exit + */ +int main() { + test(); // run self test implementations + return 0; +} From f9fb58fb87c19cf29954c1f570df8e2fda86312d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 08:09:04 +0530 Subject: [PATCH 47/74] docs: update DIRECTORY.md (#2771) Co-authored-by: github-actions[bot] --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 79eb258c16f..1404281b2fe 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -399,6 +399,7 @@ ## Strings * [Boyer Moore](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/boyer_moore.cpp) * [Brute Force String Searching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/brute_force_string_searching.cpp) + * [Duval](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/duval.cpp) * [Horspool](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/horspool.cpp) * [Knuth Morris Pratt](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/knuth_morris_pratt.cpp) * [Manacher Algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/strings/manacher_algorithm.cpp) From b957b1dfef9f13eb85182b92ba7d294301e8d1ca Mon Sep 17 00:00:00 2001 From: Harshil Shah <143382356+HarshilShah1804@users.noreply.github.com> Date: Mon, 7 Oct 2024 06:15:29 +0530 Subject: [PATCH 48/74] feat: Add hemi-sphere area algorithm (#2767) * Add area of hemi-sphere * Update math/area.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- math/area.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/math/area.cpp b/math/area.cpp index 691fe91f0fc..a787e2e3a45 100644 --- a/math/area.cpp +++ b/math/area.cpp @@ -109,6 +109,18 @@ template T cylinder_surface_area(T radius, T height) { return 2 * M_PI * radius * height + 2 * M_PI * pow(radius, 2); } + +/** + * @brief surface area of a [hemi-sphere](https://en.wikipedia.org/wiki/Surface_area) ( 3 * + * pi * r^2) + * @param radius is the radius of the hemi-sphere + * @tparam T datatype of radius + * @returns surface area of the hemi-sphere + */ +template +T hemi_sphere_surface_area(T radius) { + return 3 * M_PI * pow(radius, 2); +} } // namespace math /** @@ -267,6 +279,18 @@ static void test() { std::cout << "Output: " << double_area << std::endl; assert(double_area == double_expected); std::cout << "TEST PASSED" << std::endl << std::endl; + + // 11th test + double_radius = 10.0; + double_expected = 942.4777960769379; + double_area = math::hemi_sphere_surface_area(double_radius); + + std::cout << "SURFACE AREA OF A HEMI-SPHERE" << std::endl; + std::cout << "Input Radius: " << double_radius << std::endl; + std::cout << "Expected Output: " << double_expected << std::endl; + std::cout << "Output: " << double_area << std::endl; + assert(double_area == double_expected); + std::cout << "TEST PASSED" << std::endl << std::endl; } /** From fddedd88647315964a6a3b16bb0caf55ae8a14b5 Mon Sep 17 00:00:00 2001 From: Nguyen Phuc Chuong <72879387+hollowcrust@users.noreply.github.com> Date: Mon, 7 Oct 2024 21:26:25 +0800 Subject: [PATCH 49/74] fix: Adding documentations, tests, and amending algorithm for gcd_of_n_numbers.cpp (#2766) * Update gcd_of_n_numbers.cpp * Update gcd_of_n_numbers.cpp Reformatting code, comment and test cases, change array data type. * Update gcd_of_n_numbers.cpp * Update gcd_of_n_numbers.cpp * Update gcd_of_n_numbers.cpp * Update gcd_of_n_numbers.cpp --- math/gcd_of_n_numbers.cpp | 131 +++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 29 deletions(-) diff --git a/math/gcd_of_n_numbers.cpp b/math/gcd_of_n_numbers.cpp index 92968ff1265..45ba0b074ef 100644 --- a/math/gcd_of_n_numbers.cpp +++ b/math/gcd_of_n_numbers.cpp @@ -1,41 +1,114 @@ /** * @file - * @brief This program aims at calculating the GCD of n numbers by division - * method + * @brief This program aims at calculating the GCD of n numbers + * + * @details + * The GCD of n numbers can be calculated by + * repeatedly calculating the GCDs of pairs of numbers + * i.e. \f$\gcd(a, b, c)\f$ = \f$\gcd(\gcd(a, b), c)\f$ + * Euclidean algorithm helps calculate the GCD of each pair of numbers + * efficiently * * @see gcd_iterative_euclidean.cpp, gcd_recursive_euclidean.cpp */ -#include +#include /// for std::abs +#include /// for std::array +#include /// for assert +#include /// for IO operations -/** Compute GCD using division algorithm - * - * @param[in] a array of integers to compute GCD for - * @param[in] n number of integers in array `a` - */ -int gcd(int *a, int n) { - int j = 1; // to access all elements of the array starting from 1 - int gcd = a[0]; - while (j < n) { - if (a[j] % gcd == 0) // value of gcd is as needed so far - j++; // so we check for next element - else - gcd = a[j] % gcd; // calculating GCD by division method +/** + * @namespace math + * @brief Maths algorithms + */ +namespace math { +/** + * @namespace gcd_of_n_numbers + * @brief Compute GCD of numbers in an array + */ +namespace gcd_of_n_numbers { +/** + * @brief Function to compute GCD of 2 numbers x and y + * @param x First number + * @param y Second number + * @return GCD of x and y via recursion + */ +int gcd_two(int x, int y) { + // base cases + if (y == 0) { + return x; + } + if (x == 0) { + return y; + } + return gcd_two(y, x % y); // Euclidean method +} + +/** + * @brief Function to check if all elements in the array are 0 + * @param a Array of numbers + * @return 'True' if all elements are 0 + * @return 'False' if not all elements are 0 + */ +template +bool check_all_zeros(const std::array &a) { + // Use std::all_of to simplify zero-checking + return std::all_of(a.begin(), a.end(), [](int x) { return x == 0; }); +} + +/** + * @brief Main program to compute GCD using the Euclidean algorithm + * @param a Array of integers to compute GCD for + * @return GCD of the numbers in the array or std::nullopt if undefined + */ +template +int gcd(const std::array &a) { + // GCD is undefined if all elements in the array are 0 + if (check_all_zeros(a)) { + return -1; // Use std::optional to represent undefined GCD + } + + // divisors can be negative, we only want the positive value + int result = std::abs(a[0]); + for (std::size_t i = 1; i < n; ++i) { + result = gcd_two(result, std::abs(a[i])); + if (result == 1) { + break; // Further computations still result in gcd of 1 } - return gcd; + } + return result; } +} // namespace gcd_of_n_numbers +} // namespace math -/** Main function */ -int main() { - int n; - std::cout << "Enter value of n:" << std::endl; - std::cin >> n; - int *a = new int[n]; - int i; - std::cout << "Enter the n numbers:" << std::endl; - for (i = 0; i < n; i++) std::cin >> a[i]; +/** + * @brief Self-test implementation + * @return void + */ +static void test() { + std::array array_1 = {0}; + std::array array_2 = {1}; + std::array array_3 = {0, 2}; + std::array array_4 = {-60, 24, 18}; + std::array array_5 = {100, -100, -100, 200}; + std::array array_6 = {0, 0, 0, 0, 0}; + std::array array_7 = {10350, -24150, 0, 17250, 37950, -127650, 51750}; + std::array array_8 = {9500000, -12121200, 0, 4444, 0, 0, 123456789}; - std::cout << "GCD of entered n numbers:" << gcd(a, n) << std::endl; + assert(math::gcd_of_n_numbers::gcd(array_1) == -1); + assert(math::gcd_of_n_numbers::gcd(array_2) == 1); + assert(math::gcd_of_n_numbers::gcd(array_3) == 2); + assert(math::gcd_of_n_numbers::gcd(array_4) == 6); + assert(math::gcd_of_n_numbers::gcd(array_5) == 100); + assert(math::gcd_of_n_numbers::gcd(array_6) == -1); + assert(math::gcd_of_n_numbers::gcd(array_7) == 3450); + assert(math::gcd_of_n_numbers::gcd(array_8) == 1); +} - delete[] a; - return 0; +/** + * @brief Main function + * @return 0 on exit + */ +int main() { + test(); // run self-test implementation + return 0; } From 821d20c33a55cc3a70973da1dd2dd675bbc1e250 Mon Sep 17 00:00:00 2001 From: deDSeC00720 <62394683+deDSeC00720@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:02:52 +0530 Subject: [PATCH 50/74] feat: LFU (Least frequently used) cache (#2757) * feat: add lfu cache * docs: add comments and explanation to class LFUCache * test: add tests for class lfu cache * docs: document namespace and classes * test: modify tests to check negative numbers * docs: document template params and class data members * test: make test func static and move tests in the same func --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- others/lfu_cache.cpp | 304 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 others/lfu_cache.cpp diff --git a/others/lfu_cache.cpp b/others/lfu_cache.cpp new file mode 100644 index 00000000000..d893a96599d --- /dev/null +++ b/others/lfu_cache.cpp @@ -0,0 +1,304 @@ +/** + * @file + * @brief Implementation for [LFU Cache] + * (https://en.wikipedia.org/wiki/Least_frequently_used) + * + * @details + * LFU discards the least frequently used value. if there are multiple items + * with the same minimum frequency then, the least recently used among them is + * discarded. Data structures used - doubly linked list and unordered_map(hash + * map). + * + * Hashmap maps the key to the address of the node of the linked list and its + * current usage frequency. If the element is accessed the element is removed + * from the linked list of the current frequency and added to the linked list of + * incremented frequency. + * + * When the cache is full, the last element in the minimum frequency linked list + * is popped. + * + * @author [Karan Sharma](https://github.com/deDSeC00720) + */ + +#include // for assert +#include // for std::cout +#include // for std::unordered_map + +/** + * @namespace + * @brief Other algorithms + */ +namespace others { + +/** + * @namespace + * @brief Cache algorithm + */ +namespace Cache { + +/** + * @class + * @brief Node for a doubly linked list with data, prev and next pointers + * @tparam T type of the data of the node + */ +template +class D_Node { + public: + T data; ///< data of the node + D_Node *prev; ///< previous node in the doubly linked list + D_Node *next; ///< next node in the doubly linked list + + explicit D_Node(T data) : data(data), prev(nullptr), next(nullptr) {} +}; + +template +using CacheNode = D_Node>; + +/** + * @class + * @brief LFUCache + * @tparam K type of key in the LFU + * @tparam V type of value in the LFU + */ +template +class LFUCache { + std::unordered_map *, int>> + node_map; ///< maps the key to the node address and frequency + std::unordered_map *, CacheNode *>> + freq_map; ///< maps the frequency to doubly linked list + + int minFreq; ///< minimum frequency in the cache + int _capacity; ///< maximum capacity of the cache + + public: + /** + * @brief Constructor, Initialize with minFreq and _capacity. + * @param _capacity Total capacity of the cache. + */ + explicit LFUCache(int _capacity) : minFreq(0), _capacity(_capacity) {} + + private: + /** + * @brief push the node at first position in the linked list of given + * frequency + * @param freq the frequency mapping to the linked list where node should be + * pushed. + * @param node node to be pushed to the linked list. + */ + void push(int freq, CacheNode *node) { + // if freq is not present, then make a new list with node as the head as + // well as tail. + if (!freq_map.count(freq)) { + freq_map[freq] = {node, node}; + return; + } + + std::pair *, CacheNode *> &p = freq_map[freq]; + + // insert the node at the beginning of the linked list and update the + // head. + p.first->prev = node; + node->next = p.first; + p.first = node; + } + + /** + * @brief increase the frequency of node and push it in the respective list. + * @param p_node the node to be updated + */ + void increase_frequency(std::pair *, int> &p_node) { + CacheNode *node = p_node.first; + int freq = p_node.second; + + std::pair *, CacheNode *> &p = freq_map[freq]; + + // if the given node is the only node in the list, + // then erase the frequency from map + // and increase minFreq by 1. + if (p.first == node && p.second == node) { + freq_map.erase(freq); + if (minFreq == freq) { + minFreq = freq + 1; + } + } else { + // remove the given node from current freq linked list + CacheNode *prev = node->prev; + CacheNode *next = node->next; + node->prev = nullptr; + node->next = nullptr; + + if (prev) { + prev->next = next; + } else { + p.first = next; + } + + if (next) { + next->prev = prev; + } else { + p.second = prev; + } + } + push(freq + 1, node); + ++p_node.second; + } + + /** + * @brief pop the last node in the least frequently used linked list + */ + void pop() { + std::pair *, CacheNode *> &p = freq_map[minFreq]; + + // if there is only one node + // remove the node and erase + // the frequency from freq_map + if (p.first == p.second) { + delete p.first; + freq_map.erase(minFreq); + return; + } + + // remove the last node in the linked list + CacheNode *temp = p.second; + p.second = temp->prev; + p.second->next = nullptr; + delete temp; + } + + public: + /** + * @brief upsert a key-value pair + * @param key key of the key-value pair + * @param value value of the key-value pair + */ + void put(K key, V value) { + // update the value if key already exists + if (node_map.count(key)) { + node_map[key].first->data.second = value; + increase_frequency(node_map[key]); + return; + } + + // if the cache is full + // remove the least frequently used item + if (node_map.size() == _capacity) { + node_map.erase(freq_map[minFreq].second->data.first); + pop(); + } + + // insert the new node and set minFreq to 1 + CacheNode *node = new CacheNode({key, value}); + node_map[key] = {node, 1}; + minFreq = 1; + push(1, node); + } + + /** + * @brief get the value of the key-value pair if exists + * @param key key of the key-value pair + * @return the value mapped to the given key + * @exception exception is thrown if the key is not present in the cache + */ + V get(K key) { + if (!node_map.count(key)) { + throw std::runtime_error("key is not present in the cache"); + } + + // increase the frequency and return the value + V value = node_map[key].first->data.second; + increase_frequency(node_map[key]); + return value; + } + + /** + * @brief Returns the number of items present in the cache. + * @return number of items in the cache + */ + int size() const { return node_map.size(); } + + /** + * @brief Returns the total capacity of the cache + * @return Total capacity of the cache + */ + int capacity() const { return _capacity; } + + /** + * @brief returns true if the cache is empty, false otherwise. + * @return true if the cache is empty, false otherwise. + */ + bool empty() const { return node_map.empty(); } + + /** + * @brief destructs the cache, iterates on the map and deletes every node + * present in the cache. + */ + ~LFUCache() { + auto it = node_map.begin(); + while (it != node_map.end()) { + delete it->second.first; + ++it; + } + } +}; +} // namespace Cache +} // namespace others + +/** + * @brief self test implementation + * @return void + */ +static void test() { + others::Cache::LFUCache cache(5); + + // test the initial state of the cache + assert(cache.size() == 0); + assert(cache.capacity() == 5); + assert(cache.empty()); + + // test insertion in the cache + cache.put(1, 10); + cache.put(-2, 20); + + // test the state of cache after inserting some items + assert(cache.size() == 2); + assert(cache.capacity() == 5); + assert(!cache.empty()); + + // test getting items from the cache + assert(cache.get(1) == 10); + assert(cache.get(-2) == 20); + + cache.put(-3, -30); + cache.put(4, 40); + cache.put(5, -50); + cache.put(6, 60); + + // test the state after inserting more items than the capacity + assert(cache.size() == 5); + assert(cache.capacity() == 5); + assert(!cache.empty()); + + // test retrieval of all items in the cache + assert(cache.get(1) == 10); + assert(cache.get(-2) == 20); + + // fetching -3 throws runtime_error + // as -3 was evicted being the least frequently used + // when 6 was added + // assert(cache.get(-3) == -30); + + assert(cache.get(4) == 40); + assert(cache.get(5) == -50); + assert(cache.get(6) == 60); + + std::cout << "test - passed\n"; +} + +/** + * @brief main function + * @return 0 on exit + */ +int main() { + test(); // run the self test implementation + return 0; +} From dd36279e734ca96f4a1dd7907faf2058210dc293 Mon Sep 17 00:00:00 2001 From: Muhammad Junaid Khalid Date: Mon, 7 Oct 2024 18:39:23 +0500 Subject: [PATCH 51/74] feat: Digit Separation Algorithm added (#2759) * Digit Separation Algorithm added * feat: Added namespace greedy_algoriithms * "Updated digit separation code: added comments and docstrings, changed data types to std::int64_t, and reformatted code." * feat: Made test function and removed extra whitespaces * removed some more whitespaces * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * fix: terminate multiline comment * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Corrected test function * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * remove redundant declaration Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Corrected tests Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * file clang linted * "Moved method implementations from outside to inside class definition" * fowardOrder to forwardOrder on line 122 Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Removed Class scope resolution form digitSeparationReverseOrder function Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Removed Class scope resolution form digitSeparationForwardOrderfunction Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * docs: documentation updated --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- greedy_algorithms/digit_separation.cpp | 142 +++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 greedy_algorithms/digit_separation.cpp diff --git a/greedy_algorithms/digit_separation.cpp b/greedy_algorithms/digit_separation.cpp new file mode 100644 index 00000000000..68735741153 --- /dev/null +++ b/greedy_algorithms/digit_separation.cpp @@ -0,0 +1,142 @@ +/** + * @file digit_separation.cpp + * @brief Separates digits from numbers in forward and reverse order + * @see https://www.log2base2.com/c-examples/loop/split-a-number-into-digits-in-c.html + * @details The DigitSeparation class provides two methods to separate the + * digits of large integers: digitSeparationReverseOrder and + * digitSeparationForwardOrder. The digitSeparationReverseOrder method extracts + * digits by repeatedly applying the modulus operation (% 10) to isolate the + * last digit, then divides the number by 10 to remove it. This process + * continues until the entire number is broken down into its digits, which are + * stored in reverse order. If the number is zero, the method directly returns a + * vector containing {0} to handle this edge case. Negative numbers are handled + * by taking the absolute value, ensuring consistent behavior regardless of the + * sign. + * @author [Muhammad Junaid Khalid](https://github.com/mjk22071998) + */ + +#include /// For reveresing the vector +#include /// For assert() function to check for errors +#include /// For abs() function +#include /// For int64_t data type to handle large numbers +#include /// For input/output operations +#include /// For std::vector to store separated digits + +/** + * @namespace + * @brief Greedy Algorithms + */ +namespace greedy_algorithms { + +/** + * @brief A class that provides methods to separate the digits of a large + * positive number. + */ +class DigitSeparation { + public: + /** + * @brief Default constructor for the DigitSeparation class. + */ + DigitSeparation() {} + + /** + * @brief Implementation of digitSeparationReverseOrder method. + * + * @param largeNumber The large number to separate digits from. + * @return A vector of digits in reverse order. + */ + std::vector digitSeparationReverseOrder( + std::int64_t largeNumber) const { + std::vector result; + if (largeNumber != 0) { + while (largeNumber != 0) { + result.push_back(std::abs(largeNumber % 10)); + largeNumber /= 10; + } + } else { + result.push_back(0); + } + return result; + } + + /** + * @brief Implementation of digitSeparationForwardOrder method. + * + * @param largeNumber The large number to separate digits from. + * @return A vector of digits in forward order. + */ + std::vector digitSeparationForwardOrder( + std::int64_t largeNumber) const { + std::vector result = + digitSeparationReverseOrder(largeNumber); + std::reverse(result.begin(), result.end()); + return result; + } +}; + +} // namespace greedy_algorithms + +/** + * @brief self test implementation + * @return void + */ +static void tests() { + greedy_algorithms::DigitSeparation ds; + + // Test case: Positive number + std::int64_t number = 1234567890; + std::vector expectedReverse = {0, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + std::vector expectedForward = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + std::vector reverseOrder = + ds.digitSeparationReverseOrder(number); + assert(reverseOrder == expectedReverse); + std::vector forwardOrder = + ds.digitSeparationForwardOrder(number); + assert(forwardOrder == expectedForward); + + // Test case: Single digit number + number = 5; + expectedReverse = {5}; + expectedForward = {5}; + reverseOrder = ds.digitSeparationReverseOrder(number); + assert(reverseOrder == expectedReverse); + forwardOrder = ds.digitSeparationForwardOrder(number); + assert(forwardOrder == expectedForward); + + // Test case: Zero + number = 0; + expectedReverse = {0}; + expectedForward = {0}; + reverseOrder = ds.digitSeparationReverseOrder(number); + assert(reverseOrder == expectedReverse); + forwardOrder = ds.digitSeparationForwardOrder(number); + assert(forwardOrder == expectedForward); + + // Test case: Large number + number = 987654321012345; + expectedReverse = {5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + expectedForward = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5}; + reverseOrder = ds.digitSeparationReverseOrder(number); + assert(reverseOrder == expectedReverse); + forwardOrder = ds.digitSeparationForwardOrder(number); + assert(forwardOrder == expectedForward); + + // Test case: Negative number + number = -987654321012345; + expectedReverse = {5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + expectedForward = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5}; + reverseOrder = ds.digitSeparationReverseOrder(number); + assert(reverseOrder == expectedReverse); + forwardOrder = ds.digitSeparationForwardOrder(number); + assert(forwardOrder == expectedForward); +} + +/** + * @brief main function + * @return 0 on successful exit + */ +int main() { + tests(); // run self test implementation + + return 0; +} From faff2177c80d5f2250d456ccfea218b2b5de756c Mon Sep 17 00:00:00 2001 From: Dhanush S <95139774+Fandroid745@users.noreply.github.com> Date: Tue, 8 Oct 2024 19:34:42 +0530 Subject: [PATCH 52/74] feat: add recursive inserstion sort (#2764) * added recursive insertion sort algorithm * Modified the main function and removed user interaction as requested * Deleted previous file * Updated insertion_sort.cpp to its original code * Created insertion_sort_recursive.cpp file * Updated documentation and structure in insertion_sort_recursive.cpp * Updated documentation in insertion_sort_recursive.cpp * chore: remove redundant comment * chore:Removed unnecssary whitespace * doc: ease the brief of test * doc: remove redundant lines from main * chore:Removed redundant whitespace --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- sorting/insertion_sort_recursive.cpp | 152 +++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 sorting/insertion_sort_recursive.cpp diff --git a/sorting/insertion_sort_recursive.cpp b/sorting/insertion_sort_recursive.cpp new file mode 100644 index 00000000000..256a27e1ce3 --- /dev/null +++ b/sorting/insertion_sort_recursive.cpp @@ -0,0 +1,152 @@ +/** + * @file + * @brief Insertion Sort Algorithm + * @author [Dhanush S](https://github.com/Fandroid745) + * + * @details + * Insertion sort is a simple sorting algorithm that builds the final + * sorted array one element at a time. It is much less efficient compared + * to other sorting algorithms like heap sort, merge sort, or quick sort. + * + * However, it has several advantages: + * - Easy to implement. + * - Efficient for small data sets. + * - More efficient than other O(n²) algorithms like selection sort or bubble sort. + * - Stable: it does not change the relative order of elements with equal keys. + * + * Insertion sort works similarly to how people sort playing cards in their hands. + * The algorithm iterates through the list and inserts each element into its correct + * position in the sorted portion of the array. + * + * The time complexity of the algorithm is \f$O(n^2)\f$, and in some cases, it + * can be \f$O(n)\f$. + * + * Example execution: + * 1. Start with the array [4, 3, 2, 5, 1]. + * 2. Insert 3 in its correct position: [3, 4, 2, 5, 1]. + * 3. Insert 2: [2, 3, 4, 5, 1]. + * 4. Continue this until the array is sorted: [1, 2, 3, 4, 5]. + */ + + +#include /// for std::is_sorted +#include /// for assert function in testing +#include /// for std::cout and std::endl +#include /// for using std::vector + +/** + * @namespace sorting + * @brief Contains sorting algorithms + */ +namespace sorting { + +/** + * @brief Insertion Sort Function + * + * @tparam T Type of the array elements + * @param[in,out] arr Array to be sorted + * @param n Size of the array + */ +template +void insertionSort(T *arr, int n) { + for (int i = 1; i < n; i++) { + T temp = arr[i]; + int j = i - 1; + while (j >= 0 && temp < arr[j]) { + arr[j + 1] = arr[j]; + j--; + } + arr[j + 1] = temp; + } +} + +/** + * @brief Insertion Sort for a vector + * + * @tparam T Type of the vector elements + * @param [in,out] arr Pointer to the vector to be sorted + */ +template +void insertionSort(std::vector *arr) { + size_t n = arr->size(); + + for (size_t i = 1; i < n; i++) { + T temp = arr->at(i); + int32_t j = i - 1; + while (j >= 0 && temp < arr->at(j)) { + arr->at(j + 1) = arr->at(j); + j--; + } + arr->at(j + 1) = temp; + } +} + +} // namespace sorting + +/** + * @brief Helper function to create a random array + * + * @tparam T Type of the array elements + * @param arr Array to fill (must be pre-allocated) + * @param N Number of elements in the array + */ +template +static void create_random_array(T *arr, int N) { + while (N--) { + double r = (std::rand() % 10000 - 5000) / 100.f; + arr[N] = static_cast(r); + } +} + +/** + * @brief self test implementation + * @return void + */ +static void tests() { + int arr1[10] = {78, 34, 35, 6, 34, 56, 3, 56, 2, 4}; + std::cout << "Test 1... "; + sorting::insertionSort(arr1, 10); + assert(std::is_sorted(arr1, arr1 + 10)); + std::cout << "passed" << std::endl; + + int arr2[5] = {5, -3, 7, -2, 1}; + std::cout << "Test 2... "; + sorting::insertionSort(arr2, 5); + assert(std::is_sorted(arr2, arr2 + 5)); + std::cout << "passed" << std::endl; + + float arr3[5] = {5.6, -3.1, -3.0, -2.1, 1.8}; + std::cout << "Test 3... "; + sorting::insertionSort(arr3, 5); + assert(std::is_sorted(arr3, arr3 + 5)); + std::cout << "passed" << std::endl; + + std::vector arr4({5.6, -3.1, -3.0, -2.1, 1.8}); + std::cout << "Test 4... "; + sorting::insertionSort(&arr4); + assert(std::is_sorted(std::begin(arr4), std::end(arr4))); + std::cout << "passed" << std::endl; + + int arr5[50]; + std::cout << "Test 5... "; + create_random_array(arr5, 50); + sorting::insertionSort(arr5, 50); + assert(std::is_sorted(arr5, arr5 + 50)); + std::cout << "passed" << std::endl; + + float arr6[50]; + std::cout << "Test 6... "; + create_random_array(arr6, 50); + sorting::insertionSort(arr6, 50); + assert(std::is_sorted(arr6, arr6 + 50)); + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @return 0 on successful exit. + */ +int main() { + tests(); /// run self test implementations + return 0; +} From 512efd18610531000e28600e03e6ddc42c56cfe0 Mon Sep 17 00:00:00 2001 From: Ritobroto Kalita <158987797+ritk20@users.noreply.github.com> Date: Wed, 9 Oct 2024 18:45:12 +0530 Subject: [PATCH 53/74] fix: Update documentations and tests for fibonacci.cpp (#2793) * Update fibonacci.cpp * update documentation * Update documentation --- math/fibonacci.cpp | 83 ++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/math/fibonacci.cpp b/math/fibonacci.cpp index 4e3c15de86e..a09ebb57822 100644 --- a/math/fibonacci.cpp +++ b/math/fibonacci.cpp @@ -1,68 +1,65 @@ /** * @file - * @brief Generate fibonacci sequence + * @brief n-th [Fibonacci + * number](https://en.wikipedia.org/wiki/Fibonacci_sequence). * - * Calculate the the value on Fibonacci's sequence given an - * integer as input. + * @details + * Naive recursive implementation to calculate the n-th Fibonacci number. * \f[\text{fib}(n) = \text{fib}(n-1) + \text{fib}(n-2)\f] * * @see fibonacci_large.cpp, fibonacci_fast.cpp, string_fibonacci.cpp */ -#include -#include +#include /// for assert +#include /// for IO operations /** - * Recursively compute sequences - * @param n input - * @returns n-th element of the Fbinacci's sequence + * @namespace math + * @brief Math algorithms + */ +namespace math { +/** + * @namespace fibonacci + * @brief Functions for Fibonacci sequence + */ +namespace fibonacci { +/** + * @brief Function to compute the n-th Fibonacci number + * @param n the index of the Fibonacci number + * @returns n-th element of the Fibonacci's sequence */ uint64_t fibonacci(uint64_t n) { - /* If the input is 0 or 1 just return the same - This will set the first 2 values of the sequence */ + // If the input is 0 or 1 just return the same (Base Case) + // This will set the first 2 values of the sequence if (n <= 1) { return n; } - /* Add the last 2 values of the sequence to get next */ + // Add the preceding 2 values of the sequence to get next return fibonacci(n - 1) + fibonacci(n - 2); } +} // namespace fibonacci +} // namespace math /** - * Function for testing the fibonacci() function with a few - * test cases and assert statement. + * @brief Self-test implementation * @returns `void` -*/ + */ static void test() { - uint64_t test_case_1 = fibonacci(0); - assert(test_case_1 == 0); - std::cout << "Passed Test 1!" << std::endl; - - uint64_t test_case_2 = fibonacci(1); - assert(test_case_2 == 1); - std::cout << "Passed Test 2!" << std::endl; - - uint64_t test_case_3 = fibonacci(2); - assert(test_case_3 == 1); - std::cout << "Passed Test 3!" << std::endl; - - uint64_t test_case_4 = fibonacci(3); - assert(test_case_4 == 2); - std::cout << "Passed Test 4!" << std::endl; - - uint64_t test_case_5 = fibonacci(4); - assert(test_case_5 == 3); - std::cout << "Passed Test 5!" << std::endl; - - uint64_t test_case_6 = fibonacci(15); - assert(test_case_6 == 610); - std::cout << "Passed Test 6!" << std::endl << std::endl; + assert(math::fibonacci::fibonacci(0) == 0); + assert(math::fibonacci::fibonacci(1) == 1); + assert(math::fibonacci::fibonacci(2) == 1); + assert(math::fibonacci::fibonacci(3) == 2); + assert(math::fibonacci::fibonacci(4) == 3); + assert(math::fibonacci::fibonacci(15) == 610); + assert(math::fibonacci::fibonacci(20) == 6765); + std::cout << "All tests have passed successfully!\n"; } -/// Main function +/** + * @brief Main function + * @returns 0 on exit + */ int main() { - test(); - int n = 0; - std::cin >> n; - assert(n >= 0); - std::cout << "F(" << n << ")= " << fibonacci(n) << std::endl; + test(); // run self-test implementations + return 0; } From 34d3568b375eae699f7d9eb206d07acb20857d64 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:16:19 +0530 Subject: [PATCH 54/74] docs: update DIRECTORY.md (#2804) Co-authored-by: github-actions[bot] --- DIRECTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1404281b2fe..a59e2dc65e5 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -161,6 +161,7 @@ ## Greedy Algorithms * [Boruvkas Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/boruvkas_minimum_spanning_tree.cpp) + * [Digit Separation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/digit_separation.cpp) * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/dijkstra.cpp) * [Gale Shapley](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/gale_shapley.cpp) * [Huffman](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/huffman.cpp) @@ -300,6 +301,7 @@ * [Iterative Tree Traversals](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/iterative_tree_traversals.cpp) * [Kadanes3](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/kadanes3.cpp) * [Kelvin To Celsius](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/kelvin_to_celsius.cpp) + * [Lfu Cache](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/lfu_cache.cpp) * [Lru Cache](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/lru_cache.cpp) * [Matrix Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/matrix_exponentiation.cpp) * [Palindrome Of Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/palindrome_of_number.cpp) @@ -369,6 +371,7 @@ * [Gnome Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/gnome_sort.cpp) * [Heap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/heap_sort.cpp) * [Insertion Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/insertion_sort.cpp) + * [Insertion Sort Recursive](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/insertion_sort_recursive.cpp) * [Library Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/library_sort.cpp) * [Merge Insertion Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/merge_insertion_sort.cpp) * [Merge Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/sorting/merge_sort.cpp) From 5eff2b9e2bcc142c3de2f77ec94e71b7b5f77d5e Mon Sep 17 00:00:00 2001 From: Ashish Kumar Sahoo <79834663+ashish5kmax@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:58:50 +0530 Subject: [PATCH 55/74] Create Longest_Substring_Without_Repeating_Characters.cpp (#2761) * Create Longest_Substring_Without_Repeating_Characters.cpp * I would like to contribute for sliding window algorithm and this one is one of the famous problem that is asked in interviews. * Thank you!!. * Update and rename Longest_Substring_Without_Repeating_Characters.cpp to sliding-window/Longest_Substring_Without_Repeating_Characters.cpp * This is my contribution towards the sliding window algorithm/s and this is one of the famous problems. * Thank you. * Update Longest_Substring_Without_Repeating_Characters.cpp * I would like to contribute towards the sliding window algorithm in which this is one of the famous problem asked in interviews. * Thank you. * Update Longest_Substring_Without_Repeating_Characters.cpp * Updated certain changes in documentation, this is my contribution towards sliding window algorithm this is one of the famous interview problem. * Thank you. * Update Longest_Substring_Without_Repeating_Characters.cpp * Well documented and tested code for sliding window algorithm. * Thank you. * Update and rename Longest_Substring_Without_Repeating_Characters.cpp to Longest_Substring_Without_Repeating_Characters.cpp * So,I did a small change I added the problem into the others section I think this works fine I guess. * I would be glad if this can be tagged as hackoctoberfest * Thank you. * Update and rename Longest_Substring_Without_Repeating_Characters.cpp to longest_substring_without_repeating_characters.cpp * I hope I have done the required changes. * Update longest_substring_without_repeating_characters.cpp * Added specific edge cases and tests as void tests() and followed the guidelines. * Update longest_substring_without_repeating_characters.cpp * I hope I have made the necessary changes required. * If there are any changes to make I can do that. * Thank you. * Update longest_substring_without_repeating_characters.cpp * I have done the required changes for the include part. * Thank you. * Update longest_substring_without_repeating_characters.cpp added author name --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- ...substring_without_repeating_characters.cpp | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 others/longest_substring_without_repeating_characters.cpp diff --git a/others/longest_substring_without_repeating_characters.cpp b/others/longest_substring_without_repeating_characters.cpp new file mode 100644 index 00000000000..3664ad71e7e --- /dev/null +++ b/others/longest_substring_without_repeating_characters.cpp @@ -0,0 +1,110 @@ +/** + * @file + * @brief Solution for Longest Substring Without Repeating Characters problem. + * @details + * Problem link: https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ + * + * Intuition: + * 1) The intuition is straightforward and simple. We track the frequency of characters. + * 2) Since we can't use a string to track the longest substring without repeating characters efficiently (as removing a character from the front of a string isn't O(1)), we optimize the solution using a deque approach. + * + * Approach: + * 1) Initialize an unordered_map to track the frequency of characters. + * 2) Use a deque for pushing characters, and update the result deque (`res`) with the current deque (`temp`) + * whenever we find a longer substring. + * 3) Use a while loop to reduce the frequency from the front, incrementing `i`, + * and removing characters from the `temp` deque as we no longer need them. + * 4) Return `res.size()` as we are interested in the length of the longest substring. + * + * Time Complexity: O(N) + * Space Complexity: O(N) + * + * I hope this helps to understand. + * Thank you! + * @author [Ashish Kumar Sahoo](github.com/ashish5kmax) + **/ + +#include // for IO Operations +#include // for std::unordered_map +#include // for std::deque +#include // for string class/string datatype which is taken as input +#include // for assert + +/** + * @class Longest_Substring + * @brief Class that solves the Longest Substring Without Repeating Characters problem. + */ +class Longest_Substring { +public: + /** + * @brief Function to find the length of the longest substring without repeating characters. + * @param s Input string. + * @return Length of the longest substring. + */ + int lengthOfLongestSubstring(std::string s) { + // If the size of string is 1, then it will be the answer. + if (s.size() == 1) return 1; + + // Map used to store the character frequency. + std::unordered_map m; + int n = s.length(); + + // Deque to remove from back if repeating characters are present. + std::deque temp; + std::deque res; + int i, j; + + // Sliding window approach using two pointers. + for (i = 0, j = 0; i < n && j < n;) { + m[s[j]]++; + + // If repeating character found, update result and remove from the front. + if (m[s[j]] > 1) { + if (temp.size() > res.size()) { + res = temp; + } + + while (m[s[j]] > 1) { + temp.pop_front(); + m[s[i]]--; + i++; + } + } + + // Add the current character to the deque. + temp.push_back(s[j]); + j++; + } + + // Final check to update result. + if (temp.size() > res.size()) { + res = temp; + } + + return res.size(); // Return the length of the longest substring. + } +}; + +/** + * @brief Self-test implementations + * @returns void + */ +static void tests() { + Longest_Substring soln; + assert(soln.lengthOfLongestSubstring("abcabcbb") == 3); + assert(soln.lengthOfLongestSubstring("bbbbb") == 1); + assert(soln.lengthOfLongestSubstring("pwwkew") == 3); + assert(soln.lengthOfLongestSubstring("") == 0); // Test case for empty string + assert(soln.lengthOfLongestSubstring("abcdef") == 6); // Test case for all unique characters + assert(soln.lengthOfLongestSubstring("a") == 1); // Single character + std::cout << "All test cases passed!" << std::endl; +} + +/** + * @brief Main function. + * @return 0 on successful execution. + */ +int main() { + tests(); // run self-test implementations + return 0; +} From 49ee852d067827f8172de0a04984949b8f97ef40 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 09:52:18 +0530 Subject: [PATCH 56/74] docs: update DIRECTORY.md (#2810) Co-authored-by: github-actions[bot] --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a59e2dc65e5..840fd2a8ac4 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -302,6 +302,7 @@ * [Kadanes3](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/kadanes3.cpp) * [Kelvin To Celsius](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/kelvin_to_celsius.cpp) * [Lfu Cache](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/lfu_cache.cpp) + * [Longest Substring Without Repeating Characters](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/longest_substring_without_repeating_characters.cpp) * [Lru Cache](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/lru_cache.cpp) * [Matrix Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/matrix_exponentiation.cpp) * [Palindrome Of Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/palindrome_of_number.cpp) From 136e6c0ad8850ba79adf63f5ee9b3210a6c907b7 Mon Sep 17 00:00:00 2001 From: Nguyen Phuc Chuong <72879387+hollowcrust@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:27:30 +0800 Subject: [PATCH 57/74] docs, test: Fit bubble_sort into guidelines and enhance bubble sort algorithm (#2800) * Update bubble_sort.cpp * Update bubble_sort.cpp * Update bubble_sort.cpp Add latex notation * Update sorting/bubble_sort.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update sorting/bubble_sort.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update bubble_sort.cpp --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- sorting/bubble_sort.cpp | 183 +++++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 66 deletions(-) diff --git a/sorting/bubble_sort.cpp b/sorting/bubble_sort.cpp index c43e425fcd9..9209f8664e7 100644 --- a/sorting/bubble_sort.cpp +++ b/sorting/bubble_sort.cpp @@ -2,82 +2,133 @@ * @file * @brief Bubble sort algorithm * - * The working principle of the Bubble sort algorithm: + * @details + * Bubble sort algorithm is the bubble sorting algorithm. The most important reason + * for calling the bubble is that the largest number is thrown at the end of this + * algorithm. This is all about the logic. In each iteration, the largest number is + * expired and when iterations are completed, the sorting takes place. + * + * What is Swap? + * + * Swap in the software means that two variables are displaced. + * An additional variable is required for this operation. x = 5, y = 10. + * We want x = 10, y = 5. Here we create the most variable to do it. + * + * ```cpp + * int z; + * z = x; + * x = y; + * y = z; + * ``` + * + * The above process is a typical displacement process. + * When x assigns the value to x, the old value of x is lost. + * That's why we created a variable z to create the first value of the value of x, + * and finally, we have assigned to y. + * + * ## Bubble Sort Algorithm Analysis (Best Case - Worst Case - Average Case) + * + * ### Best Case + * Bubble Sort Best Case Performance. \f$O(n)\f$. However, you + * can't get the best status in the code we shared above. This happens on the + * optimized bubble sort algorithm. It's right down there. + * + * ### Worst Case + * Bubble Sort Worst Case Performance is \f$O(n^{2})\f$. Why is that? Because if you + * remember Big O Notation, we were calculating the complexity of the algorithms in + * the nested loops. The \f$n * (n - 1)\f$ product gives us \f$O(n^{2})\f$ performance. In the + * worst case all the steps of the cycle will occur. + * + * ### Average Case + * Bubble Sort is not an optimal algorithm. In average, \f$O(n^{2})\f$ performance is taken. + * + * @author [Deepak](https://github.com/Deepak-j-p) + * @author [Nguyen Phuc Chuong](https://github.com/hollowcrust) + */ -Bubble sort algorithm is the bubble sorting algorithm. The most important reason -for calling the bubble is that the largest number is thrown at the end of this -algorithm. This is all about the logic. In each iteration, the largest number is -expired and when iterations are completed, the sorting takes place. +#include /// for std::is_sorted +#include /// for assert +#include /// for IO implementations +#include /// for std::string +#include /// for std::pair, std::swap +#include /// for std::vector, std::vector::push_back, std::vector::size -What is Swap? +/** + * @namespace sorting + * @brief Sorting algorithms + */ +namespace sorting { +/** + * @namespace bubble_sort + * @brief Bubble sort algorithm + */ +namespace bubble_sort { +/** + * @brief Bubble sort algorithm + * @param array An array to be sorted + * @return The array sorted in ascending order + */ +template +std::vector bubble_sort(std::vector& array) { + // swap_check flag to terminate the function early + // if there is no swap occurs in one iteration. + bool swap_check = true; + int size = array.size(); + for (int i = 0; (i < size) && (swap_check); i++) { + swap_check = false; + for (int j = 0; j < size - 1 - i; j++) { + if (array[j] > array[j + 1]) { + swap_check = true; + std::swap(array[j], array[j + 1]); + } + } + } -Swap in the software means that two variables are displaced. -An additional variable is required for this operation. x = 5, y = 10. -We want x = 10, y = 5. Here we create the most variable to do it. + return array; +} +} // namespace bubble_sort +} // namespace sorting -int z; -z = x; -x = y; -y = z; +/** + * @brief Self-test implementation + * @return void + */ +static void test() { + std::vector vec_1 = {3, 1, -9, 0}; + std::vector sorted_1 = sorting::bubble_sort::bubble_sort(vec_1); -The above process is a typical displacement process. -When x assigns the value to x, the old value of x is lost. -That's why we created a variable z to create the first value of the value of x, -and finally, we have assigned to y. + std::vector vec_2 = {3}; + std::vector sorted_2 = sorting::bubble_sort::bubble_sort(vec_2); -Bubble Sort Algorithm Analysis (Best Case - Worst Case - Average Case) + std::vector vec_3 = {10, 10, 10, 10, 10}; + std::vector sorted_3 = sorting::bubble_sort::bubble_sort(vec_3); -Bubble Sort Worst Case Performance is O (n²). Why is that? Because if you -remember Big O Notation, we were calculating the complexity of the algorithms in -the nested loops. The n * (n - 1) product gives us O (n²) performance. In the -worst case all the steps of the cycle will occur. Bubble Sort (Avarage Case) -Performance. Bubble Sort is not an optimal algorithm. in average, O (n²) -performance is taken. Bubble Sort Best Case Performance. O (n). However, you -can't get the best status in the code we shared above. This happens on the -optimized bubble sort algorithm. It's right down there. -*/ + std::vector vec_4 = {1234, -273.1, 23, 150, 1234, 1555.55, -2000}; + std::vector sorted_4 = sorting::bubble_sort::bubble_sort(vec_4); -#include -#include + std::vector vec_5 = {'z', 'Z', 'a', 'B', ' ', 'c', 'a'}; + std::vector sorted_5 = sorting::bubble_sort::bubble_sort(vec_5); -int main() { - int n; - bool swap_check = true; - std::cout << "Enter the amount of numbers to sort: "; - std::cin >> n; - std::vector numbers; - std::cout << "Enter " << n << " numbers: "; - int num; + std::vector vec_6 = {"Hello", "hello", "Helo", "Hi", "hehe"}; + std::vector sorted_6 = sorting::bubble_sort::bubble_sort(vec_6); - // Input - for (int i = 0; i < n; i++) { - std::cin >> num; - numbers.push_back(num); - } + std::vector> vec_7 = {{10, 'c'}, {2, 'z'}, {10, 'a'}, {0, 'b'}, {-1, 'z'}}; + std::vector> sorted_7 = sorting::bubble_sort::bubble_sort(vec_7); - // Bubble Sorting - for (int i = 0; (i < n) && (swap_check); i++) { - swap_check = false; - for (int j = 0; j < n - 1 - i; j++) { - if (numbers[j] > numbers[j + 1]) { - swap_check = true; - std::swap(numbers[j], - numbers[j + 1]); // by changing swap location. - // I mean, j. If the number is - // greater than j + 1, then it - // means the location. - } - } - } + assert(std::is_sorted(sorted_1.begin(), sorted_1.end())); + assert(std::is_sorted(sorted_2.begin(), sorted_2.end())); + assert(std::is_sorted(sorted_3.begin(), sorted_3.end())); + assert(std::is_sorted(sorted_4.begin(), sorted_4.end())); + assert(std::is_sorted(sorted_5.begin(), sorted_5.end())); + assert(std::is_sorted(sorted_6.begin(), sorted_6.end())); + assert(std::is_sorted(sorted_7.begin(), sorted_7.end())); +} - // Output - std::cout << "\nSorted Array : "; - for (int i = 0; i < numbers.size(); i++) { - if (i != numbers.size() - 1) { - std::cout << numbers[i] << ", "; - } else { - std::cout << numbers[i] << std::endl; - } - } - return 0; +/** + * @brief Main function + * @return 0 on exit + */ +int main() { + test(); + return 0; } From c2adc3b1e623635ef1db86f2c380ff9950185a79 Mon Sep 17 00:00:00 2001 From: Harshil Shah <143382356+HarshilShah1804@users.noreply.github.com> Date: Sun, 13 Oct 2024 00:09:50 +0530 Subject: [PATCH 58/74] feat: Added Exponential Probability Distribution (#2780) * Add Exponential Distribution * Modified the documentation * Update Documentation * Update probability/exponential_dist.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update probability/exponential_dist.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update probability/exponential_dist.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update the files * Removed the link from documentation * docs: remove the second brief tag * Update latex notation Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update latex notation Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Corrected format issues * Update probability/exponential_dist.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update probability/exponential_dist.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update probability/exponential_dist.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Added more test, formatted with clang-format * Update files * Update format issues * Add more tests * Added namespaces --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- probability/exponential_dist.cpp | 151 +++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 probability/exponential_dist.cpp diff --git a/probability/exponential_dist.cpp b/probability/exponential_dist.cpp new file mode 100644 index 00000000000..ef6d396d58c --- /dev/null +++ b/probability/exponential_dist.cpp @@ -0,0 +1,151 @@ +/** + * @file + * @brief [Exponential + * Distribution](https://en.wikipedia.org/wiki/Exponential_distribution) + * + * The exponential distribution is used to model + * events occuring between a Poisson process like radioactive decay. + * + * \f[P(x, \lambda) = \lambda e^{-\lambda x}\f] + * + * Summary of variables used: + * \f$\lambda\f$ : rate parameter + */ + +#include // For assert +#include // For std::pow +#include // For I/O operation +#include // For std::invalid_argument +#include // For std::string + +/** + * @namespace probability + * @brief Probability algorithms + */ +namespace probability { +/** + * @namespace exponential_dist + * @brief Functions for the [Exponential + * Distribution](https://en.wikipedia.org/wiki/Exponential_distribution) + * algorithm implementation + */ +namespace geometric_dist { +/** + * @brief the expected value of the exponential distribution + * @returns \f[\mu = \frac{1}{\lambda}\f] + */ +double exponential_expected(double lambda) { + if (lambda <= 0) { + throw std::invalid_argument("lambda must be greater than 0"); + } + return 1 / lambda; +} + +/** + * @brief the variance of the exponential distribution + * @returns \f[\sigma^2 = \frac{1}{\lambda^2}\f] + */ +double exponential_var(double lambda) { + if (lambda <= 0) { + throw std::invalid_argument("lambda must be greater than 0"); + } + return 1 / pow(lambda, 2); +} + +/** + * @brief the standard deviation of the exponential distribution + * @returns \f[\sigma = \frac{1}{\lambda}\f] + */ +double exponential_std(double lambda) { + if (lambda <= 0) { + throw std::invalid_argument("lambda must be greater than 0"); + } + return 1 / lambda; +} +} // namespace geometric_dist +} // namespace probability + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + double lambda_1 = 1; + double expected_1 = 1; + double var_1 = 1; + double std_1 = 1; + + double lambda_2 = 2; + double expected_2 = 0.5; + double var_2 = 0.25; + double std_2 = 0.5; + + double lambda_3 = 3; + double expected_3 = 0.333333; + double var_3 = 0.111111; + double std_3 = 0.333333; + + double lambda_4 = 0; // Test 0 + double lambda_5 = -2.3; // Test negative value + + const float threshold = 1e-3f; + + std::cout << "Test for lambda = 1 \n"; + assert( + std::abs(expected_1 - probability::geometric_dist::exponential_expected( + lambda_1)) < threshold); + assert(std::abs(var_1 - probability::geometric_dist::exponential_var( + lambda_1)) < threshold); + assert(std::abs(std_1 - probability::geometric_dist::exponential_std( + lambda_1)) < threshold); + std::cout << "ALL TEST PASSED\n\n"; + + std::cout << "Test for lambda = 2 \n"; + assert( + std::abs(expected_2 - probability::geometric_dist::exponential_expected( + lambda_2)) < threshold); + assert(std::abs(var_2 - probability::geometric_dist::exponential_var( + lambda_2)) < threshold); + assert(std::abs(std_2 - probability::geometric_dist::exponential_std( + lambda_2)) < threshold); + std::cout << "ALL TEST PASSED\n\n"; + + std::cout << "Test for lambda = 3 \n"; + assert( + std::abs(expected_3 - probability::geometric_dist::exponential_expected( + lambda_3)) < threshold); + assert(std::abs(var_3 - probability::geometric_dist::exponential_var( + lambda_3)) < threshold); + assert(std::abs(std_3 - probability::geometric_dist::exponential_std( + lambda_3)) < threshold); + std::cout << "ALL TEST PASSED\n\n"; + + std::cout << "Test for lambda = 0 \n"; + try { + probability::geometric_dist::exponential_expected(lambda_4); + probability::geometric_dist::exponential_var(lambda_4); + probability::geometric_dist::exponential_std(lambda_4); + } catch (std::invalid_argument& err) { + assert(std::string(err.what()) == "lambda must be greater than 0"); + } + std::cout << "ALL TEST PASSED\n\n"; + + std::cout << "Test for lambda = -2.3 \n"; + try { + probability::geometric_dist::exponential_expected(lambda_5); + probability::geometric_dist::exponential_var(lambda_5); + probability::geometric_dist::exponential_std(lambda_5); + } catch (std::invalid_argument& err) { + assert(std::string(err.what()) == "lambda must be greater than 0"); + } + std::cout << "ALL TEST PASSED\n\n"; +} + +/** + * @brief Main function + * @return 0 on exit + */ +int main() { + test(); // Self test implementation + return 0; +} From e8416052808d1693052fff3023803650e713834a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:49:11 +0530 Subject: [PATCH 59/74] docs: update DIRECTORY.md (#2827) Co-authored-by: github-actions[bot] --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 840fd2a8ac4..3e8c64d950d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -325,6 +325,7 @@ * [Addition Rule](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/probability/addition_rule.cpp) * [Bayes Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/probability/bayes_theorem.cpp) * [Binomial Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/probability/binomial_dist.cpp) + * [Exponential Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/probability/exponential_dist.cpp) * [Geometric Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/probability/geometric_dist.cpp) * [Poisson Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/probability/poisson_dist.cpp) * [Windowed Median](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/probability/windowed_median.cpp) From 05d784d844c98677d8418130d33209b319c0d52d Mon Sep 17 00:00:00 2001 From: Naman Jain <103953760+namanmodi65@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:59:49 +0530 Subject: [PATCH 60/74] Longest Increasing subsequence using binary search most optimal approach (Modified) (#2776) * Longest Increasing subsequence using binary search most optimal approach for this problem * Longest Increasing subsequence using binary search most optimal approach for this problem * Longest Increasing subsequence using binary search most optimal approach for this problem (Modified) * Longest Increasing subsequence using binary search most optimal approach for this problem * Longest Increasing subsequence using binary search most optimal approach for this problem(done) * Longest Increasing subsequence using binary search most optimal approach for this problem * Floyd warshall * Longest Increasing subsequence using binary search most optimal approach for this problem * Longest Increasing subsequence using binary search most optimal approach for this problem * Longest Increasing subsequence using binary search most optimal approach for this problem --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- ...easing_Subsequence_using_binary_search.cpp | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 search/Longest_Increasing_Subsequence_using_binary_search.cpp diff --git a/search/Longest_Increasing_Subsequence_using_binary_search.cpp b/search/Longest_Increasing_Subsequence_using_binary_search.cpp new file mode 100644 index 00000000000..2f83de72ecf --- /dev/null +++ b/search/Longest_Increasing_Subsequence_using_binary_search.cpp @@ -0,0 +1,117 @@ +/** + * @file + * @brief find the length of the Longest Increasing Subsequence (LIS) + * using [Binary Search](https://en.wikipedia.org/wiki/Longest_increasing_subsequence) + * @details + * Given an integer array nums, return the length of the longest strictly + * increasing subsequence. + * The longest increasing subsequence is described as a subsequence of an array + * where: All elements of the subsequence are in increasing order. This subsequence + * itself is of the longest length possible. + + * For solving this problem we have Three Approaches :- + + * Approach 1 :- Using Brute Force + * The first approach that came to your mind is the Brute Force approach where we + * generate all subsequences and then manually filter the subsequences whose + * elements come in increasing order and then return the longest such subsequence. + * Time Complexity :- O(2^n) + * It's time complexity is exponential. Therefore we will try some other + * approaches. + + * Approach 2 :- Using Dynamic Programming + * To generate all subsequences we will use recursion and in the recursive logic we + * will figure out a way to solve this problem. Recursive Logic to solve this + * problem:- + * 1. We only consider the element in the subsequence if the element is grater then + * the last element present in the subsequence + * 2. When we consider the element we will increase the length of subsequence by 1 + * Time Complexity: O(N*N) + * Space Complexity: O(N*N) + O(N) + + * This approach is better then the previous Brute Force approach so, we can + * consider this approach. + + * But when the Constraints for the problem is very larger then this approach fails + + * Approach 3 :- Using Binary Search + * Other approaches use additional space to create a new subsequence Array. + * Instead, this solution uses the existing nums Array to build the subsequence + * array. We can do this because the length of the subsequence array will never be + * longer than the current index. + + * Time complexity: O(n∗log(n)) + * Space complexity: O(1) + + * This approach consider Most optimal Approach for solving this problem + + * @author [Naman Jain](https://github.com/namanmodi65) + */ + +#include /// for std::assert +#include /// for IO operations +#include /// for std::vector +#include /// for std::lower_bound +#include /// for std::uint32_t + +/** + * @brief Function to find the length of the Longest Increasing Subsequence (LIS) + * using Binary Search + * @tparam T The type of the elements in the input vector + * @param nums The input vector of elements of type T + * @return The length of the longest increasing subsequence + */ +template +std::uint32_t longest_increasing_subsequence_using_binary_search(std::vector& nums) { + if (nums.empty()) return 0; + + std::vector ans; + ans.push_back(nums[0]); + for (std::size_t i = 1; i < nums.size(); i++) { + if (nums[i] > ans.back()) { + ans.push_back(nums[i]); + } else { + auto idx = std::lower_bound(ans.begin(), ans.end(), nums[i]) - ans.begin(); + ans[idx] = nums[i]; + } + } + return static_cast(ans.size()); +} + +/** + * @brief Test cases for Longest Increasing Subsequence function + * @returns void + */ +static void tests() { + std::vector arr = {10, 9, 2, 5, 3, 7, 101, 18}; + assert(longest_increasing_subsequence_using_binary_search(arr) == 4); + + std::vector arr2 = {0, 1, 0, 3, 2, 3}; + assert(longest_increasing_subsequence_using_binary_search(arr2) == 4); + + std::vector arr3 = {7, 7, 7, 7, 7, 7, 7}; + assert(longest_increasing_subsequence_using_binary_search(arr3) == 1); + + std::vector arr4 = {-10, -1, -5, 0, 5, 1, 2}; + assert(longest_increasing_subsequence_using_binary_search(arr4) == 5); + + std::vector arr5 = {3.5, 1.2, 2.8, 3.1, 4.0}; + assert(longest_increasing_subsequence_using_binary_search(arr5) == 4); + + std::vector arr6 = {'a', 'b', 'c', 'a', 'd'}; + assert(longest_increasing_subsequence_using_binary_search(arr6) == 4); + + std::vector arr7 = {}; + assert(longest_increasing_subsequence_using_binary_search(arr7) == 0); + + std::cout << "All tests have successfully passed!\n"; +} + +/** + * @brief Main function to run tests + * @returns 0 on exit + */ +int main() { + tests(); // run self test implementation + return 0; +} From d438f0fc7fb3593fff2a076071714fe6aeafe954 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 15:22:15 +0530 Subject: [PATCH 61/74] docs: update DIRECTORY.md (#2857) Co-authored-by: github-actions[bot] --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 3e8c64d950d..4ba06fa0b28 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -340,6 +340,7 @@ * [Sparse Table](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/range_queries/sparse_table.cpp) ## Search + * [Longest Increasing Subsequence Using Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/Longest_Increasing_Subsequence_using_binary_search.cpp) * [Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/binary_search.cpp) * [Exponential Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/exponential_search.cpp) * [Fibonacci Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/fibonacci_search.cpp) From 37a98113724205f66d2f92adb784a34c44553c2b Mon Sep 17 00:00:00 2001 From: Nguyen Phuc Chuong <72879387+hollowcrust@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:21:23 +0800 Subject: [PATCH 62/74] docs, test: fit modular inverse fermat little theorem to contributing guidelines (#2779) * Update modular_inverse_fermat_little_theorem.cpp * Update modular_inverse_fermat_little_theorem.cpp * Update modular_inverse_fermat_little_theorem.cpp * Update modular_inverse_fermat_little_theorem.cpp * Update math/modular_inverse_fermat_little_theorem.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update math/modular_inverse_fermat_little_theorem.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update modular_inverse_fermat_little_theorem.cpp Add time complexity in comment * Update modular_inverse_fermat_little_theorem.cpp * Update modular_inverse_fermat_little_theorem.cpp --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- .../modular_inverse_fermat_little_theorem.cpp | 128 ++++++++++++------ 1 file changed, 85 insertions(+), 43 deletions(-) diff --git a/math/modular_inverse_fermat_little_theorem.cpp b/math/modular_inverse_fermat_little_theorem.cpp index 7550e14bf23..d870c4da978 100644 --- a/math/modular_inverse_fermat_little_theorem.cpp +++ b/math/modular_inverse_fermat_little_theorem.cpp @@ -30,8 +30,8 @@ * a^{m-2} &≡& a^{-1} \;\text{mod}\; m * \f} * - * We will find the exponent using binary exponentiation. Such that the - * algorithm works in \f$O(\log m)\f$ time. + * We will find the exponent using binary exponentiation such that the + * algorithm works in \f$O(\log n)\f$ time. * * Examples: - * * a = 3 and m = 7 @@ -43,56 +43,98 @@ * (as \f$a\times a^{-1} = 1\f$) */ -#include -#include +#include /// for assert +#include /// for std::int64_t +#include /// for IO implementations -/** Recursive function to calculate exponent in \f$O(\log n)\f$ using binary - * exponent. +/** + * @namespace math + * @brief Maths algorithms. + */ +namespace math { +/** + * @namespace modular_inverse_fermat + * @brief Calculate modular inverse using Fermat's Little Theorem. + */ +namespace modular_inverse_fermat { +/** + * @brief Calculate exponent with modulo using binary exponentiation in \f$O(\log b)\f$ time. + * @param a The base + * @param b The exponent + * @param m The modulo + * @return The result of \f$a^{b} % m\f$ */ -int64_t binExpo(int64_t a, int64_t b, int64_t m) { - a %= m; - int64_t res = 1; - while (b > 0) { - if (b % 2) { - res = res * a % m; - } - a = a * a % m; - // Dividing b by 2 is similar to right shift. - b >>= 1; +std::int64_t binExpo(std::int64_t a, std::int64_t b, std::int64_t m) { + a %= m; + std::int64_t res = 1; + while (b > 0) { + if (b % 2 != 0) { + res = res * a % m; } - return res; + a = a * a % m; + // Dividing b by 2 is similar to right shift by 1 bit + b >>= 1; + } + return res; } - -/** Prime check in \f$O(\sqrt{m})\f$ time. +/** + * @brief Check if an integer is a prime number in \f$O(\sqrt{m})\f$ time. + * @param m An intger to check for primality + * @return true if the number is prime + * @return false if the number is not prime */ -bool isPrime(int64_t m) { - if (m <= 1) { - return false; - } else { - for (int64_t i = 2; i * i <= m; i++) { - if (m % i == 0) { - return false; - } - } +bool isPrime(std::int64_t m) { + if (m <= 1) { + return false; + } + for (std::int64_t i = 2; i * i <= m; i++) { + if (m % i == 0) { + return false; } - return true; + } + return true; +} +/** + * @brief calculates the modular inverse. + * @param a Integer value for the base + * @param m Integer value for modulo + * @return The result that is the modular inverse of a modulo m + */ +std::int64_t modular_inverse(std::int64_t a, std::int64_t m) { + while (a < 0) { + a += m; + } + + // Check for invalid cases + if (!isPrime(m) || a == 0) { + return -1; // Invalid input + } + + return binExpo(a, m - 2, m); // Fermat's Little Theorem +} +} // namespace modular_inverse_fermat +} // namespace math + +/** + * @brief Self-test implementation + * @return void + */ +static void test() { + assert(math::modular_inverse_fermat::modular_inverse(0, 97) == -1); + assert(math::modular_inverse_fermat::modular_inverse(15, -2) == -1); + assert(math::modular_inverse_fermat::modular_inverse(3, 10) == -1); + assert(math::modular_inverse_fermat::modular_inverse(3, 7) == 5); + assert(math::modular_inverse_fermat::modular_inverse(1, 101) == 1); + assert(math::modular_inverse_fermat::modular_inverse(-1337, 285179) == 165519); + assert(math::modular_inverse_fermat::modular_inverse(123456789, 998244353) == 25170271); + assert(math::modular_inverse_fermat::modular_inverse(-9876543210, 1000000007) == 784794281); } /** - * Main function + * @brief Main function + * @return 0 on exit */ int main() { - int64_t a, m; - // Take input of a and m. - std::cout << "Computing ((a^(-1))%(m)) using Fermat's Little Theorem"; - std::cout << std::endl << std::endl; - std::cout << "Give input 'a' and 'm' space separated : "; - std::cin >> a >> m; - if (isPrime(m)) { - std::cout << "The modular inverse of a with mod m is (a^(m-2)) : "; - std::cout << binExpo(a, m - 2, m) << std::endl; - } else { - std::cout << "m must be a prime number."; - std::cout << std::endl; - } + test(); // run self-test implementation + return 0; } From ffef54470dededc7cc82cffb930432c110f7c46a Mon Sep 17 00:00:00 2001 From: deDSeC00720 <62394683+deDSeC00720@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:34:52 +0530 Subject: [PATCH 63/74] feat: LRU (Least recently used) cache - different implementation (#2783) * feat: add lru cache * test: add test to cover exception * test: add assert for exception message * review: change int to uint32_t * review: add header for std::uint32_t --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- others/lru_cache2.cpp | 277 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 others/lru_cache2.cpp diff --git a/others/lru_cache2.cpp b/others/lru_cache2.cpp new file mode 100644 index 00000000000..aaa6c943fbf --- /dev/null +++ b/others/lru_cache2.cpp @@ -0,0 +1,277 @@ +/** + * @file + * @brief Implementation for [LRU Cache] + * (https://en.wikipedia.org/wiki/Cache_replacement_policies#:~:text=Least%20Recently%20Used%20(LRU)) + * + * @details + * LRU discards the least recently used value. + * Data structures used - doubly linked list and unordered_map + * + * unordered_map maps the key to the address of the node of the linked list. + * If the element is accessed, the element is moved to the beginning of the + * linked list. + * + * When the cache is full, the last element in the linked list is popped. + * + * @author [Karan Sharma](https://github.com/deDSeC00720) + */ + +#include // for assert +#include // for std::uint32_t +#include // for std::cout +#include // for std::unordered_map + +/** + * @namespace + * @brief Other algorithms + */ +namespace others { + +/** + * @namespace + * @brief Cache algorithm + */ +namespace Cache { + +/** + * @class + * @brief Node for a doubly linked list with data, prev and next pointers + * @tparam T type of the data of the node + */ +template +class D_Node { + public: + T data; ///< data of the node + D_Node *prev; ///< previous node in the doubly linked list + D_Node *next; ///< next node in the doubly linked list + + explicit D_Node(T data) : data(data), prev(nullptr), next(nullptr) {} +}; + +template +using CacheNode = D_Node>; + +/** + * @class + * @brief LRUCache + * @tparam K type of key in the LRU + * @tparam V type of value in the LRU + */ +template +class LRUCache { + CacheNode *head; ///< head of the doubly linked list + CacheNode *tail; ///< tail of the doubly linked list + std::uint32_t _capacity; ///< maximum capacity of the cache + + std::unordered_map *> + node_map; ///< maps the key to the node address + + public: + /** + * @brief Constructor, Initialize the head and tail pointers to nullptr and + * initialize the _capacity of the cache + * @param _capacity Total capacity of the cache + */ + explicit LRUCache(int _capacity) + : head(nullptr), tail(nullptr), _capacity(_capacity) {} + + private: + /** + * @brief push the node to the front of the linked list. + * @param node_ptr the node to be pushed + */ + void push_front(CacheNode *node_ptr) { + if (!head) { + head = node_ptr; + tail = node_ptr; + return; + } + + node_ptr->next = head; + head->prev = node_ptr; + head = node_ptr; + } + + /** + * @brief move the existing node in the list to the beginning of the list. + * @param node_ptr node to be moved to the beginning. + */ + void make_recent(CacheNode *node_ptr) { + if (head == node_ptr) { + return; + } + + CacheNode *prev = node_ptr->prev; + CacheNode *next = node_ptr->next; + + prev->next = next; + if (next) { + next->prev = prev; + } else { + tail = prev; + } + + node_ptr->prev = nullptr; + node_ptr->next = nullptr; + push_front(node_ptr); + } + + /** + * @brief pop the last node in the linked list. + */ + void pop_back() { + if (!head) { + return; + } + if (head == tail) { + delete head; + head = nullptr; + tail = nullptr; + return; + } + + CacheNode *temp = tail; + tail = tail->prev; + tail->next = nullptr; + delete temp; + } + + public: + /** + * @brief upsert a key-value pair + * @param key key of the key-value pair + * @param value value of the key-value pair + */ + void put(K key, V value) { + // update the value if key already exists + if (node_map.count(key)) { + node_map[key]->data.second = value; + make_recent(node_map[key]); + return; + } + + // if the cache is full + // remove the least recently used item + if (node_map.size() == _capacity) { + node_map.erase(tail->data.first); + pop_back(); + } + + CacheNode *newNode = new CacheNode({key, value}); + + node_map[key] = newNode; + push_front(newNode); + } + + /** + * @brief get the value of the key-value pair if exists + * @param key key of the key-value pair + * @return the value mapped to the given key + * @exception exception is thrown if the key is not present in the cache + */ + V get(K key) { + if (!node_map.count(key)) { + throw std::runtime_error("key is not present in the cache"); + } + + // move node to the beginning of the list + V value = node_map[key]->data.second; + make_recent(node_map[key]); + return value; + } + + /** + * @brief Returns the number of items present in the cache. + * @return number of items in the cache + */ + int size() const { return node_map.size(); } + + /** + * @brief Returns the total capacity of the cache + * @return Total capacity of the cache + */ + int capacity() const { return _capacity; } + + /** + * @brief returns whether the cache is empty or not + * @return true if the cache is empty, false otherwise. + */ + bool empty() const { return node_map.empty(); } + + /** + * @brief destructs the cache, iterates on the map and deletes every node + * present in the cache. + */ + ~LRUCache() { + auto it = node_map.begin(); + while (it != node_map.end()) { + delete it->second; + ++it; + } + } +}; +} // namespace Cache +} // namespace others + +/** + * @brief self test implementations + * @return void + */ +static void test() { + others::Cache::LRUCache cache(5); + + // test the initial state of the cache + assert(cache.size() == 0); + assert(cache.capacity() == 5); + assert(cache.empty()); + + // test insertion in the cache + cache.put(1, 10); + cache.put(-2, 20); + + // test the state of cache after inserting some items + assert(cache.size() == 2); + assert(cache.capacity() == 5); + assert(!cache.empty()); + + // test getting items from the cache + assert(cache.get(1) == 10); + assert(cache.get(-2) == 20); + + cache.put(-3, -30); + cache.put(4, 40); + cache.put(5, -50); + cache.put(6, 60); + + // test the state after inserting more items than the capacity + assert(cache.size() == 5); + assert(cache.capacity() == 5); + assert(!cache.empty()); + + // fetching 1 throws runtime_error + // as 1 was evicted being the least recently used + // when 6 was added + try { + cache.get(1); + } catch (const std::runtime_error &e) { + assert(std::string(e.what()) == "key is not present in the cache"); + } + + // test retrieval of all items in the cache + assert(cache.get(-2) == 20); + assert(cache.get(-3) == -30); + assert(cache.get(4) == 40); + assert(cache.get(5) == -50); + assert(cache.get(6) == 60); + + std::cout << "test - passed\n"; +} + +/** + * @brief main function + * @return 0 on exit + */ +int main() { + test(); // run the self test implementation + return 0; +} From ecb8a3388d2343dea268ed972577fca646654fa0 Mon Sep 17 00:00:00 2001 From: Muhammad Junaid Khalid Date: Thu, 24 Oct 2024 21:24:38 +0500 Subject: [PATCH 64/74] feat: Added Binary Addition Algorithm (#2802) * Digit Separation Algorithm added * feat: Added namespace greedy_algoriithms * "Updated digit separation code: added comments and docstrings, changed data types to std::int64_t, and reformatted code." * feat: Made test function and removed extra whitespaces * removed some more whitespaces * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * fix: terminate multiline comment * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Corrected test function * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/digit_separation.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * remove redundant declaration Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Corrected tests Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * file clang linted * "Moved method implementations from outside to inside class definition" * fowardOrder to forwardOrder on line 122 Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Removed Class scope resolution form digitSeparationReverseOrder function Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Removed Class scope resolution form digitSeparationForwardOrderfunction Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * docs: documentation updated * initial commit of Binary Addition * "Formatting changes and whitespace adjustments in binary_addition.cpp" * Documentation added * fix: removed unnecessary whitespaces * fix: Fixed the case of non binary strings * clang linted * docs: Documentation updated * Comments updated * Removed link Removed @see link in header documentation Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * clang-format and clang-tidy fixes for cd8a5953 * made `tests()` static Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * added @returns in documentation of tests function Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * added @return in documentation of main function Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Co-authored-by: github-actions[bot] --- greedy_algorithms/binary_addition.cpp | 119 ++++++++++++++++++ ...asing_subsequence_using_binary_search.cpp} | 0 2 files changed, 119 insertions(+) create mode 100644 greedy_algorithms/binary_addition.cpp rename search/{Longest_Increasing_Subsequence_using_binary_search.cpp => longest_increasing_subsequence_using_binary_search.cpp} (100%) diff --git a/greedy_algorithms/binary_addition.cpp b/greedy_algorithms/binary_addition.cpp new file mode 100644 index 00000000000..4a365323815 --- /dev/null +++ b/greedy_algorithms/binary_addition.cpp @@ -0,0 +1,119 @@ +/** + * @file binary_addition.cpp + * @brief Adds two binary numbers and outputs resulting string + * + * @details The algorithm for adding two binary strings works by processing them + * from right to left, similar to manual addition. It starts by determining the + * longer string's length to ensure both strings are fully traversed. For each + * pair of corresponding bits and any carry from the previous addition, it + * calculates the sum. If the sum exceeds 1, a carry is generated for the next + * bit. The results for each bit are collected in a result string, which is + * reversed at the end to present the final binary sum correctly. Additionally, + * the function validates the input to ensure that only valid binary strings + * (containing only '0' and '1') are processed. If invalid input is detected, + * it returns an empty string. + * @author [Muhammad Junaid Khalid](https://github.com/mjk22071998) + */ + +#include /// for reverse function +#include /// for tests +#include /// for input and outputs +#include /// for string class + +/** + * @namespace + * @brief Greedy Algorithms + */ +namespace greedy_algorithms { +/** + * @brief A class to perform binary addition of two binary strings. + */ +class BinaryAddition { + public: + /** + * @brief Adds two binary strings and returns the result as a binary string. + * @param a The first binary string. + * @param b The second binary string. + * @return The sum of the two binary strings as a binary string, or an empty + * string if either input string contains non-binary characters. + */ + std::string addBinary(const std::string& a, const std::string& b) { + if (!isValidBinaryString(a) || !isValidBinaryString(b)) { + return ""; // Return empty string if input contains non-binary + // characters + } + + std::string result; + int carry = 0; + int maxLength = std::max(a.size(), b.size()); + + // Traverse both strings from the end to the beginning + for (int i = 0; i < maxLength; ++i) { + // Get the current bits from both strings, if available + int bitA = (i < a.size()) ? (a[a.size() - 1 - i] - '0') : 0; + int bitB = (i < b.size()) ? (b[b.size() - 1 - i] - '0') : 0; + + // Calculate the sum of bits and carry + int sum = bitA + bitB + carry; + carry = sum / 2; // Determine the carry for the next bit + result.push_back((sum % 2) + + '0'); // Append the sum's current bit to result + } + if (carry) { + result.push_back('1'); + } + std::reverse(result.begin(), result.end()); + return result; + } + + private: + /** + * @brief Validates whether a string contains only binary characters (0 or 1). + * @param str The string to validate. + * @return true if the string is binary, false otherwise. + */ + bool isValidBinaryString(const std::string& str) const { + return std::all_of(str.begin(), str.end(), + [](char c) { return c == '0' || c == '1'; }); + } +}; +} // namespace greedy_algorithms + +/** + * @brief run self test implementation. + * @returns void + */ +static void tests() { + greedy_algorithms::BinaryAddition binaryAddition; + + // Valid binary string tests + assert(binaryAddition.addBinary("1010", "1101") == "10111"); + assert(binaryAddition.addBinary("1111", "1111") == "11110"); + assert(binaryAddition.addBinary("101", "11") == "1000"); + assert(binaryAddition.addBinary("0", "0") == "0"); + assert(binaryAddition.addBinary("1111", "1111") == "11110"); + assert(binaryAddition.addBinary("0", "10101") == "10101"); + assert(binaryAddition.addBinary("10101", "0") == "10101"); + assert(binaryAddition.addBinary("101010101010101010101010101010", + "110110110110110110110110110110") == + "1100001100001100001100001100000"); + assert(binaryAddition.addBinary("1", "11111111") == "100000000"); + assert(binaryAddition.addBinary("10101010", "01010101") == "11111111"); + + // Invalid binary string tests (should return empty string) + assert(binaryAddition.addBinary("10102", "1101") == ""); + assert(binaryAddition.addBinary("ABC", "1101") == ""); + assert(binaryAddition.addBinary("1010", "1102") == ""); + assert(binaryAddition.addBinary("111", "1x1") == ""); + assert(binaryAddition.addBinary("1x1", "111") == ""); + assert(binaryAddition.addBinary("1234", "1101") == ""); +} + +/** + * @brief main function + * @returns 0 on successful exit + */ +int main() { + tests(); /// To execute tests + return 0; +} diff --git a/search/Longest_Increasing_Subsequence_using_binary_search.cpp b/search/longest_increasing_subsequence_using_binary_search.cpp similarity index 100% rename from search/Longest_Increasing_Subsequence_using_binary_search.cpp rename to search/longest_increasing_subsequence_using_binary_search.cpp From db3f9d34060ca40f7c29f3b61b40c8e80ba28148 Mon Sep 17 00:00:00 2001 From: Sanskruti Pravin Yeole <129084275+yeolesanskruti@users.noreply.github.com> Date: Mon, 28 Oct 2024 21:21:55 +0530 Subject: [PATCH 65/74] Create Unbounded_knapsack.cpp (#2786) * Create Unbounded_knapsack.cpp * Update Unbounded_knapsack.cpp Documentation done. * Update dynamic_programming/Unbounded_knapsack.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update dynamic_programming/Unbounded_knapsack.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update dynamic_programming/Unbounded_knapsack.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update dynamic_programming/Unbounded_knapsack.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Delete dynamic_programming/Unbounded_knapsack.cpp * Create Unbounded_0_1_Knapsack.cpp * Update Unbounded_0_1_Knapsack.cpp * Update Unbounded_0_1_Knapsack.cpp * docs: add docs for main * Update dynamic_programming/Unbounded_0_1_Knapsack.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update dynamic_programming/Unbounded_0_1_Knapsack.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update Unbounded_0_1_Knapsack.cpp * Update Unbounded_0_1_Knapsack.cpp * Update Unbounded_0_1_Knapsack.cpp * Update dynamic_programming/Unbounded_0_1_Knapsack.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update Unbounded_0_1_Knapsack.cpp * Update Unbounded_0_1_Knapsack.cpp --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- .../Unbounded_0_1_Knapsack.cpp | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 dynamic_programming/Unbounded_0_1_Knapsack.cpp diff --git a/dynamic_programming/Unbounded_0_1_Knapsack.cpp b/dynamic_programming/Unbounded_0_1_Knapsack.cpp new file mode 100644 index 00000000000..96588fe3936 --- /dev/null +++ b/dynamic_programming/Unbounded_0_1_Knapsack.cpp @@ -0,0 +1,151 @@ +/** + * @file + * @brief Implementation of the Unbounded 0/1 Knapsack Problem + * + * @details + * The Unbounded 0/1 Knapsack problem allows taking unlimited quantities of each item. + * The goal is to maximize the total value without exceeding the given knapsack capacity. + * Unlike the 0/1 knapsack, where each item can be taken only once, in this variation, + * any item can be picked any number of times as long as the total weight stays within + * the knapsack's capacity. + * + * Given a set of N items, each with a weight and a value, represented by the arrays + * `wt` and `val` respectively, and a knapsack with a weight limit W, the task is to + * fill the knapsack to maximize the total value. + * + * @note weight and value of items is greater than zero + * + * ### Algorithm + * The approach uses dynamic programming to build a solution iteratively. + * A 2D array is used for memoization to store intermediate results, allowing + * the function to avoid redundant calculations. + * + * @author [Sanskruti Yeole](https://github.com/yeolesanskruti) + * @see dynamic_programming/0_1_knapsack.cpp + */ + +#include // Standard input-output stream +#include // Standard library for using dynamic arrays (vectors) +#include // For using assert function to validate test cases +#include // For fixed-width integer types like std::uint16_t + +/** + * @namespace dynamic_programming + * @brief Namespace for dynamic programming algorithms + */ +namespace dynamic_programming { + +/** + * @namespace Knapsack + * @brief Implementation of unbounded 0-1 knapsack problem + */ +namespace unbounded_knapsack { + +/** + * @brief Recursive function to calculate the maximum value obtainable using + * an unbounded knapsack approach. + * + * @param i Current index in the value and weight vectors. + * @param W Remaining capacity of the knapsack. + * @param val Vector of values corresponding to the items. + * @note "val" data type can be changed according to the size of the input. + * @param wt Vector of weights corresponding to the items. + * @note "wt" data type can be changed according to the size of the input. + * @param dp 2D vector for memoization to avoid redundant calculations. + * @return The maximum value that can be obtained for the given index and capacity. + */ +std::uint16_t KnapSackFilling(std::uint16_t i, std::uint16_t W, + const std::vector& val, + const std::vector& wt, + std::vector>& dp) { + if (i == 0) { + if (wt[0] <= W) { + return (W / wt[0]) * val[0]; // Take as many of the first item as possible + } else { + return 0; // Can't take the first item + } + } + if (dp[i][W] != -1) return dp[i][W]; // Return result if available + + int nottake = KnapSackFilling(i - 1, W, val, wt, dp); // Value without taking item i + int take = 0; + if (W >= wt[i]) { + take = val[i] + KnapSackFilling(i, W - wt[i], val, wt, dp); // Value taking item i + } + return dp[i][W] = std::max(take, nottake); // Store and return the maximum value +} + +/** + * @brief Wrapper function to initiate the unbounded knapsack calculation. + * + * @param N Number of items. + * @param W Maximum weight capacity of the knapsack. + * @param val Vector of values corresponding to the items. + * @param wt Vector of weights corresponding to the items. + * @return The maximum value that can be obtained for the given capacity. + */ +std::uint16_t unboundedKnapsack(std::uint16_t N, std::uint16_t W, + const std::vector& val, + const std::vector& wt) { + if(N==0)return 0; // Expect 0 since no items + std::vector> dp(N, std::vector(W + 1, -1)); // Initialize memoization table + return KnapSackFilling(N - 1, W, val, wt, dp); // Start the calculation +} + +} // unbounded_knapsack + +} // dynamic_programming + +/** + * @brief self test implementation + * @return void + */ +static void tests() { + // Test Case 1 + std::uint16_t N1 = 4; // Number of items + std::vector wt1 = {1, 3, 4, 5}; // Weights of the items + std::vector val1 = {6, 1, 7, 7}; // Values of the items + std::uint16_t W1 = 8; // Maximum capacity of the knapsack + // Test the function and assert the expected output + assert(unboundedKnapsack(N1, W1, val1, wt1) == 48); + std::cout << "Maximum Knapsack value " << unboundedKnapsack(N1, W1, val1, wt1) << std::endl; + + // Test Case 2 + std::uint16_t N2 = 3; // Number of items + std::vector wt2 = {10, 20, 30}; // Weights of the items + std::vector val2 = {60, 100, 120}; // Values of the items + std::uint16_t W2 = 5; // Maximum capacity of the knapsack + // Test the function and assert the expected output + assert(unboundedKnapsack(N2, W2, val2, wt2) == 0); + std::cout << "Maximum Knapsack value " << unboundedKnapsack(N2, W2, val2, wt2) << std::endl; + + // Test Case 3 + std::uint16_t N3 = 3; // Number of items + std::vector wt3 = {2, 4, 6}; // Weights of the items + std::vector val3 = {5, 11, 13};// Values of the items + std::uint16_t W3 = 27;// Maximum capacity of the knapsack + // Test the function and assert the expected output + assert(unboundedKnapsack(N3, W3, val3, wt3) == 27); + std::cout << "Maximum Knapsack value " << unboundedKnapsack(N3, W3, val3, wt3) << std::endl; + + // Test Case 4 + std::uint16_t N4 = 0; // Number of items + std::vector wt4 = {}; // Weights of the items + std::vector val4 = {}; // Values of the items + std::uint16_t W4 = 10; // Maximum capacity of the knapsack + assert(unboundedKnapsack(N4, W4, val4, wt4) == 0); + std::cout << "Maximum Knapsack value for empty arrays: " << unboundedKnapsack(N4, W4, val4, wt4) << std::endl; + + std::cout << "All test cases passed!" << std::endl; + +} + +/** + * @brief main function + * @return 0 on successful exit + */ +int main() { + tests(); // Run self test implementation + return 0; +} + From 649a145234b2ce7842760bc18832b897f3ae22d3 Mon Sep 17 00:00:00 2001 From: Ritobroto Kalita Date: Tue, 29 Oct 2024 22:38:49 +0530 Subject: [PATCH 66/74] docs, test: Fit Sieve of Eratosthenes to contributing guidelines (#2803) * Update sieve_of_eratosthenes.cpp * Update doc --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- math/sieve_of_eratosthenes.cpp | 94 ++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 22 deletions(-) diff --git a/math/sieve_of_eratosthenes.cpp b/math/sieve_of_eratosthenes.cpp index e011b6c0018..e003706d12b 100644 --- a/math/sieve_of_eratosthenes.cpp +++ b/math/sieve_of_eratosthenes.cpp @@ -1,6 +1,7 @@ /** * @file - * @brief Get list of prime numbers using Sieve of Eratosthenes + * @brief Prime Numbers using [Sieve of + * Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) * @details * Sieve of Eratosthenes is an algorithm that finds all the primes * between 2 and N. @@ -11,21 +12,39 @@ * @see primes_up_to_billion.cpp prime_numbers.cpp */ -#include -#include -#include +#include /// for assert +#include /// for IO operations +#include /// for std::vector /** - * This is the function that finds the primes and eliminates the multiples. + * @namespace math + * @brief Mathematical algorithms + */ +namespace math { +/** + * @namespace sieve_of_eratosthenes + * @brief Functions for finding Prime Numbers using Sieve of Eratosthenes + */ +namespace sieve_of_eratosthenes { +/** + * @brief Function to sieve out the primes + * @details + * This function finds all the primes between 2 and N using the Sieve of + * Eratosthenes algorithm. It starts by assuming all numbers (except zero and + * one) are prime and then iteratively marks the multiples of each prime as + * non-prime. + * * Contains a common optimization to start eliminating multiples of * a prime p starting from p * p since all of the lower multiples * have been already eliminated. - * @param N number of primes to check - * @return is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not + * @param N number till which primes are to be found + * @return is_prime a vector of `N + 1` booleans identifying if `i`^th number is + * a prime or not */ std::vector sieve(uint32_t N) { - std::vector is_prime(N + 1, true); - is_prime[0] = is_prime[1] = false; + std::vector is_prime(N + 1, true); // Initialize all as prime numbers + is_prime[0] = is_prime[1] = false; // 0 and 1 are not prime numbers + for (uint32_t i = 2; i * i <= N; i++) { if (is_prime[i]) { for (uint32_t j = i * i; j <= N; j += i) { @@ -37,9 +56,10 @@ std::vector sieve(uint32_t N) { } /** - * This function prints out the primes to STDOUT - * @param N number of primes to check - * @param is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not + * @brief Function to print the prime numbers + * @param N number till which primes are to be found + * @param is_prime a vector of `N + 1` booleans identifying if `i`^th number is + * a prime or not */ void print(uint32_t N, const std::vector &is_prime) { for (uint32_t i = 2; i <= N; i++) { @@ -50,23 +70,53 @@ void print(uint32_t N, const std::vector &is_prime) { std::cout << std::endl; } +} // namespace sieve_of_eratosthenes +} // namespace math + /** - * Test implementations + * @brief Self-test implementations + * @return void */ -void tests() { - // 0 1 2 3 4 5 6 7 8 9 10 - std::vector ans{false, false, true, true, false, true, false, true, false, false, false}; - assert(sieve(10) == ans); +static void tests() { + std::vector is_prime_1 = + math::sieve_of_eratosthenes::sieve(static_cast(10)); + std::vector is_prime_2 = + math::sieve_of_eratosthenes::sieve(static_cast(20)); + std::vector is_prime_3 = + math::sieve_of_eratosthenes::sieve(static_cast(100)); + + std::vector expected_1{false, false, true, true, false, true, + false, true, false, false, false}; + assert(is_prime_1 == expected_1); + + std::vector expected_2{false, false, true, true, false, true, + false, true, false, false, false, true, + false, true, false, false, false, true, + false, true, false}; + assert(is_prime_2 == expected_2); + + std::vector expected_3{ + false, false, true, true, false, true, false, true, false, false, + false, true, false, true, false, false, false, true, false, true, + false, false, false, true, false, false, false, false, false, true, + false, true, false, false, false, false, false, true, false, false, + false, true, false, true, false, false, false, true, false, false, + false, false, false, true, false, false, false, false, false, true, + false, true, false, false, false, false, false, true, false, false, + false, true, false, true, false, false, false, false, false, true, + false, false, false, true, false, false, false, false, false, true, + false, false, false, false, false, false, false, true, false, false, + false}; + assert(is_prime_3 == expected_3); + + std::cout << "All tests have passed successfully!\n"; } /** - * Main function + * @brief Main function + * @returns 0 on exit */ int main() { tests(); - - uint32_t N = 100; - std::vector is_prime = sieve(N); - print(N, is_prime); return 0; } From 85d62bb80dc8eb3a51c1169a39a0374d18c4fe04 Mon Sep 17 00:00:00 2001 From: Harshil Shah <143382356+HarshilShah1804@users.noreply.github.com> Date: Fri, 1 Nov 2024 22:51:52 +0530 Subject: [PATCH 67/74] docs, test: Fit Topological Sort algorithm to contributing guidelines (#2835) * Modified docs,test of topological sort algorithm * Update topological_sort.cpp * Add class "Graph" * Update graph/topological_sort.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Add namespace topological_sort --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- graph/topological_sort.cpp | 215 ++++++++++++++++++++++++++++++------- 1 file changed, 177 insertions(+), 38 deletions(-) diff --git a/graph/topological_sort.cpp b/graph/topological_sort.cpp index 5de8ed69e7f..6ff81b473f1 100644 --- a/graph/topological_sort.cpp +++ b/graph/topological_sort.cpp @@ -1,50 +1,189 @@ -#include -#include -#include - -int number_of_vertices, - number_of_edges; // For number of Vertices (V) and number of edges (E) -std::vector> graph; -std::vector visited; -std::vector topological_order; - -void dfs(int v) { - visited[v] = true; - for (int u : graph[v]) { - if (!visited[u]) { - dfs(u); +/** + * @file + * @brief [Topological Sort + * Algorithm](https://en.wikipedia.org/wiki/Topological_sorting) + * @details + * Topological sorting of a directed graph is a linear ordering or its vertices + * such that for every directed edge (u,v) from vertex u to vertex v, u comes + * before v in the oredering. + * + * A topological sort is possible only in a directed acyclic graph (DAG). + * This file contains code of finding topological sort using Kahn's Algorithm + * which involves using Depth First Search technique + */ + +#include // For std::reverse +#include // For assert +#include // For IO operations +#include // For std::stack +#include // For std::invalid_argument +#include // For std::vector + +/** + * @namespace graph + * @brief Graph algorithms + */ +namespace graph { + +/** + * @namespace topological_sort + * @brief Topological Sort Algorithm + */ +namespace topological_sort { +/** + * @class Graph + * @brief Class that represents a directed graph and provides methods for + * manipulating the graph + */ +class Graph { + private: + int n; // Number of nodes + std::vector> adj; // Adjacency list representation + + public: + /** + * @brief Constructor for the Graph class + * @param nodes Number of nodes in the graph + */ + Graph(int nodes) : n(nodes), adj(nodes) {} + + /** + * @brief Function that adds an edge between two nodes or vertices of graph + * @param u Start node of the edge + * @param v End node of the edge + */ + void addEdge(int u, int v) { adj[u].push_back(v); } + + /** + * @brief Get the adjacency list of the graph + * @returns A reference to the adjacency list + */ + const std::vector>& getAdjacencyList() const { + return adj; + } + + /** + * @brief Get the number of nodes in the graph + * @returns The number of nodes + */ + int getNumNodes() const { return n; } +}; + +/** + * @brief Function to perform Depth First Search on the graph + * @param v Starting vertex for depth-first search + * @param visited Array representing whether each node has been visited + * @param graph Adjacency list of the graph + * @param s Stack containing the vertices for topological sorting + */ +void dfs(int v, std::vector& visited, + const std::vector>& graph, std::stack& s) { + visited[v] = 1; + for (int neighbour : graph[v]) { + if (!visited[neighbour]) { + dfs(neighbour, visited, graph, s); } } - topological_order.push_back(v); + s.push(v); } -void topological_sort() { - visited.assign(number_of_vertices, false); - topological_order.clear(); - for (int i = 0; i < number_of_vertices; ++i) { +/** + * @brief Function to get the topological sort of the graph + * @param g Graph object + * @returns A vector containing the topological order of nodes + */ +std::vector topologicalSort(const Graph& g) { + int n = g.getNumNodes(); + const auto& adj = g.getAdjacencyList(); + std::vector visited(n, 0); + std::stack s; + + for (int i = 0; i < n; i++) { if (!visited[i]) { - dfs(i); + dfs(i, visited, adj, s); } } - reverse(topological_order.begin(), topological_order.end()); + + std::vector ans; + while (!s.empty()) { + int elem = s.top(); + s.pop(); + ans.push_back(elem); + } + + if (ans.size() < n) { // Cycle detected + throw std::invalid_argument("cycle detected in graph"); + } + return ans; } -int main() { - std::cout - << "Enter the number of vertices and the number of directed edges\n"; - std::cin >> number_of_vertices >> number_of_edges; - int x = 0, y = 0; - graph.resize(number_of_vertices, std::vector()); - for (int i = 0; i < number_of_edges; ++i) { - std::cin >> x >> y; - x--, y--; // to convert 1-indexed to 0-indexed - graph[x].push_back(y); - } - topological_sort(); - std::cout << "Topological Order : \n"; - for (int v : topological_order) { - std::cout << v + 1 - << ' '; // converting zero based indexing back to one based. +} // namespace topological_sort +} // namespace graph + +/** + * @brief Self-test implementation + * @returns void + */ +static void test() { + // Test 1 + std::cout << "Testing for graph 1\n"; + int n_1 = 6; + graph::topological_sort::Graph graph1(n_1); + graph1.addEdge(4, 0); + graph1.addEdge(5, 0); + graph1.addEdge(5, 2); + graph1.addEdge(2, 3); + graph1.addEdge(3, 1); + graph1.addEdge(4, 1); + std::vector ans_1 = graph::topological_sort::topologicalSort(graph1); + std::vector expected_1 = {5, 4, 2, 3, 1, 0}; + std::cout << "Topological Sorting Order: "; + for (int i : ans_1) { + std::cout << i << " "; + } + std::cout << '\n'; + assert(ans_1 == expected_1); + std::cout << "Test Passed\n\n"; + + // Test 2 + std::cout << "Testing for graph 2\n"; + int n_2 = 5; + graph::topological_sort::Graph graph2(n_2); + graph2.addEdge(0, 1); + graph2.addEdge(0, 2); + graph2.addEdge(1, 2); + graph2.addEdge(2, 3); + graph2.addEdge(1, 3); + graph2.addEdge(2, 4); + std::vector ans_2 = graph::topological_sort::topologicalSort(graph2); + std::vector expected_2 = {0, 1, 2, 4, 3}; + std::cout << "Topological Sorting Order: "; + for (int i : ans_2) { + std::cout << i << " "; } std::cout << '\n'; + assert(ans_2 == expected_2); + std::cout << "Test Passed\n\n"; + + // Test 3 - Graph with cycle + std::cout << "Testing for graph 3\n"; + int n_3 = 3; + graph::topological_sort::Graph graph3(n_3); + graph3.addEdge(0, 1); + graph3.addEdge(1, 2); + graph3.addEdge(2, 0); + try { + graph::topological_sort::topologicalSort(graph3); + } catch (std::invalid_argument& err) { + assert(std::string(err.what()) == "cycle detected in graph"); + } + std::cout << "Test Passed\n"; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self test implementations return 0; } From 5fd64423deb284b3b115626a06d30a479c2fa230 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 2 Nov 2024 23:30:26 +0530 Subject: [PATCH 68/74] docs: updating `DIRECTORY.md` (#2875) * docs: update DIRECTORY.md * docs: update DIRECTORY.md * clang-format and clang-tidy fixes for d0663990 --------- Co-authored-by: github-actions[bot] Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- DIRECTORY.md | 4 +++- ...{Unbounded_0_1_Knapsack.cpp => unbounded_0_1_knapsack.cpp} | 0 2 files changed, 3 insertions(+), 1 deletion(-) rename dynamic_programming/{Unbounded_0_1_Knapsack.cpp => unbounded_0_1_knapsack.cpp} (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 4ba06fa0b28..00b38f217eb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -160,6 +160,7 @@ * [Spirograph](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/graphics/spirograph.cpp) ## Greedy Algorithms + * [Binary Addition](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/binary_addition.cpp) * [Boruvkas Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/boruvkas_minimum_spanning_tree.cpp) * [Digit Separation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/digit_separation.cpp) * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/dijkstra.cpp) @@ -304,6 +305,7 @@ * [Lfu Cache](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/lfu_cache.cpp) * [Longest Substring Without Repeating Characters](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/longest_substring_without_repeating_characters.cpp) * [Lru Cache](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/lru_cache.cpp) + * [Lru Cache2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/lru_cache2.cpp) * [Matrix Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/matrix_exponentiation.cpp) * [Palindrome Of Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/palindrome_of_number.cpp) * [Paranthesis Matching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/others/paranthesis_matching.cpp) @@ -340,7 +342,6 @@ * [Sparse Table](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/range_queries/sparse_table.cpp) ## Search - * [Longest Increasing Subsequence Using Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/Longest_Increasing_Subsequence_using_binary_search.cpp) * [Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/binary_search.cpp) * [Exponential Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/exponential_search.cpp) * [Fibonacci Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/fibonacci_search.cpp) @@ -350,6 +351,7 @@ * [Interpolation Search2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/interpolation_search2.cpp) * [Jump Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/jump_search.cpp) * [Linear Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/linear_search.cpp) + * [Longest Increasing Subsequence Using Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/longest_increasing_subsequence_using_binary_search.cpp) * [Median Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/median_search.cpp) * [Median Search2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/median_search2.cpp) * [Saddleback Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/search/saddleback_search.cpp) diff --git a/dynamic_programming/Unbounded_0_1_Knapsack.cpp b/dynamic_programming/unbounded_0_1_knapsack.cpp similarity index 100% rename from dynamic_programming/Unbounded_0_1_Knapsack.cpp rename to dynamic_programming/unbounded_0_1_knapsack.cpp From 9b1d7024af5f53f8fe0b57c224d48208fa25dd39 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 3 Nov 2024 19:44:03 +0530 Subject: [PATCH 69/74] docs: update DIRECTORY.md (#2896) Co-authored-by: github-actions[bot] Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 00b38f217eb..05fe99c0c11 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -122,6 +122,7 @@ * [Subset Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/subset_sum.cpp) * [Trapped Rainwater](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/trapped_rainwater.cpp) * [Tree Height](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/tree_height.cpp) + * [Unbounded 0 1 Knapsack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/unbounded_0_1_knapsack.cpp) * [Word Break](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/word_break.cpp) ## Games From c6af94350830a38824fb69ca21b8b4bb111a1f49 Mon Sep 17 00:00:00 2001 From: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:38:54 +0530 Subject: [PATCH 70/74] fix: add cstdint header to all files using fixed width integers (#2717) * fix: add to subset_sum.cpp * fix: add to subarray_sum.cpp * fix: add to wildcard_matching.cpp * fix: add to count_bit_flips.cpp * fix: add to count_of_set_bits.cpp * fix: add to trailing_ciphers.cpp * fix: add to hamming_distance.cpp * doc: include doc for hamming_distance * fix: add to next_higher_numebr_with_same_number_of_set_bits.cpp * fix: add to power_of_2.cpp * fix: add to set_kth_bit.cpp * fix: add to bit_manipulation/set_kth_bit.cpp * fix: add to bit_manipulation/travelling_salesman_using_bit_manipulation.cpp * fix: add to ciphers/base64_encoding.cpp * fix: add to ciphers/hill_cipher.cpp * fix: add to ciphers/uint128_t.hpp * fix: add to data_structures/dsu_path_compression.cpp * fix: add to data_structures/dsu_path_compression.cpp * fix add to datastructures/list_array>cpp * fix add to datastructures/queue_using_array.cpp * fix: add to sparse_table.cpp * fix: add to stack_using_list_queue.cpp * fix: add to treap.cpp * fix: add to graham_scan_functions.hpp * fix: add to graph/** * fix: add integral typdefs to hashing/** * fix: add to math/** * fix: add to numerical_methods/** * fix: add to other/** * fix: add to search/** * fix: add to sorting/** * fix: add to string/** * doc: remove include statement from comment * fix: make tests static Co-authored-by: David Leal * fix: make tests static Co-authored-by: David Leal * chore: use iwyu on backtracking/**.cpp * chore: use iwyu on bit_manip/**.cpp * chore: use iwyu on ciphers/**.cpp * chore: use iwyu on cpu_scheduling_algorithms/**.cpp * chore: use iwyu on data_structures/**.cpp * chore: use iwyu on divide_and_conquer/**.cpp * chore: use iwyu on geometry/**.cpp * chore: use iwyu on graph/**.cpp * chore: use iwyu on hashing/**.cpp * chore: use iwyu on machine_learning/**.cpp * chore: use iwyu on math/**.cpp * chore: use iwyu on numerical_methods/**.cpp * chore: use iwyu on others/**.cpp * chore: use iwyu on probablity/**.cpp * chore: use iwyu on search/**.cpp * chore: use iwyu on sorting/**.cpp * chore: use iwyu on strings/**.cpp * Revert "chore: use iwyu on strings/**.cpp" This reverts commit f2127456a8eb3e25fc54f39e129578677838f6a4. * Revert "chore: use iwyu on sorting/**.cpp" This reverts commit a290ae7ee2bc73c32348aa74ef622794d02d4938. * Revert "chore: use iwyu on search/**.cpp" This reverts commit 19d136ae0fe13798b58b74a7932ce4c7a3950453. * Revert "chore: use iwyu on probablity/**.cpp" This reverts commit 5dd7f82a34501dc48b985c9fe4822cfa2ef125c2. * Revert "chore: use iwyu on others/**.cpp" This reverts commit 8a8fd42383207c24bee7dbf8f502ceb339b0e63d. * Revert "chore: use iwyu on numerical_methods/**.cpp" This reverts commit eff2f44a502aa437903938c6a9ebbc0f8ac7d278. * Revert "chore: use iwyu on math/**.cpp" This reverts commit c47117ca3f02aee4ba054b861bf7ab44e2ae6348. * Revert "chore: use iwyu on machine_learning/**.cpp" This reverts commit c3897d3763c5f0fb0077d761f824e754b7b181da. * Revert "chore: use iwyu on hashing/**.cpp" This reverts commit 0c6611a835d75718ae060b8b634ce47c85d7690b. * Revert "chore: use iwyu on graph/**.cpp" This reverts commit dabd6d2591d2feeefec2aa512fdcfd335e600606. * Revert "chore: use iwyu on geometry/**.cpp" This reverts commit 740bd65932f7db3e94b2f541b7eb3b9859be61c9. * Revert "chore: use iwyu on divide_and_conquer/**.cpp" This reverts commit 16ee49e0868d28d7c5fbefaf86d8e5a2b1c7cd7d. * Revert "chore: use iwyu on data_structures/**.cpp" This reverts commit a3b719e3684d32d966ed64f31d3c20bdfd3b5ea3. * Revert "chore: use iwyu on cpu_scheduling_algorithms/**.cpp" This reverts commit 24e597f7e249c7fd6998b2db39eba7a91d484455. * Revert "chore: use iwyu on ciphers/**.cpp" This reverts commit 3d80295883d15a6753f1e0e746c19a0c3ea35abe. * Revert "chore: use iwyu on bit_manip/**.cpp" This reverts commit 7edcb6e458fecd7ed05a7d4e87418680f443ec23. * Revert "chore: use iwyu on backtracking/**.cpp" This reverts commit f0a30d7cdbc0b06330b02d9ff0387feb3d9b380b. * Update search/binary_search.cpp * Update backtracking/subarray_sum.cpp * Update backtracking/subset_sum.cpp * Update backtracking/wildcard_matching.cpp * Update bit_manipulation/count_bits_flip.cpp * Update bit_manipulation/count_of_set_bits.cpp * Update bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp * Update bit_manipulation/hamming_distance.cpp * Update bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp * Update bit_manipulation/power_of_2.cpp * Update others/lru_cache.cpp * Update bit_manipulation/set_kth_bit.cpp * Update bit_manipulation/travelling_salesman_using_bit_manipulation.cpp * Update ciphers/base64_encoding.cpp * Update ciphers/hill_cipher.cpp * Update ciphers/uint128_t.hpp * Update cpu_scheduling_algorithms/fcfs_scheduling.cpp * Update data_structures/dsu_path_compression.cpp * Update data_structures/dsu_union_rank.cpp * Update data_structures/list_array.cpp * Update data_structures/queue_using_array.cpp * Update data_structures/sparse_table.cpp * Update data_structures/stack_using_queue.cpp * Update data_structures/treap.cpp * Update geometry/graham_scan_functions.hpp * Update graph/bidirectional_dijkstra.cpp * Update graph/connected_components_with_dsu.cpp * Update graph/cycle_check_directed_graph.cpp * Update graph/is_graph_bipartite2.cpp * Update graph/travelling_salesman_problem.cpp * Update hashing/md5.cpp * Update hashing/sha1.cpp * Update math/n_choose_r.cpp * Update strings/z_function.cpp * Update strings/manacher_algorithm.cpp * Update sorting/wiggle_sort.cpp * Update sorting/selection_sort_recursive.cpp * Update sorting/selection_sort_iterative.cpp * Update sorting/recursive_bubble_sort.cpp * Update sorting/radix_sort2.cpp * Update sorting/dnf_sort.cpp * Update sorting/cycle_sort.cpp * Update search/sublist_search.cpp * Update search/saddleback_search.cpp * Update search/interpolation_search.cpp * Update search/floyd_cycle_detection_algo.cpp * Update search/exponential_search.cpp * Update search/exponential_search.cpp * Update math/n_bonacci.cpp * Update math/aliquot_sum.cpp * Update math/check_factorial.cpp * Update math/double_factorial.cpp * Update math/eulers_totient_function.cpp * Update math/factorial.cpp * Update math/fibonacci.cpp * Update math/fibonacci_matrix_exponentiation.cpp * Update math/fibonacci_sum.cpp * Update math/finding_number_of_digits_in_a_number.cpp * chore: remove "/// for integral typedefs" * chore: remove for integral typedefs from modular division * fix: remove comment from include * fix: add cstdint to gale shapely --------- Co-authored-by: David Leal --- backtracking/subarray_sum.cpp | 1 + backtracking/subset_sum.cpp | 1 + backtracking/wildcard_matching.cpp | 1 + bit_manipulation/count_bits_flip.cpp | 1 + bit_manipulation/count_of_set_bits.cpp | 1 + ...unt_of_trailing_ciphers_in_factorial_n.cpp | 1 + bit_manipulation/hamming_distance.cpp | 1 + ...er_number_with_same_number_of_set_bits.cpp | 1 + bit_manipulation/power_of_2.cpp | 1 + bit_manipulation/set_kth_bit.cpp | 1 + ...elling_salesman_using_bit_manipulation.cpp | 1 + ciphers/base64_encoding.cpp | 1 + ciphers/hill_cipher.cpp | 1 + ciphers/uint128_t.hpp | 1 + cpu_scheduling_algorithms/fcfs_scheduling.cpp | 1 + data_structures/dsu_path_compression.cpp | 1 + data_structures/dsu_union_rank.cpp | 1 + data_structures/list_array.cpp | 344 +++++++++--------- data_structures/queue_using_array.cpp | 1 + data_structures/sparse_table.cpp | 1 + data_structures/stack_using_queue.cpp | 1 + data_structures/treap.cpp | 7 +- dynamic_programming/trapped_rainwater.cpp | 4 +- geometry/graham_scan_functions.hpp | 1 + graph/bidirectional_dijkstra.cpp | 1 + graph/connected_components_with_dsu.cpp | 19 +- graph/cycle_check_directed_graph.cpp | 1 + graph/is_graph_bipartite2.cpp | 1 + graph/travelling_salesman_problem.cpp | 1 + greedy_algorithms/gale_shapley.cpp | 96 +++-- hashing/md5.cpp | 1 + hashing/sha1.cpp | 1 + math/aliquot_sum.cpp | 1 + math/check_factorial.cpp | 1 + math/double_factorial.cpp | 1 + math/eulers_totient_function.cpp | 14 +- math/factorial.cpp | 2 +- math/fibonacci.cpp | 2 + math/fibonacci_matrix_exponentiation.cpp | 163 +++++---- math/fibonacci_sum.cpp | 1 + math/finding_number_of_digits_in_a_number.cpp | 1 + math/integral_approximation.cpp | 35 +- math/inv_sqrt.cpp | 2 +- math/largest_power.cpp | 105 +++--- math/lcm_sum.cpp | 1 + math/linear_recurrence_matrix.cpp | 1 + math/magic_number.cpp | 1 + math/modular_division.cpp | 1 + math/modular_exponentiation.cpp | 2 +- math/modular_inverse_simple.cpp | 1 + math/n_bonacci.cpp | 2 +- math/n_choose_r.cpp | 2 +- math/sieve_of_eratosthenes.cpp | 2 +- math/string_fibonacci.cpp | 1 + math/sum_of_binomial_coefficient.cpp | 1 + numerical_methods/brent_method_extrema.cpp | 1 + numerical_methods/durand_kerner_roots.cpp | 1 + numerical_methods/fast_fourier_transform.cpp | 1 + numerical_methods/golden_search_extrema.cpp | 1 + .../inverse_fast_fourier_transform.cpp | 1 + numerical_methods/newton_raphson_method.cpp | 1 + numerical_methods/rungekutta.cpp | 2 +- others/easter.cpp | 1 + others/kadanes3.cpp | 2 +- others/lru_cache.cpp | 1 + search/binary_search.cpp | 1 + search/exponential_search.cpp | 2 +- search/floyd_cycle_detection_algo.cpp | 2 +- search/interpolation_search.cpp | 1 + search/saddleback_search.cpp | 51 +-- search/sublist_search.cpp | 1 + sorting/cycle_sort.cpp | 1 + sorting/dnf_sort.cpp | 1 + sorting/quick_sort.cpp | 1 + sorting/radix_sort2.cpp | 2 + sorting/recursive_bubble_sort.cpp | 51 +-- sorting/selection_sort_iterative.cpp | 1 + sorting/selection_sort_recursive.cpp | 7 +- sorting/wiggle_sort.cpp | 3 +- strings/manacher_algorithm.cpp | 1 + strings/z_function.cpp | 1 + 81 files changed, 559 insertions(+), 420 deletions(-) diff --git a/backtracking/subarray_sum.cpp b/backtracking/subarray_sum.cpp index 8001d74cc0d..ba9834e87a6 100644 --- a/backtracking/subarray_sum.cpp +++ b/backtracking/subarray_sum.cpp @@ -14,6 +14,7 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for unordered_map #include /// for std::vector diff --git a/backtracking/subset_sum.cpp b/backtracking/subset_sum.cpp index fad820920a5..8551a66e0ca 100644 --- a/backtracking/subset_sum.cpp +++ b/backtracking/subset_sum.cpp @@ -10,6 +10,7 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector diff --git a/backtracking/wildcard_matching.cpp b/backtracking/wildcard_matching.cpp index d9163a41b48..cd0bd72ad8c 100644 --- a/backtracking/wildcard_matching.cpp +++ b/backtracking/wildcard_matching.cpp @@ -12,6 +12,7 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector diff --git a/bit_manipulation/count_bits_flip.cpp b/bit_manipulation/count_bits_flip.cpp index 5a6584b7241..2ab2ce31c15 100644 --- a/bit_manipulation/count_bits_flip.cpp +++ b/bit_manipulation/count_bits_flip.cpp @@ -20,6 +20,7 @@ * @author [Yash Raj Singh](https://github.com/yashrajyash) */ #include /// for assert +#include #include /// for IO operations /** * @namespace bit_manipulation diff --git a/bit_manipulation/count_of_set_bits.cpp b/bit_manipulation/count_of_set_bits.cpp index f2d802061cc..dd29fd8bf19 100644 --- a/bit_manipulation/count_of_set_bits.cpp +++ b/bit_manipulation/count_of_set_bits.cpp @@ -16,6 +16,7 @@ * @author [Prashant Thakur](https://github.com/prashant-th18) */ #include /// for assert +#include #include /// for IO operations /** * @namespace bit_manipulation diff --git a/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp b/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp index aa2ceb3dd8a..c1c57d0a617 100644 --- a/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp +++ b/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp @@ -18,6 +18,7 @@ */ #include /// for assert +#include #include /// for IO operations /** diff --git a/bit_manipulation/hamming_distance.cpp b/bit_manipulation/hamming_distance.cpp index 62879cf4883..ca4e9fc5b36 100644 --- a/bit_manipulation/hamming_distance.cpp +++ b/bit_manipulation/hamming_distance.cpp @@ -13,6 +13,7 @@ */ #include /// for assert +#include #include /// for io operations /** diff --git a/bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp b/bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp index d93884d4e11..f6d840f91bd 100644 --- a/bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp +++ b/bit_manipulation/next_higher_number_with_same_number_of_set_bits.cpp @@ -16,6 +16,7 @@ */ #include /// for assert +#include #include /// for IO operations /** diff --git a/bit_manipulation/power_of_2.cpp b/bit_manipulation/power_of_2.cpp index c62bfdaa3f5..f35361c8a9d 100644 --- a/bit_manipulation/power_of_2.cpp +++ b/bit_manipulation/power_of_2.cpp @@ -16,6 +16,7 @@ */ #include /// for assert +#include #include /// for IO operations /** diff --git a/bit_manipulation/set_kth_bit.cpp b/bit_manipulation/set_kth_bit.cpp index a58e663b163..d3d50e6cb28 100644 --- a/bit_manipulation/set_kth_bit.cpp +++ b/bit_manipulation/set_kth_bit.cpp @@ -19,6 +19,7 @@ */ #include /// for assert +#include #include /// for IO operations /** diff --git a/bit_manipulation/travelling_salesman_using_bit_manipulation.cpp b/bit_manipulation/travelling_salesman_using_bit_manipulation.cpp index 31243ed2921..9858b8107a3 100644 --- a/bit_manipulation/travelling_salesman_using_bit_manipulation.cpp +++ b/bit_manipulation/travelling_salesman_using_bit_manipulation.cpp @@ -22,6 +22,7 @@ */ #include /// for std::min #include /// for assert +#include #include /// for IO operations #include /// for limits of integral types #include /// for std::vector diff --git a/ciphers/base64_encoding.cpp b/ciphers/base64_encoding.cpp index a592226a5e7..81459408a8e 100644 --- a/ciphers/base64_encoding.cpp +++ b/ciphers/base64_encoding.cpp @@ -13,6 +13,7 @@ */ #include /// for `std::array` #include /// for `assert` operations +#include #include /// for IO operations /** diff --git a/ciphers/hill_cipher.cpp b/ciphers/hill_cipher.cpp index 1fef0f32e2d..d77a51c22b3 100644 --- a/ciphers/hill_cipher.cpp +++ b/ciphers/hill_cipher.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/ciphers/uint128_t.hpp b/ciphers/uint128_t.hpp index d50cb4ffb2d..7abffb08a61 100644 --- a/ciphers/uint128_t.hpp +++ b/ciphers/uint128_t.hpp @@ -8,6 +8,7 @@ */ #include /// for `std::reverse` and other operations +#include #include /// for `std::cout` overload #include /// for `std::string` #include /// for `std::pair` library diff --git a/cpu_scheduling_algorithms/fcfs_scheduling.cpp b/cpu_scheduling_algorithms/fcfs_scheduling.cpp index 4fc61af6bce..5c5e2fa3c58 100644 --- a/cpu_scheduling_algorithms/fcfs_scheduling.cpp +++ b/cpu_scheduling_algorithms/fcfs_scheduling.cpp @@ -11,6 +11,7 @@ #include /// for sorting #include /// for assert +#include #include /// random number generation #include /// for time #include /// for formatting the output diff --git a/data_structures/dsu_path_compression.cpp b/data_structures/dsu_path_compression.cpp index 022e632a784..c08040570dd 100644 --- a/data_structures/dsu_path_compression.cpp +++ b/data_structures/dsu_path_compression.cpp @@ -19,6 +19,7 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector diff --git a/data_structures/dsu_union_rank.cpp b/data_structures/dsu_union_rank.cpp index 8936d6d6964..16e1d3275bf 100644 --- a/data_structures/dsu_union_rank.cpp +++ b/data_structures/dsu_union_rank.cpp @@ -20,6 +20,7 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector diff --git a/data_structures/list_array.cpp b/data_structures/list_array.cpp index 05c66ed84fa..0c8099f5788 100644 --- a/data_structures/list_array.cpp +++ b/data_structures/list_array.cpp @@ -4,17 +4,20 @@ * * @details * The list_array is the implementation of list represented using array. - * We can perform basic CRUD operations as well as other operations like sorting etc. + * We can perform basic CRUD operations as well as other operations like sorting + * etc. * * ### Algorithm * It implements various method like insert, sort, search etc. efficiently. * You can select the operation and methods will do the rest work for you. - * You can insert element, sort them in order, search efficiently, delete values and print the list. + * You can insert element, sort them in order, search efficiently, delete values + * and print the list. */ -#include /// for io operations -#include /// for std::array -#include /// for assert +#include /// for std::array +#include /// for assert +#include +#include /// for io operations /** * @namespace data_structures @@ -23,181 +26,190 @@ namespace data_structures { /** * @namespace list_array - * @brief Functions for [Dynamic Array](https://en.wikipedia.org/wiki/Dynamic_array) algorithm + * @brief Functions for [Dynamic + * Array](https://en.wikipedia.org/wiki/Dynamic_array) algorithm */ namespace list_array { +/** + * @brief Structure of List with supporting methods. + */ +template +struct list { + std::array data{}; // Array that implement list + uint64_t top = 0; // Pointer to the last element + bool isSorted = false; // indicator whether list is sorted or not /** - * @brief Structure of List with supporting methods. + * @brief Search an element in the list using binarySearch. + * @param dataArr list + * @param first pointer to the first element in the remaining list + * @param last pointer to the last element in the remaining list + * @param val element that will be searched + * @return index of element in the list if present else -1 */ - template - struct list { - std::array data{}; // Array that implement list - uint64_t top = 0; // Pointer to the last element - bool isSorted = false; // indicator whether list is sorted or not - /** - * @brief Search an element in the list using binarySearch. - * @param dataArr list - * @param first pointer to the first element in the remaining list - * @param last pointer to the last element in the remaining list - * @param val element that will be searched - * @return index of element in the list if present else -1 - */ - uint64_t BinarySearch(const std::array &dataArr, const uint64_t &first, const uint64_t &last, - const uint64_t &val) { - // If both pointer cross each other means no element present in the list which is equal to the val - if (last < first) { - return -1; - } - uint64_t mid = (first + last) / 2; - // check whether current mid pointer value is equal to element or not - if (dataArr[mid] == val) - return mid; - // if current mid value is greater than element we have to search in first half - else if (val < dataArr[mid]) - return (BinarySearch(dataArr, first, mid - 1, val)); - // if current mid value is greater than element we have to search in second half - else if (val > dataArr[mid]) - return (BinarySearch(dataArr, mid + 1, last, val)); - - std::cerr << __func__ << ":" << __LINE__ << ": Undefined condition\n"; + uint64_t BinarySearch(const std::array &dataArr, + const uint64_t &first, const uint64_t &last, + const uint64_t &val) { + // If both pointer cross each other means no element present in the list + // which is equal to the val + if (last < first) { return -1; } + uint64_t mid = (first + last) / 2; + // check whether current mid pointer value is equal to element or not + if (dataArr[mid] == val) + return mid; + // if current mid value is greater than element we have to search in + // first half + else if (val < dataArr[mid]) + return (BinarySearch(dataArr, first, mid - 1, val)); + // if current mid value is greater than element we have to search in + // second half + else if (val > dataArr[mid]) + return (BinarySearch(dataArr, mid + 1, last, val)); - /** - * @brief Search an element using linear search - * @param dataArr list - * @param val element that will be searched - * @return index of element in the list if present else -1 - */ - uint64_t LinearSearch(const std::array &dataArr, const uint64_t &val) const { - // Going through each element in the list - for (uint64_t i = 0; i < top; i++) { - if (dataArr[i] == val) { - return i; // element found at ith index - } + std::cerr << __func__ << ":" << __LINE__ << ": Undefined condition\n"; + return -1; + } + + /** + * @brief Search an element using linear search + * @param dataArr list + * @param val element that will be searched + * @return index of element in the list if present else -1 + */ + uint64_t LinearSearch(const std::array &dataArr, + const uint64_t &val) const { + // Going through each element in the list + for (uint64_t i = 0; i < top; i++) { + if (dataArr[i] == val) { + return i; // element found at ith index } - // element is not present in the list - return -1; } + // element is not present in the list + return -1; + } - /* - * @brief Parent function of binarySearch and linearSearch methods - * @param val element that will be searched - * @return index of element in the list if present else -1 - */ - uint64_t search(const uint64_t &val) { - uint64_t pos; // pos variable to store index value of element. - // if list is sorted, binary search works efficiently else linear search is the only option - if (isSorted) { - pos = BinarySearch(data, 0, top - 1, val); - } else { - pos = LinearSearch(data, val); - } - // if index is equal to -1 means element does not present - // else print the index of that element - if (pos != -1) { - std::cout << "\nElement found at position : " << pos; - } else { - std::cout << "\nElement not found"; - } - // return the index of element or -1. - return pos; + /* + * @brief Parent function of binarySearch and linearSearch methods + * @param val element that will be searched + * @return index of element in the list if present else -1 + */ + uint64_t search(const uint64_t &val) { + uint64_t pos; // pos variable to store index value of element. + // if list is sorted, binary search works efficiently else linear search + // is the only option + if (isSorted) { + pos = BinarySearch(data, 0, top - 1, val); + } else { + pos = LinearSearch(data, val); + } + // if index is equal to -1 means element does not present + // else print the index of that element + if (pos != -1) { + std::cout << "\nElement found at position : " << pos; + } else { + std::cout << "\nElement not found"; } + // return the index of element or -1. + return pos; + } - /** - * @brief Sort the list - * @returns void - */ - void sort() { - //Going through each element in the list - for (uint64_t i = 0; i < top; i++) { - uint64_t min_idx = i; // Initialize the min variable - for (uint64_t j = i + 1; j < top; j++) { - // check whether any element less than current min value - if (data[j] < data[min_idx]) { - min_idx = j; // update index accordingly - } + /** + * @brief Sort the list + * @returns void + */ + void sort() { + // Going through each element in the list + for (uint64_t i = 0; i < top; i++) { + uint64_t min_idx = i; // Initialize the min variable + for (uint64_t j = i + 1; j < top; j++) { + // check whether any element less than current min value + if (data[j] < data[min_idx]) { + min_idx = j; // update index accordingly } - // swap min value and element at the ith index - std::swap(data[min_idx], data[i]); } - // mark isSorted variable as true - isSorted = true; + // swap min value and element at the ith index + std::swap(data[min_idx], data[i]); } + // mark isSorted variable as true + isSorted = true; + } - /** - * @brief Insert the new element in the list - * @param val element that will be inserted - * @returns void - */ - void insert(const uint64_t &val) { - // overflow check - if (top == N) { - std::cout << "\nOverflow"; - return; - } - // if list is not sorted, insert at the last - // otherwise place it to correct position - if (!isSorted) { - data[top] = val; - top++; - } else { - uint64_t pos = 0; // Initialize the index variable - // Going through each element and find correct position for element - for (uint64_t i = 0; i < top - 1; i++) { - // check for the correct position - if (data[i] <= val && val <= data[i + 1]) { - pos = i + 1; // assign correct pos to the index var - break; // to get out from the loop - } - } - // if all elements are smaller than the element - if (pos == 0) { - pos = top - 1; - } - // shift all element to make a room for new element - for (uint64_t i = top; i > pos; i--) { - data[i] = data[i - 1]; + /** + * @brief Insert the new element in the list + * @param val element that will be inserted + * @returns void + */ + void insert(const uint64_t &val) { + // overflow check + if (top == N) { + std::cout << "\nOverflow"; + return; + } + // if list is not sorted, insert at the last + // otherwise place it to correct position + if (!isSorted) { + data[top] = val; + top++; + } else { + uint64_t pos = 0; // Initialize the index variable + // Going through each element and find correct position for element + for (uint64_t i = 0; i < top - 1; i++) { + // check for the correct position + if (data[i] <= val && val <= data[i + 1]) { + pos = i + 1; // assign correct pos to the index var + break; // to get out from the loop } - top++; // Increment the value of top. - data[pos] = val; // Assign the value to the correct index in the array } - } - - /** - * @brief To remove the element from the list - * @param val element that will be removed - * @returns void - */ - void remove(const uint64_t &val) { - uint64_t pos = search(val); // search the index of the value - // if search returns -1, element does not present in the list - if (pos == -1) { - std::cout << "\n Element does not present in the list "; - return; + // if all elements are smaller than the element + if (pos == 0) { + pos = top - 1; } - std::cout << "\n" << data[pos] << " deleted"; // print the appropriate message - // shift all the element 1 left to fill vacant space - for (uint64_t i = pos; i < top; i++) { - data[i] = data[i + 1]; + // shift all element to make a room for new element + for (uint64_t i = top; i > pos; i--) { + data[i] = data[i - 1]; } - top--; // decrement the top variable to maintain last index + top++; // Increment the value of top. + data[pos] = + val; // Assign the value to the correct index in the array } + } - /** - * @brief Utility function to print array - * @returns void - */ - void show() { - // Going through each element in the list - std::cout << '\n'; - for (uint64_t i = 0; i < top; i++) { - std::cout << data[i] << " "; // print the element - } + /** + * @brief To remove the element from the list + * @param val element that will be removed + * @returns void + */ + void remove(const uint64_t &val) { + uint64_t pos = search(val); // search the index of the value + // if search returns -1, element does not present in the list + if (pos == -1) { + std::cout << "\n Element does not present in the list "; + return; + } + std::cout << "\n" + << data[pos] << " deleted"; // print the appropriate message + // shift all the element 1 left to fill vacant space + for (uint64_t i = pos; i < top; i++) { + data[i] = data[i + 1]; + } + top--; // decrement the top variable to maintain last index + } + + /** + * @brief Utility function to print array + * @returns void + */ + void show() { + // Going through each element in the list + std::cout << '\n'; + for (uint64_t i = 0; i < top; i++) { + std::cout << data[i] << " "; // print the element } - }; // structure list -} // namespace list_array -} // namespace data_structures + } +}; // structure list +} // namespace list_array +} // namespace data_structures /** * @brief Test implementations @@ -216,19 +228,19 @@ static void test() { L.insert(20); L.insert(18); assert(L.top == 7); - L.show(); // To print the array + L.show(); // To print the array // Remove testing - L.remove(12); // Remove Duplicate value in the list - L.remove(15); // Remove the existing value in the list + L.remove(12); // Remove Duplicate value in the list + L.remove(15); // Remove the existing value in the list assert(L.top == 5); - L.remove(50); // Try to remove the non-existing value in the list + L.remove(50); // Try to remove the non-existing value in the list assert(L.top == 5); // LinearSearch testing - assert(L.search(11) == 0); // search for the existing element + assert(L.search(11) == 0); // search for the existing element assert(L.search(12) == 2); - assert(L.search(50) == -1); // search for the non-existing element + assert(L.search(50) == -1); // search for the non-existing element // Sort testing L.sort(); @@ -236,9 +248,9 @@ static void test() { L.show(); // BinarySearch testing - assert(L.search(11) == 1); // search for the existing element + assert(L.search(11) == 1); // search for the existing element assert(L.search(12) == 2); - assert(L.search(50) == -1); // search for the non-existing element + assert(L.search(50) == -1); // search for the non-existing element } /** @@ -246,6 +258,6 @@ static void test() { * @returns 0 on exit */ int main() { - test(); // Execute the tests + test(); // Execute the tests return 0; } diff --git a/data_structures/queue_using_array.cpp b/data_structures/queue_using_array.cpp index 8b9b387c5b8..c2437258328 100644 --- a/data_structures/queue_using_array.cpp +++ b/data_structures/queue_using_array.cpp @@ -18,6 +18,7 @@ * @author [Farbod Ahmadian](https://github.com/farbodahm) */ #include /// for std::array +#include #include /// for io operations constexpr uint16_t max_size{10}; ///< Maximum size of the queue diff --git a/data_structures/sparse_table.cpp b/data_structures/sparse_table.cpp index b99616ae6b0..7b3d74b90c3 100644 --- a/data_structures/sparse_table.cpp +++ b/data_structures/sparse_table.cpp @@ -24,6 +24,7 @@ #include /// for std::array #include /// for assert +#include #include /// for IO operations /** diff --git a/data_structures/stack_using_queue.cpp b/data_structures/stack_using_queue.cpp index b849fcf053a..c5fc55a3e61 100644 --- a/data_structures/stack_using_queue.cpp +++ b/data_structures/stack_using_queue.cpp @@ -9,6 +9,7 @@ * @author [tushar2407](https://github.com/tushar2407) */ #include /// for assert +#include #include /// for IO operations #include /// for queue data structure diff --git a/data_structures/treap.cpp b/data_structures/treap.cpp index 522876941b1..592f49e7dfb 100644 --- a/data_structures/treap.cpp +++ b/data_structures/treap.cpp @@ -19,6 +19,7 @@ #include /// For array #include /// For assert +#include #include /// For IO operations /** @@ -157,11 +158,9 @@ struct Treap { } if (k == key[x]) { return size[childs[x][0]] + 1; - } - else if (k < key[x]) { + } else if (k < key[x]) { return _get_rank(childs[x][0], k); - } - else { + } else { return size[childs[x][0]] + cnt[x] + _get_rank(childs[x][1], k); } } diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index 8ac80835180..d9e16682754 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -11,8 +11,8 @@ #include /// For std::min and std::max #include /// For assert #include /// For std::size_t -#include /// For integral typedefs -#include /// For std::vector +#include +#include /// For std::vector /* * @namespace diff --git a/geometry/graham_scan_functions.hpp b/geometry/graham_scan_functions.hpp index f6e05095e74..58ac066e498 100644 --- a/geometry/graham_scan_functions.hpp +++ b/geometry/graham_scan_functions.hpp @@ -39,6 +39,7 @@ * *******************************************************************************/ #include /// for std::swap +#include #include /// for mathematics and datatype conversion #include /// for IO operations #include /// for std::stack diff --git a/graph/bidirectional_dijkstra.cpp b/graph/bidirectional_dijkstra.cpp index deef6622758..b4f58d22621 100644 --- a/graph/bidirectional_dijkstra.cpp +++ b/graph/bidirectional_dijkstra.cpp @@ -14,6 +14,7 @@ */ #include /// for assert +#include #include /// for io operations #include /// for variable INF #include /// for the priority_queue of distances diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index c0194e85163..59dc2fda3cd 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -3,20 +3,24 @@ * @brief [Disjoint union](https://en.wikipedia.org/wiki/Disjoint_union) * * @details - * The Disjoint union is the technique to find connected component in graph efficiently. + * The Disjoint union is the technique to find connected component in graph + * efficiently. * * ### Algorithm - * In Graph, if you have to find out the number of connected components, there are 2 options + * In Graph, if you have to find out the number of connected components, there + * are 2 options * 1. Depth first search * 2. Disjoint union - * 1st option is inefficient, Disjoint union is the most optimal way to find this. + * 1st option is inefficient, Disjoint union is the most optimal way to find + * this. * * @author Unknown author * @author [Sagar Pandya](https://github.com/sagarpandyansit) */ -#include /// for IO operations -#include /// for std::set -#include /// for std::vector +#include +#include /// for IO operations +#include /// for std::set +#include /// for std::vector /** * @namespace graph @@ -25,7 +29,8 @@ namespace graph { /** * @namespace disjoint_union - * @brief Functions for [Disjoint union](https://en.wikipedia.org/wiki/Disjoint_union) implementation + * @brief Functions for [Disjoint + * union](https://en.wikipedia.org/wiki/Disjoint_union) implementation */ namespace disjoint_union { uint32_t number_of_nodes = 0; // denotes number of nodes diff --git a/graph/cycle_check_directed_graph.cpp b/graph/cycle_check_directed_graph.cpp index 8a651cfc5f6..15b92c4d6d2 100644 --- a/graph/cycle_check_directed_graph.cpp +++ b/graph/cycle_check_directed_graph.cpp @@ -7,6 +7,7 @@ * */ +#include #include // for std::cout #include // for std::map #include // for std::queue diff --git a/graph/is_graph_bipartite2.cpp b/graph/is_graph_bipartite2.cpp index f1b04d0707b..0711dfb9296 100644 --- a/graph/is_graph_bipartite2.cpp +++ b/graph/is_graph_bipartite2.cpp @@ -15,6 +15,7 @@ * @author [tushar2407](https://github.com/tushar2407) */ #include /// for assert +#include #include /// for IO operations #include /// for queue data structure #include /// for vector data structure diff --git a/graph/travelling_salesman_problem.cpp b/graph/travelling_salesman_problem.cpp index 28df3e93155..1b329d5cb32 100644 --- a/graph/travelling_salesman_problem.cpp +++ b/graph/travelling_salesman_problem.cpp @@ -19,6 +19,7 @@ #include /// for std::min #include /// for assert +#include #include /// for IO operations #include /// for limits of integral types #include /// for std::vector diff --git a/greedy_algorithms/gale_shapley.cpp b/greedy_algorithms/gale_shapley.cpp index ddc6298fa44..6267bf3b160 100644 --- a/greedy_algorithms/gale_shapley.cpp +++ b/greedy_algorithms/gale_shapley.cpp @@ -1,24 +1,26 @@ /** * @file - * @brief [Gale Shapley Algorithm](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) + * @brief [Gale Shapley + * Algorithm](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) * @details - * This implementation utilizes the Gale-Shapley algorithm to find stable matches. + * This implementation utilizes the Gale-Shapley algorithm to find stable + * matches. * - * **Gale Shapley Algorithm** aims to find a stable matching between two equally sized - * sets of elements given an ordinal preference for each element. The algorithm was - * introduced by David Gale and Lloyd Shapley in 1962. - * - * Reference: + * **Gale Shapley Algorithm** aims to find a stable matching between two equally + * sized sets of elements given an ordinal preference for each element. The + * algorithm was introduced by David Gale and Lloyd Shapley in 1962. + * + * Reference: * [Wikipedia](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) * [Wikipedia](https://en.wikipedia.org/wiki/Stable_matching_problem) * * @author [B Karthik](https://github.com/BKarthik7) */ -#include /// for std::u32int_t -#include /// for std::vector #include /// for std::find #include /// for assert +#include /// for std::uint32_t +#include /// for std::vector /** * @namespace @@ -31,19 +33,25 @@ namespace greedy_algorithms { */ namespace stable_matching { /** - * @brief The main function that finds the stable matching between two sets of elements - * using the Gale-Shapley Algorithm. - * @note This doesn't work on negative preferences. the preferences should be continuous integers starting from - * 0 to number of preferences - 1. - * @param primary_preferences the preferences of the primary set should be a 2D vector - * @param secondary_preferences the preferences of the secondary set should be a 2D vector + * @brief The main function that finds the stable matching between two sets of + * elements using the Gale-Shapley Algorithm. + * @note This doesn't work on negative preferences. the preferences should be + * continuous integers starting from 0 to number of preferences - 1. + * @param primary_preferences the preferences of the primary set should be a 2D + * vector + * @param secondary_preferences the preferences of the secondary set should be a + * 2D vector * @returns matches the stable matching between the two sets */ -std::vector gale_shapley(const std::vector>& secondary_preferences, const std::vector>& primary_preferences) { +std::vector gale_shapley( + const std::vector>& secondary_preferences, + const std::vector>& primary_preferences) { std::uint32_t num_elements = secondary_preferences.size(); std::vector matches(num_elements, -1); std::vector is_free_primary(num_elements, true); - std::vector proposal_index(num_elements, 0); // Tracks the next secondary to propose for each primary + std::vector proposal_index( + num_elements, + 0); // Tracks the next secondary to propose for each primary while (true) { int free_primary_index = -1; @@ -57,10 +65,13 @@ std::vector gale_shapley(const std::vector gale_shapley(const std::vector gale_shapley(const std::vector> primary_preferences = {{0, 1, 2, 3}, {2, 1, 3, 0}, {1, 2, 0, 3}, {3, 0, 1, 2}}; - std::vector> secondary_preferences = {{1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; - assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({0, 2, 1, 3})); + std::vector> primary_preferences = { + {0, 1, 2, 3}, {2, 1, 3, 0}, {1, 2, 0, 3}, {3, 0, 1, 2}}; + std::vector> secondary_preferences = { + {1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; + assert(greedy_algorithms::stable_matching::gale_shapley( + secondary_preferences, primary_preferences) == + std::vector({0, 2, 1, 3})); // Test Case 2 - primary_preferences = {{0, 2, 1, 3}, {2, 3, 0, 1}, {3, 1, 2, 0}, {2, 1, 0, 3}}; - secondary_preferences = {{1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; - assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({0, 3, 1, 2})); + primary_preferences = { + {0, 2, 1, 3}, {2, 3, 0, 1}, {3, 1, 2, 0}, {2, 1, 0, 3}}; + secondary_preferences = { + {1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; + assert(greedy_algorithms::stable_matching::gale_shapley( + secondary_preferences, primary_preferences) == + std::vector({0, 3, 1, 2})); // Test Case 3 primary_preferences = {{0, 1, 2}, {2, 1, 0}, {1, 2, 0}}; secondary_preferences = {{1, 0, 2}, {2, 0, 1}, {0, 2, 1}}; - assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({0, 2, 1})); + assert(greedy_algorithms::stable_matching::gale_shapley( + secondary_preferences, primary_preferences) == + std::vector({0, 2, 1})); // Test Case 4 primary_preferences = {}; secondary_preferences = {}; - assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector({})); + assert(greedy_algorithms::stable_matching::gale_shapley( + secondary_preferences, primary_preferences) == + std::vector({})); } /** @@ -124,6 +150,6 @@ static void tests() { * @returns 0 on exit */ int main() { - tests(); // Run self-test implementations + tests(); // Run self-test implementations return 0; } diff --git a/hashing/md5.cpp b/hashing/md5.cpp index aad75731007..52bc898f7d4 100644 --- a/hashing/md5.cpp +++ b/hashing/md5.cpp @@ -41,6 +41,7 @@ #include /// Used for std::copy #include /// Used for std::array #include /// Used for assert +#include #include /// Used for std::memcopy #include /// Used for IO operations #include /// Used for strings diff --git a/hashing/sha1.cpp b/hashing/sha1.cpp index 106da827296..2d551b99316 100644 --- a/hashing/sha1.cpp +++ b/hashing/sha1.cpp @@ -32,6 +32,7 @@ #include /// For std::copy #include /// For std::array #include /// For assert +#include #include /// For std::memcopy #include /// For IO operations #include /// For strings diff --git a/math/aliquot_sum.cpp b/math/aliquot_sum.cpp index 6d94d53a1be..0b8afdf8920 100644 --- a/math/aliquot_sum.cpp +++ b/math/aliquot_sum.cpp @@ -20,6 +20,7 @@ */ #include /// for assert +#include #include /// for IO operations /** diff --git a/math/check_factorial.cpp b/math/check_factorial.cpp index 0be45b89509..0b63433ebe4 100644 --- a/math/check_factorial.cpp +++ b/math/check_factorial.cpp @@ -10,6 +10,7 @@ * @author [ewd00010](https://github.com/ewd00010) */ #include /// for assert +#include #include /// for cout /** diff --git a/math/double_factorial.cpp b/math/double_factorial.cpp index 72feda60c4e..5832ce440d6 100644 --- a/math/double_factorial.cpp +++ b/math/double_factorial.cpp @@ -10,6 +10,7 @@ */ #include +#include #include /** Compute double factorial using iterative method diff --git a/math/eulers_totient_function.cpp b/math/eulers_totient_function.cpp index f1752e9e92a..768034327da 100644 --- a/math/eulers_totient_function.cpp +++ b/math/eulers_totient_function.cpp @@ -1,6 +1,7 @@ /** * @file - * @brief Implementation of [Euler's Totient](https://en.wikipedia.org/wiki/Euler%27s_totient_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) = @@ -24,8 +25,9 @@ * @author [Mann Mehta](https://github.com/mann2108) */ -#include /// for IO operations -#include /// for assert +#include /// for assert +#include +#include /// for IO operations /** * @brief Mathematical algorithms @@ -39,12 +41,14 @@ namespace math { uint64_t phiFunction(uint64_t n) { uint64_t result = n; for (uint64_t i = 2; i * i <= n; i++) { - if (n % i != 0) continue; + 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; } diff --git a/math/factorial.cpp b/math/factorial.cpp index acfa053d89a..aca1886c783 100644 --- a/math/factorial.cpp +++ b/math/factorial.cpp @@ -12,8 +12,8 @@ */ #include /// for assert +#include #include /// for I/O operations - /** * @namespace * @brief Mathematical algorithms diff --git a/math/fibonacci.cpp b/math/fibonacci.cpp index a09ebb57822..79048040ac4 100644 --- a/math/fibonacci.cpp +++ b/math/fibonacci.cpp @@ -9,6 +9,8 @@ * * @see fibonacci_large.cpp, fibonacci_fast.cpp, string_fibonacci.cpp */ + +#include #include /// for assert #include /// for IO operations diff --git a/math/fibonacci_matrix_exponentiation.cpp b/math/fibonacci_matrix_exponentiation.cpp index 1a119d210aa..915cf62b580 100644 --- a/math/fibonacci_matrix_exponentiation.cpp +++ b/math/fibonacci_matrix_exponentiation.cpp @@ -1,101 +1,103 @@ /** - * @file + * @file * @brief This program computes the N^th Fibonacci number in modulo mod * input argument . * * Takes O(logn) time to compute nth Fibonacci number - * + * * * \author [villayatali123](https://github.com/villayatali123) * \author [unknown author]() - * @see fibonacci.cpp, fibonacci_fast.cpp, string_fibonacci.cpp, fibonacci_large.cpp + * @see fibonacci.cpp, fibonacci_fast.cpp, string_fibonacci.cpp, + * fibonacci_large.cpp */ -#include -#include #include +#include +#include +#include /** * This function finds nth fibonacci number in a given modulus * @param n nth fibonacci number - * @param mod modulo number + * @param mod modulo number */ -uint64_t fibo(uint64_t n , uint64_t mod ) -{ - std::vector result(2,0); - std::vector> transition(2,std::vector(2,0)); - std::vector> Identity(2,std::vector(2,0)); - n--; - result[0]=1, result[1]=1; - Identity[0][0]=1; Identity[0][1]=0; - Identity[1][0]=0; Identity[1][1]=1; - - transition[0][0]=0; - transition[1][0]=transition[1][1]=transition[0][1]=1; - - while(n) - { - if(n%2) - { - std::vector> res(2, std::vector(2,0)); - for(int i=0;i<2;i++) - { - for(int j=0;j<2;j++) - { - for(int k=0;k<2;k++) - { - res[i][j]=(res[i][j]%mod+((Identity[i][k]%mod*transition[k][j]%mod))%mod)%mod; - } - } - } - for(int i=0;i<2;i++) - { - for(int j=0;j<2;j++) - { - Identity[i][j]=res[i][j]; - } - } - n--; - } - else{ - std::vector> res1(2, std::vector(2,0)); - for(int i=0;i<2;i++) - { - for(int j=0;j<2;j++) - { - for(int k=0;k<2;k++) - { - res1[i][j]=(res1[i][j]%mod+((transition[i][k]%mod*transition[k][j]%mod))%mod)%mod; - } - } - } - for(int i=0;i<2;i++) - { - for(int j=0;j<2;j++) - { - transition[i][j]=res1[i][j]; - } - } - n=n/2; - } - } - return ((result[0]%mod*Identity[0][0]%mod)%mod+(result[1]%mod*Identity[1][0]%mod)%mod)%mod; +uint64_t fibo(uint64_t n, uint64_t mod) { + std::vector result(2, 0); + std::vector> transition(2, + std::vector(2, 0)); + std::vector> Identity(2, std::vector(2, 0)); + n--; + result[0] = 1, result[1] = 1; + Identity[0][0] = 1; + Identity[0][1] = 0; + Identity[1][0] = 0; + Identity[1][1] = 1; + + transition[0][0] = 0; + transition[1][0] = transition[1][1] = transition[0][1] = 1; + + while (n) { + if (n % 2) { + std::vector> res(2, + std::vector(2, 0)); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + res[i][j] = + (res[i][j] % mod + + ((Identity[i][k] % mod * transition[k][j] % mod)) % + mod) % + mod; + } + } + } + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + Identity[i][j] = res[i][j]; + } + } + n--; + } else { + std::vector> res1( + 2, std::vector(2, 0)); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + res1[i][j] = + (res1[i][j] % mod + ((transition[i][k] % mod * + transition[k][j] % mod)) % + mod) % + mod; + } + } + } + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + transition[i][j] = res1[i][j]; + } + } + n = n / 2; + } + } + return ((result[0] % mod * Identity[0][0] % mod) % mod + + (result[1] % mod * Identity[1][0] % mod) % mod) % + mod; } /** * Function to test above algorithm */ -void test() -{ - assert(fibo(6, 1000000007 ) == 8); +static void test() { + assert(fibo(6, 1000000007) == 8); std::cout << "test case:1 passed\n"; - assert(fibo(5, 1000000007 ) == 5); + assert(fibo(5, 1000000007) == 5); std::cout << "test case:2 passed\n"; - assert(fibo(10 , 1000000007) == 55); + assert(fibo(10, 1000000007) == 55); std::cout << "test case:3 passed\n"; - assert(fibo(500 , 100) == 25); + assert(fibo(500, 100) == 25); std::cout << "test case:3 passed\n"; - assert(fibo(500 , 10000) == 4125); + assert(fibo(500, 10000) == 4125); std::cout << "test case:3 passed\n"; std::cout << "--All tests passed--\n"; } @@ -103,11 +105,12 @@ void test() /** * Main function */ -int main() -{ - test(); - uint64_t mod=1000000007; - std::cout<<"Enter the value of N: "; - uint64_t n=0; std::cin>>n; - std::cout<> n; + std::cout << n << "th Fibonacci number in modulo " << mod << ": " + << fibo(n, mod) << std::endl; } diff --git a/math/fibonacci_sum.cpp b/math/fibonacci_sum.cpp index 5107578888e..9373e21cb87 100644 --- a/math/fibonacci_sum.cpp +++ b/math/fibonacci_sum.cpp @@ -13,6 +13,7 @@ */ #include /// for assert +#include #include /// for std::cin and std::cout #include /// for std::vector diff --git a/math/finding_number_of_digits_in_a_number.cpp b/math/finding_number_of_digits_in_a_number.cpp index 32ddd649ec3..b0edb746d65 100644 --- a/math/finding_number_of_digits_in_a_number.cpp +++ b/math/finding_number_of_digits_in_a_number.cpp @@ -18,6 +18,7 @@ #include /// for assert #include /// for log calculation +#include #include /// for IO operations /** diff --git a/math/integral_approximation.cpp b/math/integral_approximation.cpp index 7e72ef4042b..2d1d42f916d 100644 --- a/math/integral_approximation.cpp +++ b/math/integral_approximation.cpp @@ -1,18 +1,29 @@ /** * @file - * @brief Compute integral approximation of the function using [Riemann sum](https://en.wikipedia.org/wiki/Riemann_sum) - * @details In mathematics, a Riemann sum is a certain kind of approximation of an integral by a finite sum. It is named after nineteenth-century German mathematician Bernhard Riemann. - * One very common application is approximating the area of functions or lines on a graph and the length of curves and other approximations. - * The sum is calculated by partitioning the region into shapes (rectangles, trapezoids, parabolas, or cubics) that form a region similar to the region being measured, then calculating the area for each of these shapes, and finally adding all of these small areas together. - * This approach can be used to find a numerical approximation for a definite integral even if the fundamental theorem of calculus does not make it easy to find a closed-form solution. - * Because the region filled by the small shapes is usually not the same shape as the region being measured, the Riemann sum will differ from the area being measured. - * This error can be reduced by dividing up the region more finely, using smaller and smaller shapes. As the shapes get smaller and smaller, the sum approaches the Riemann integral. - * \author [Benjamin Walton](https://github.com/bwalton24) - * \author [Shiqi Sheng](https://github.com/shiqisheng00) + * @brief Compute integral approximation of the function using [Riemann + * sum](https://en.wikipedia.org/wiki/Riemann_sum) + * @details In mathematics, a Riemann sum is a certain kind of approximation of + * an integral by a finite sum. It is named after nineteenth-century German + * mathematician Bernhard Riemann. One very common application is approximating + * the area of functions or lines on a graph and the length of curves and other + * approximations. The sum is calculated by partitioning the region into shapes + * (rectangles, trapezoids, parabolas, or cubics) that form a region similar to + * the region being measured, then calculating the area for each of these + * shapes, and finally adding all of these small areas together. This approach + * can be used to find a numerical approximation for a definite integral even if + * the fundamental theorem of calculus does not make it easy to find a + * closed-form solution. Because the region filled by the small shapes is + * usually not the same shape as the region being measured, the Riemann sum will + * differ from the area being measured. This error can be reduced by dividing up + * the region more finely, using smaller and smaller shapes. As the shapes get + * smaller and smaller, the sum approaches the Riemann integral. \author + * [Benjamin Walton](https://github.com/bwalton24) \author [Shiqi + * Sheng](https://github.com/shiqisheng00) */ -#include /// for assert -#include /// for mathematical functions -#include /// for passing in functions +#include /// for assert +#include /// for mathematical functions +#include +#include /// for passing in functions #include /// for IO operations /** diff --git a/math/inv_sqrt.cpp b/math/inv_sqrt.cpp index ef490ddf918..96a13fc08a1 100644 --- a/math/inv_sqrt.cpp +++ b/math/inv_sqrt.cpp @@ -10,9 +10,9 @@ #include /// for assert #include /// for `std::sqrt` +#include #include /// for IO operations #include /// for numeric_limits - /** * @brief This is the function that calculates the fast inverse square root. * The following code is the fast inverse square root implementation from diff --git a/math/largest_power.cpp b/math/largest_power.cpp index 8fffbbd078b..bc1ba484754 100644 --- a/math/largest_power.cpp +++ b/math/largest_power.cpp @@ -1,41 +1,42 @@ /** * @file - * @brief Algorithm to find largest x such that p^x divides n! (factorial) using Legendre's Formula. - * @details Given an integer n and a prime number p, the task is to find the largest x such that - * p^x (p raised to power x) divides n! (factorial). This will be done using Legendre's formula: - * x = [n/(p^1)] + [n/(p^2)] + [n/(p^3)] + \ldots + 1 - * @see more on https://math.stackexchange.com/questions/141196/highest-power-of-a-prime-p-dividing-n + * @brief Algorithm to find largest x such that p^x divides n! (factorial) using + * Legendre's Formula. + * @details Given an integer n and a prime number p, the task is to find the + * largest x such that p^x (p raised to power x) divides n! (factorial). This + * will be done using Legendre's formula: x = [n/(p^1)] + [n/(p^2)] + [n/(p^3)] + * + \ldots + 1 + * @see more on + * https://math.stackexchange.com/questions/141196/highest-power-of-a-prime-p-dividing-n * @author [uday6670](https://github.com/uday6670) */ -#include /// for std::cin and std::cout -#include /// for assert - +#include /// for assert +#include +#include /// for std::cin and std::cout /** * @namespace math * @brief Mathematical algorithms */ namespace math { - /** - * @brief Function to calculate largest power - * @param n number - * @param p prime number - * @returns largest power - */ - uint64_t largestPower(uint32_t n, const uint16_t& p) - { - // Initialize result - int x = 0; - - // Calculate result - while (n) - { - n /= p; - x += n; - } - return x; +/** + * @brief Function to calculate largest power + * @param n number + * @param p prime number + * @returns largest power + */ +uint64_t largestPower(uint32_t n, const uint16_t& p) { + // Initialize result + int x = 0; + + // Calculate result + while (n) { + n /= p; + x += n; } + return x; +} } // namespace math @@ -43,36 +44,34 @@ namespace math { * @brief Function for testing largestPower function. * test cases and assert statement. * @returns `void` -*/ -static void test() -{ - uint8_t test_case_1 = math::largestPower(5,2); - assert(test_case_1==3); - std::cout<<"Test 1 Passed!"< /// for assert +#include #include /// for std::cin and std::cout #include /// for std::vector diff --git a/math/linear_recurrence_matrix.cpp b/math/linear_recurrence_matrix.cpp index 98c90e5f8fa..c54d1272bf7 100644 --- a/math/linear_recurrence_matrix.cpp +++ b/math/linear_recurrence_matrix.cpp @@ -18,6 +18,7 @@ * @author [Ashish Daulatabad](https://github.com/AshishYUO) */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector STL diff --git a/math/magic_number.cpp b/math/magic_number.cpp index 51232601b2b..c07869e3dfe 100644 --- a/math/magic_number.cpp +++ b/math/magic_number.cpp @@ -17,6 +17,7 @@ * @author [Neha Hasija](https://github.com/neha-hasija17) */ #include /// for assert +#include #include /// for io operations /** diff --git a/math/modular_division.cpp b/math/modular_division.cpp index 6fd984f2bf0..d37341b4a47 100644 --- a/math/modular_division.cpp +++ b/math/modular_division.cpp @@ -25,6 +25,7 @@ */ #include /// for assert +#include #include /// for IO operations /** diff --git a/math/modular_exponentiation.cpp b/math/modular_exponentiation.cpp index 01410860fda..d4a9dd84d07 100644 --- a/math/modular_exponentiation.cpp +++ b/math/modular_exponentiation.cpp @@ -17,8 +17,8 @@ * @author [Shri2206](https://github.com/Shri2206) */ #include /// for assert +#include #include /// for io operations - /** * @namespace math * @brief Mathematical algorithms diff --git a/math/modular_inverse_simple.cpp b/math/modular_inverse_simple.cpp index 813f0e0b4a5..f8a36d4eae9 100644 --- a/math/modular_inverse_simple.cpp +++ b/math/modular_inverse_simple.cpp @@ -8,6 +8,7 @@ */ #include /// for assert +#include #include /// for IO operations /** diff --git a/math/n_bonacci.cpp b/math/n_bonacci.cpp index c34dab7a19d..bb2e85d13e4 100644 --- a/math/n_bonacci.cpp +++ b/math/n_bonacci.cpp @@ -16,9 +16,9 @@ */ #include /// for assert +#include #include /// for std::cout #include /// for std::vector - /** * @namespace math * @brief Mathematical algorithms diff --git a/math/n_choose_r.cpp b/math/n_choose_r.cpp index 8bb3bbcdc2d..5e151f39a84 100644 --- a/math/n_choose_r.cpp +++ b/math/n_choose_r.cpp @@ -11,8 +11,8 @@ */ #include /// for assert +#include #include /// for io operations - /** * @namespace math * @brief Mathematical algorithms diff --git a/math/sieve_of_eratosthenes.cpp b/math/sieve_of_eratosthenes.cpp index e003706d12b..29115d306d5 100644 --- a/math/sieve_of_eratosthenes.cpp +++ b/math/sieve_of_eratosthenes.cpp @@ -12,6 +12,7 @@ * @see primes_up_to_billion.cpp prime_numbers.cpp */ +#include #include /// for assert #include /// for IO operations #include /// for std::vector @@ -109,7 +110,6 @@ static void tests() { false}; assert(is_prime_3 == expected_3); - std::cout << "All tests have passed successfully!\n"; } /** diff --git a/math/string_fibonacci.cpp b/math/string_fibonacci.cpp index eb9b6d7e1a7..1aef80f7a3c 100644 --- a/math/string_fibonacci.cpp +++ b/math/string_fibonacci.cpp @@ -8,6 +8,7 @@ * @see fibonacci_large.cpp, fibonacci_fast.cpp, fibonacci.cpp */ +#include #include #ifdef _MSC_VER #include // use this for MS Visual C diff --git a/math/sum_of_binomial_coefficient.cpp b/math/sum_of_binomial_coefficient.cpp index 1942df527dd..c5b1fbeb681 100644 --- a/math/sum_of_binomial_coefficient.cpp +++ b/math/sum_of_binomial_coefficient.cpp @@ -10,6 +10,7 @@ * @author [muskan0719](https://github.com/muskan0719) */ #include /// for assert +#include #include /// for std::cin and std::cout /** diff --git a/numerical_methods/brent_method_extrema.cpp b/numerical_methods/brent_method_extrema.cpp index 654a694514a..ea3c783bc53 100644 --- a/numerical_methods/brent_method_extrema.cpp +++ b/numerical_methods/brent_method_extrema.cpp @@ -16,6 +16,7 @@ #define _USE_MATH_DEFINES ///< required for MS Visual C++ #include #include +#include #include #include #include diff --git a/numerical_methods/durand_kerner_roots.cpp b/numerical_methods/durand_kerner_roots.cpp index 9bf0619b829..a5afc6a0046 100644 --- a/numerical_methods/durand_kerner_roots.cpp +++ b/numerical_methods/durand_kerner_roots.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/numerical_methods/fast_fourier_transform.cpp b/numerical_methods/fast_fourier_transform.cpp index 23a6c8a1f54..392789ea710 100644 --- a/numerical_methods/fast_fourier_transform.cpp +++ b/numerical_methods/fast_fourier_transform.cpp @@ -22,6 +22,7 @@ #include /// for assert #include /// for mathematical-related functions #include /// for storing points and coefficents +#include #include /// for IO operations #include /// for std::vector diff --git a/numerical_methods/golden_search_extrema.cpp b/numerical_methods/golden_search_extrema.cpp index 1ca47949fee..3f72db06f56 100644 --- a/numerical_methods/golden_search_extrema.cpp +++ b/numerical_methods/golden_search_extrema.cpp @@ -10,6 +10,7 @@ #define _USE_MATH_DEFINES //< required for MS Visual C++ #include #include +#include #include #include #include diff --git a/numerical_methods/inverse_fast_fourier_transform.cpp b/numerical_methods/inverse_fast_fourier_transform.cpp index 3837c21f966..928a20da802 100644 --- a/numerical_methods/inverse_fast_fourier_transform.cpp +++ b/numerical_methods/inverse_fast_fourier_transform.cpp @@ -14,6 +14,7 @@ #include /// for assert #include /// for mathematical-related functions #include /// for storing points and coefficents +#include #include /// for IO operations #include /// for std::vector diff --git a/numerical_methods/newton_raphson_method.cpp b/numerical_methods/newton_raphson_method.cpp index 17147e0bedd..1f5c9849f74 100644 --- a/numerical_methods/newton_raphson_method.cpp +++ b/numerical_methods/newton_raphson_method.cpp @@ -13,6 +13,7 @@ * \see bisection_method.cpp, false_position.cpp */ #include +#include #include #include #include diff --git a/numerical_methods/rungekutta.cpp b/numerical_methods/rungekutta.cpp index 01ca3a0745a..8522bd0ebc2 100644 --- a/numerical_methods/rungekutta.cpp +++ b/numerical_methods/rungekutta.cpp @@ -19,9 +19,9 @@ * There can be many such equations */ #include /// asserting the test functions +#include #include /// for io operations #include /// for using the vector container - /** * @brief The change() function is used * to return the updated iterative value corresponding diff --git a/others/easter.cpp b/others/easter.cpp index 36ac48028fc..6ae357deba7 100644 --- a/others/easter.cpp +++ b/others/easter.cpp @@ -18,6 +18,7 @@ */ #include /// for assert +#include #include /// for IO operations /* diff --git a/others/kadanes3.cpp b/others/kadanes3.cpp index 9cc6604e9c5..3d7ef442cfd 100644 --- a/others/kadanes3.cpp +++ b/others/kadanes3.cpp @@ -17,8 +17,8 @@ #include /// for std::array #include /// for assert #include /// for INT_MIN value +#include #include /// for IO operations - /** * @brief Utility function to check the current maximum number * \param arr input array diff --git a/others/lru_cache.cpp b/others/lru_cache.cpp index f9cd3caec7d..29f8bd0ed16 100644 --- a/others/lru_cache.cpp +++ b/others/lru_cache.cpp @@ -46,6 +46,7 @@ * */ #include /// for assert +#include #include /// for IO Operations #include /// for std::list #include /// for std::unordered_map diff --git a/search/binary_search.cpp b/search/binary_search.cpp index bed938b290c..ebe488e5658 100644 --- a/search/binary_search.cpp +++ b/search/binary_search.cpp @@ -37,6 +37,7 @@ #include /// for std::sort function #include /// for std::assert +#include #include /// for IO operations #include /// for std::vector /****************************************************************************** diff --git a/search/exponential_search.cpp b/search/exponential_search.cpp index f57cbf96b51..6443084dc25 100644 --- a/search/exponential_search.cpp +++ b/search/exponential_search.cpp @@ -14,7 +14,7 @@ */ #include #include -#include +#include #ifdef _MSC_VER #include // use for MS Visual C++ #else diff --git a/search/floyd_cycle_detection_algo.cpp b/search/floyd_cycle_detection_algo.cpp index c7dd95aea8c..58c994dccf3 100644 --- a/search/floyd_cycle_detection_algo.cpp +++ b/search/floyd_cycle_detection_algo.cpp @@ -12,9 +12,9 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector - /** * @namespace search * @brief Search algorithms diff --git a/search/interpolation_search.cpp b/search/interpolation_search.cpp index 5ed75774959..234d90ff698 100644 --- a/search/interpolation_search.cpp +++ b/search/interpolation_search.cpp @@ -31,6 +31,7 @@ #include /// for std::sort function #include /// for std::assert +#include #include /// for IO operations #include /// for std::vector diff --git a/search/saddleback_search.cpp b/search/saddleback_search.cpp index dab5adcf059..d75c65e3ea6 100644 --- a/search/saddleback_search.cpp +++ b/search/saddleback_search.cpp @@ -1,28 +1,34 @@ /** * @file - * @brief Implementation of [Saddleback Algorithm](https://www.geeksforgeeks.org/saddleback-search-algorithm-in-a-2d-array) for 2D arrays. + * @brief Implementation of [Saddleback + * Algorithm](https://www.geeksforgeeks.org/saddleback-search-algorithm-in-a-2d-array) + * for 2D arrays. * * @details * Saddleback Algorithm is an algorithm that searches 2D array in linear time, - * i.e, O(m + n), where m is number of rows and n is number of columns of 2D array. Also, each row and - * column of the matrix should be sorted beforehand for this algorithm to work. + * i.e, O(m + n), where m is number of rows and n is number of columns of 2D + * array. Also, each row and column of the matrix should be sorted beforehand + * for this algorithm to work. * * @author [Hashir Niazi](https://github.com/HashirGJ8842) */ -#include /// for assert -#include /// for io operations, and std::pair -#include /// for std::vector +#include /// for assert +#include +#include /// for io operations, and std::pair +#include /// for std::vector /** \namespace search * \brief Algorithms for searching */ namespace search { /** \namespace saddleback - * \brief Function for implementing [Saddleback Algorithm](https://www.geeksforgeeks.org/saddleback-search-algorithm-in-a-2d-array). + * \brief Function for implementing [Saddleback + * Algorithm](https://www.geeksforgeeks.org/saddleback-search-algorithm-in-a-2d-array). */ namespace saddleback { /** - * This function implements [Saddleback Algorithm](https://www.geeksforgeeks.org/saddleback-search-algorithm-in-a-2d-array), + * This function implements [Saddleback + * Algorithm](https://www.geeksforgeeks.org/saddleback-search-algorithm-in-a-2d-array), * on a sorted 2D array, and finds the location of the element needed to search * @param matrix 2D matrix which is sorted on the basis of rows and columns * @param element element to be searched @@ -30,16 +36,17 @@ namespace saddleback { * element is present. * @return An std::pair with (0, 0), if the element is not present. */ -std::pair saddleback(std::vector> matrix, - int32_t element) { +std::pair saddleback( + std::vector> matrix, int32_t element) { uint32_t left_index = 0; uint32_t right_index = matrix[0].size() - 1; // Start from top right corner - while (left_index < matrix.size()) { // Exit once the value of indexes get out of range. + while (left_index < + matrix.size()) { // Exit once the value of indexes get out of range. if (element == matrix[left_index] [right_index]) { // If value on this position of matrix is // equal to element, return (row, column). - return std::make_pair(left_index+1, right_index+1); + return std::make_pair(left_index + 1, right_index + 1); } else if (element > matrix[left_index] [right_index]) { // Else if value on this position of @@ -51,14 +58,15 @@ std::pair saddleback(std::vector> matri [right_index]) { // Else if value on this position of // matrix is greater than the // element, move down. - if(!right_index) + if (!right_index) break; - else --right_index; + else + --right_index; } } return std::make_pair( 0, 0); // If the program reaches here, that means one of the index - // went out of index, hence no element present. + // went out of index, hence no element present. } } // namespace saddleback } // namespace search @@ -69,15 +77,16 @@ std::pair saddleback(std::vector> matri */ static void test() { std::vector> matrix = {{1, 10, 100, 1000, 10000}, - {2, 20, 200, 2000, 20000}, - {3, 30, 300, 3000, 30000}, - {4, 40, 400, 4000, 40000}, - {5, 50, 500, 5000, 50000}}; + {2, 20, 200, 2000, 20000}, + {3, 30, 300, 3000, 30000}, + {4, 40, 400, 4000, 40000}, + {5, 50, 500, 5000, 50000}}; std::pair not_found = std::make_pair(0, 0); std::pair test_answer; // Test 1 - std::pair answer1 = search::saddleback::saddleback(matrix, 123); + std::pair answer1 = + search::saddleback::saddleback(matrix, 123); assert(not_found == answer1); // Test 2 answer1 = search::saddleback::saddleback(matrix, 0); @@ -101,6 +110,6 @@ static void test() { * @returns 0 on exit */ int main() { - test(); // execute the tests + test(); // execute the tests return 0; } diff --git a/search/sublist_search.cpp b/search/sublist_search.cpp index 0954173d20c..bb63cac0fa5 100644 --- a/search/sublist_search.cpp +++ b/search/sublist_search.cpp @@ -26,6 +26,7 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector diff --git a/sorting/cycle_sort.cpp b/sorting/cycle_sort.cpp index 8acf462af78..88364bf12a0 100644 --- a/sorting/cycle_sort.cpp +++ b/sorting/cycle_sort.cpp @@ -13,6 +13,7 @@ #include /// for std::is_sorted, std::swap #include /// for assert +#include #include /// for io operations #include /// for std::vector diff --git a/sorting/dnf_sort.cpp b/sorting/dnf_sort.cpp index 8b7c2279e0e..4fe0129cc81 100644 --- a/sorting/dnf_sort.cpp +++ b/sorting/dnf_sort.cpp @@ -12,6 +12,7 @@ #include /// for std::is_sorted #include /// for assert +#include #include /// for std::swap and io operations #include /// for std::vector diff --git a/sorting/quick_sort.cpp b/sorting/quick_sort.cpp index 514361444e4..8a582790817 100644 --- a/sorting/quick_sort.cpp +++ b/sorting/quick_sort.cpp @@ -26,6 +26,7 @@ #include /// for std::is_sorted #include /// for std::assert +#include #include /// for std::time #include /// for IO operations #include /// for std::vector diff --git a/sorting/radix_sort2.cpp b/sorting/radix_sort2.cpp index 3d6916e1617..d20e81bccae 100644 --- a/sorting/radix_sort2.cpp +++ b/sorting/radix_sort2.cpp @@ -23,8 +23,10 @@ */ /// header files + #include /// for collection of functions #include /// for a macro called assert which can be used to verify assumptions +#include #include /// for io operations #include /// for std::vector diff --git a/sorting/recursive_bubble_sort.cpp b/sorting/recursive_bubble_sort.cpp index d76a72d8633..f73cc0aeac5 100644 --- a/sorting/recursive_bubble_sort.cpp +++ b/sorting/recursive_bubble_sort.cpp @@ -1,20 +1,23 @@ /** * @file * @author [Aditya Prakash](https://adityaprakash.tech) - * @brief This is an implementation of a recursive version of the [Bubble sort algorithm](https://www.geeksforgeeks.org/recursive-bubble-sort/) + * @brief This is an implementation of a recursive version of the [Bubble sort + algorithm](https://www.geeksforgeeks.org/recursive-bubble-sort/) * * @details * The working principle of the Bubble sort algorithm. - * Bubble sort is a simple sorting algorithm used to rearrange a set of ascending or descending order elements. - * Bubble sort gets its name from the fact that data "bubbles" to the top of the dataset. - + * Bubble sort is a simple sorting algorithm used to rearrange a set of + ascending or descending order elements. + * Bubble sort gets its name from the fact that data "bubbles" to the top of the + dataset. + * ### Algorithm * What is Swap? * Swapping two numbers means that we interchange their values. - * Often, an additional variable is required for this operation. + * Often, an additional variable is required for this operation. * This is further illustrated in the following: * void swap(int x, int y){ @@ -26,15 +29,19 @@ * The above process is a typical displacement process. * When we assign a value to x, the old value of x is lost. * That's why we create a temporary variable z to store the initial value of x. - * z is further used to assign the initial value of x to y, to complete swapping. + * z is further used to assign the initial value of x to y, to complete + swapping. * Recursion - * While the recursive method does not necessarily have advantages over iterative + * While the recursive method does not necessarily have advantages over + iterative * versions, but it is useful to enhance the understanding of the algorithm and * recursion itself. In Recursive Bubble sort algorithm, we firstly call the - * function on the entire array, and for every subsequent function call, we exclude - * the last element. This fixes the last element for that sub-array.Formally, for + * function on the entire array, and for every subsequent function call, we + exclude + * the last element. This fixes the last element for that sub-array.Formally, + for * `ith` iteration, we consider elements up to n-i, where n is the number of * elements in the array. Exit condition: n==1; i.e. the sub-array contains only * one element. @@ -43,16 +50,19 @@ * Time complexity: O(n) best case; O(n²) average case; O(n²) worst case * Space complexity: O(n) - * We need to traverse the array `n * (n-1)` times. However, if the entire array is - * already sorted, then we need to traverse it only once. Hence, O(n) is the best case + * We need to traverse the array `n * (n-1)` times. However, if the entire array + is + * already sorted, then we need to traverse it only once. Hence, O(n) is the + best case * complexity */ -#include /// for assert -#include /// for IO operations -#include /// for std::vector -#include /// for std::array -#include /// for std::is_sorted +#include /// for std::is_sorted +#include /// for std::array +#include /// for assert +#include +#include /// for IO operations +#include /// for std::vector /** * @namespace sorting @@ -61,11 +71,11 @@ namespace sorting { /** - * @brief This is an implementation of the recursive_bubble_sort. A vector is passed - * to the function which is then dereferenced, so that the changes are + * @brief This is an implementation of the recursive_bubble_sort. A vector is + * passed to the function which is then dereferenced, so that the changes are * reflected in the original vector. It also accepts a second parameter of * type `int` and name `n`, which is the size of the array. - * + * * @tparam T type of data variables in the array * @param nums our array of elements. * @param n size of the array @@ -136,14 +146,13 @@ static void test() { std::cout << double_arr[i] << ", "; } std::cout << std::endl; - } /** * @brief Main function * @returns 0 on exit */ -int main() { +int main() { test(); // run self-test implementations return 0; } diff --git a/sorting/selection_sort_iterative.cpp b/sorting/selection_sort_iterative.cpp index a9adac0891b..db293b88d03 100644 --- a/sorting/selection_sort_iterative.cpp +++ b/sorting/selection_sort_iterative.cpp @@ -29,6 +29,7 @@ *******************************************************************************/ #include /// for std::is_sorted #include /// for std::assert +#include #include /// for IO operations #include /// for std::vector diff --git a/sorting/selection_sort_recursive.cpp b/sorting/selection_sort_recursive.cpp index 57eadfbd0fe..2ef6219b8dc 100644 --- a/sorting/selection_sort_recursive.cpp +++ b/sorting/selection_sort_recursive.cpp @@ -28,9 +28,10 @@ */ #include /// for std::is_sorted -#include /// for assert -#include /// for std::swap and io operations -#include /// for std::vector +#include /// for assert +#include +#include /// for std::swap and io operations +#include /// for std::vector /** * @namespace sorting diff --git a/sorting/wiggle_sort.cpp b/sorting/wiggle_sort.cpp index bf8574c98c5..45ba788a86e 100644 --- a/sorting/wiggle_sort.cpp +++ b/sorting/wiggle_sort.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include /// for io operations #include @@ -50,7 +51,7 @@ namespace wiggle_sort { */ template // this allows to have vectors of ints, double, float, // etc - std::vector wiggleSort(const std::vector &arr) { +std::vector wiggleSort(const std::vector &arr) { uint32_t size = arr.size(); std::vector out( diff --git a/strings/manacher_algorithm.cpp b/strings/manacher_algorithm.cpp index 94314c3b466..e544d818d8c 100644 --- a/strings/manacher_algorithm.cpp +++ b/strings/manacher_algorithm.cpp @@ -11,6 +11,7 @@ */ #include /// for assert +#include #include /// for IO operations #include /// for std::vector STL #ifdef _MSC_VER diff --git a/strings/z_function.cpp b/strings/z_function.cpp index 6ce98c491d1..d32f19b9f4a 100644 --- a/strings/z_function.cpp +++ b/strings/z_function.cpp @@ -11,6 +11,7 @@ * @author [Ritika Gupta](https://github.com/RitikaGupta8734) */ +#include #include /// for IO operations #ifdef _MSC_VER #include /// for string (use this for MS Visual C++) From 0d766b0f8abc24bf40e881ddb55f276652ba9827 Mon Sep 17 00:00:00 2001 From: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:00:20 +0530 Subject: [PATCH 71/74] feat: update to CXX standard 17 and add CMakeLists file to directories without them (#2746) * chore: add cache and build comment to git ignore * fix: add cmakelists to dynamic programming * fix: add cmakelists to greedy_algorithms * fix: add cmakelists to operations_on_datastructures * fix: add cmakelists to range_queries * fix: add `dynamic_programmin`, `greedy_algorithms`, `range_queries` and `operations_on_datastructures` subdirectories to cmakelists.txt * fix: init of transform_reduce in dynamic_programming * fix: add an include for functional in catalan_numbers * chore: bump CXX standard to 20 * revert: bump CXX standard to 20 * chore: bump c++ version to 17 and add justification Arm supports c++ 17 Esp32 supports c++ 23 decision was made to be 17 because it seemed to offer the best combatability * fix: compilation error in catalan numbers * fix: add header to longest increasing subsequence nlogn * fix: add cmath & algorithm header to mo.cpp * fix: remove register key word from fast integer * fix: replace using namespace std with std::cin and std::cout * docs: typo in c++17 * fix: memory leak in bellman_ford * fix: typo in bellman_ford * fix: typo in word_break * fix: dynamic array in coin_change * fix dynamic array in egg_dropping puzzle * chore: remove unnecessary comment * fix: add vla to be an error * chore: add extra warnings * fix: use add_compile options instead of set() * fix: compile options are not strings * fix: vla in floyd_warshall * fix: vla in egg_dropping_puzzel * fix: vla in coin_change * fix: vla in edit_distance * fix: vla in floyd_warshall * feat: remove kadane and replace it with kadane2 * fix: vla in longest_common_subsequence * fix: int overflow in floyd_warshall * fix: vla in lisnlogn * fix: use const vector& instead of array * fix: use dynamic array instead of vla in knapsack * fix: use of and in msvc is unsupported by default adding permissive flag fixes it * test: make executables the tests themselves * Revert "test: make executables the tests themselves" This reverts commit 7a16c31c4e7fa2d472f0713d4fc97d48c9be6838. * fix: make dist constant in print * fix: namespace issue in unbounded_0_1 * fix: include cstdint to fix compilation --- .gitignore | 4 + CMakeLists.txt | 17 +- README.md | 2 +- dynamic_programming/CMakeLists.txt | 18 ++ dynamic_programming/abbreviation.cpp | 1 + ...ber.cpp => armstrong_number_templated.cpp} | 0 dynamic_programming/bellman_ford.cpp | 12 +- dynamic_programming/catalan_numbers.cpp | 13 +- dynamic_programming/coin_change.cpp | 3 +- dynamic_programming/cut_rod.cpp | 13 +- dynamic_programming/edit_distance.cpp | 3 +- dynamic_programming/egg_dropping_puzzle.cpp | 5 +- dynamic_programming/floyd_warshall.cpp | 15 +- dynamic_programming/house_robber.cpp | 2 +- dynamic_programming/kadane.cpp | 85 +++++++--- dynamic_programming/kadane2.cpp | 74 --------- .../longest_common_subsequence.cpp | 3 +- .../longest_increasing_subsequence.cpp | 1 + ... longest_increasing_subsequence_nlogn.cpp} | 6 +- dynamic_programming/minimum_edit_distance.cpp | 139 +++++++++------- dynamic_programming/partition_problem.cpp | 2 +- ...{subset_sum.cpp => subset_sum_dynamic.cpp} | 0 .../unbounded_0_1_knapsack.cpp | 154 ++++++++++-------- dynamic_programming/word_break.cpp | 2 +- greedy_algorithms/CMakeLists.txt | 18 ++ .../{dijkstra.cpp => dijkstra_greedy.cpp} | 0 greedy_algorithms/knapsack.cpp | 4 +- operations_on_datastructures/CMakeLists.txt | 15 ++ .../circular_queue_using_array.cpp | 3 +- .../trie_multiple_search.cpp | 7 +- others/fast_integer_input.cpp | 2 +- range_queries/CMakeLists.txt | 18 ++ range_queries/mo.cpp | 3 + range_queries/segtree.cpp | 1 + ...ble.cpp => sparse_table_range_queries.cpp} | 0 35 files changed, 377 insertions(+), 268 deletions(-) create mode 100644 dynamic_programming/CMakeLists.txt rename dynamic_programming/{armstrong_number.cpp => armstrong_number_templated.cpp} (100%) delete mode 100644 dynamic_programming/kadane2.cpp rename dynamic_programming/{longest_increasing_subsequence_(nlogn).cpp => longest_increasing_subsequence_nlogn.cpp} (92%) rename dynamic_programming/{subset_sum.cpp => subset_sum_dynamic.cpp} (100%) create mode 100644 greedy_algorithms/CMakeLists.txt rename greedy_algorithms/{dijkstra.cpp => dijkstra_greedy.cpp} (100%) create mode 100644 operations_on_datastructures/CMakeLists.txt create mode 100644 range_queries/CMakeLists.txt rename range_queries/{sparse_table.cpp => sparse_table_range_queries.cpp} (100%) diff --git a/.gitignore b/.gitignore index a94731cc2ed..c4951fe97b1 100644 --- a/.gitignore +++ b/.gitignore @@ -34,5 +34,9 @@ a.out *.out *.app +# Cache +.cache/ + +# Build build/ git_diff.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index cca1b54649b..95038fbab78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,16 +5,17 @@ project(Algorithms_in_C++ DESCRIPTION "Set of algorithms implemented in C++." ) -# set(CMAKE_CXX_CPPLINT "~/anaconda3/bin/cpplint --filter=-legal/copyright --std=c++11") -# find_program(CLANG_FORMAT "clang-format") - -set(CMAKE_CXX_STANDARD 11) +# C++ standard +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Additional warnings and errors if(MSVC) - # set(CMAKE_CXX_STANDARD 14) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) -endif(MSVC) + add_compile_options(/W4 /permissive-) +else() + add_compile_options(-Wall -Wextra -Wno-register -Werror=vla) +endif() option(USE_OPENMP "flag to use OpenMP for multithreading" ON) if(USE_OPENMP) @@ -38,6 +39,10 @@ add_subdirectory(graphics) add_subdirectory(probability) add_subdirectory(backtracking) add_subdirectory(bit_manipulation) +add_subdirectory(dynamic_programming) +add_subdirectory(greedy_algorithms) +add_subdirectory(range_queries) +add_subdirectory(operations_on_datastructures) add_subdirectory(data_structures) add_subdirectory(machine_learning) add_subdirectory(numerical_methods) diff --git a/README.md b/README.md index 5ad49b18473..9f32c07b70e 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This repository is a collection of open-source implementation of a variety of al * Well documented source code with detailed explanations provide a valuable resource for educators and students alike. * Each source code is atomic using [STL classes](https://en.wikipedia.org/wiki/Standard_Template_Library) and _no external libraries_ are required for their compilation and execution. Thus, the fundamentals of the algorithms can be studied in much depth. * Source codes are [compiled and tested](https://github.com/TheAlgorithms/C-Plus-Plus/actions?query=workflow%3A%22Awesome+CI+Workflow%22) for every commit on the latest versions of three major operating systems viz., Windows, MacOS, and Ubuntu (Linux) using MSVC 19 2022, AppleClang 14.0.0, and GNU 11.3.0 respectively. -* Strict adherence to [C++11](https://en.wikipedia.org/wiki/C%2B%2B11) standard ensures portability of code to embedded systems as well like ESP32, ARM Cortex, etc. with little to no changes. +* Strict adherence to [C++17](https://en.wikipedia.org/wiki/C%2B%2B17) standard ensures portability of code to embedded systems as well like [ESP32](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/cplusplus.html#c-language-standard), [ARM Cortex](https://developer.arm.com/documentation/101458/2404/Standards-support/Supported-C-C---standards-in-Arm-C-C---Compiler), etc. with little to no changes. * Self-checks within programs ensure correct implementations with confidence. * Modular implementations and OpenSource licensing enable the functions to be utilized conveniently in other applications. diff --git a/dynamic_programming/CMakeLists.txt b/dynamic_programming/CMakeLists.txt new file mode 100644 index 00000000000..bcf0a990013 --- /dev/null +++ b/dynamic_programming/CMakeLists.txt @@ -0,0 +1,18 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".cpp" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX) + if(OpenMP_CXX_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_CXX) + endif() + install(TARGETS ${testname} DESTINATION "bin/dynamic_programming") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/dynamic_programming/abbreviation.cpp b/dynamic_programming/abbreviation.cpp index 9ee4dc27436..1da8d30f83d 100644 --- a/dynamic_programming/abbreviation.cpp +++ b/dynamic_programming/abbreviation.cpp @@ -24,6 +24,7 @@ */ #include /// for `assert` +#include /// for `std::uint32_t` #include /// for IO operations #include /// for `std::string` library #include /// for `std::vector` STL library diff --git a/dynamic_programming/armstrong_number.cpp b/dynamic_programming/armstrong_number_templated.cpp similarity index 100% rename from dynamic_programming/armstrong_number.cpp rename to dynamic_programming/armstrong_number_templated.cpp diff --git a/dynamic_programming/bellman_ford.cpp b/dynamic_programming/bellman_ford.cpp index c96f3fd8eea..a55596d41d1 100644 --- a/dynamic_programming/bellman_ford.cpp +++ b/dynamic_programming/bellman_ford.cpp @@ -1,5 +1,6 @@ -#include +#include #include +#include using namespace std; @@ -13,13 +14,13 @@ class Edge { class Graph { public: int vertexNum, edgeNum; - Edge *edges; + std::vector edges; // Constructs a graph with V vertices and E edges Graph(int V, int E) { this->vertexNum = V; this->edgeNum = E; - this->edges = (Edge *)malloc(E * sizeof(Edge)); + this->edges.reserve(E); } // Adds the given edge to the graph @@ -36,7 +37,7 @@ class Graph { }; // Utility function to print distances -void print(int dist[], int V) { +void print(const std::vector& dist, int V) { cout << "\nVertex Distance" << endl; for (int i = 0; i < V; i++) { if (dist[i] != INT_MAX) @@ -52,7 +53,8 @@ void print(int dist[], int V) { void BellmanFord(Graph graph, int src) { int V = graph.vertexNum; int E = graph.edgeNum; - int dist[V]; + std::vector dist; + dist.reserve(E); // Initialize distances array as INF for all except source // Intialize source as zero diff --git a/dynamic_programming/catalan_numbers.cpp b/dynamic_programming/catalan_numbers.cpp index c99ea00265c..9c737b466cb 100644 --- a/dynamic_programming/catalan_numbers.cpp +++ b/dynamic_programming/catalan_numbers.cpp @@ -9,11 +9,12 @@ https://oeis.org/A000108/ */ -#include /// for assert -#include /// for std::uint64_t -#include /// for std::size_t -#include /// for std::transform_reduce -#include /// for std::vector +#include /// for assert +#include /// for std::uint64_t +#include /// for std::size_t +#include /// for std::plus & std::multiplies +#include /// for std::transform_reduce +#include /// for std::vector /** * @brief computes and caches Catalan numbers @@ -24,7 +25,7 @@ class catalan_numbers { value_type compute_next() { return std::transform_reduce(known.begin(), known.end(), known.rbegin(), - static_cast(), std::plus<>(), + static_cast(0), std::plus<>(), std::multiplies<>()); } diff --git a/dynamic_programming/coin_change.cpp b/dynamic_programming/coin_change.cpp index 8c8fc3dfb68..f4c0541fde8 100644 --- a/dynamic_programming/coin_change.cpp +++ b/dynamic_programming/coin_change.cpp @@ -1,11 +1,12 @@ #include #include +#include using namespace std; // Function to find the Minimum number of coins required to get Sum S int findMinCoins(int arr[], int n, int N) { // dp[i] = no of coins required to get a total of i - int dp[N + 1]; + std::vector dp(N + 1); // 0 coins are needed for 0 sum diff --git a/dynamic_programming/cut_rod.cpp b/dynamic_programming/cut_rod.cpp index c365be4fcaf..cb7a247c2e2 100644 --- a/dynamic_programming/cut_rod.cpp +++ b/dynamic_programming/cut_rod.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include /** * @namespace dynamic_programming @@ -70,8 +71,8 @@ int maxProfitByCuttingRod(const std::array &price, const uint64_t &n) { */ static void test() { // Test 1 - const int16_t n1 = 8; // size of rod - std::array price1 = {1,2,4,6,8,45,21,9}; // price array + const int16_t n1 = 8; // size of rod + std::array price1 = {1, 2, 4, 6, 8, 45, 21, 9}; // price array const int64_t max_profit1 = dynamic_programming::cut_rod::maxProfitByCuttingRod(price1, n1); const int64_t expected_max_profit1 = 47; @@ -86,15 +87,15 @@ static void test() { 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50}; - const int64_t max_profit2= + const int64_t max_profit2 = dynamic_programming::cut_rod::maxProfitByCuttingRod(price2, n2); const int32_t expected_max_profit2 = 90; assert(max_profit2 == expected_max_profit2); std::cout << "Maximum profit with " << n2 << " inch road is " << max_profit2 << std::endl; - // Test 3 - const int16_t n3 = 5; // size of rod - std::array price3 = {2,9,17,23,45}; // price array + // Test 3 + const int16_t n3 = 5; // size of rod + std::array price3 = {2, 9, 17, 23, 45}; // price array const int64_t max_profit3 = dynamic_programming::cut_rod::maxProfitByCuttingRod(price3, n3); const int64_t expected_max_profit3 = 45; diff --git a/dynamic_programming/edit_distance.cpp b/dynamic_programming/edit_distance.cpp index 889b080cb93..02dae8ca90e 100644 --- a/dynamic_programming/edit_distance.cpp +++ b/dynamic_programming/edit_distance.cpp @@ -13,6 +13,7 @@ #include #include +#include using namespace std; int min(int x, int y, int z) { return min(min(x, y), z); } @@ -46,7 +47,7 @@ int editDist(string str1, string str2, int m, int n) { */ int editDistDP(string str1, string str2, int m, int n) { // Create Table for SubProblems - int dp[m + 1][n + 1]; + std::vector > dp(m + 1, std::vector(n + 1)); // Fill d[][] in bottom up manner for (int i = 0; i <= m; i++) { diff --git a/dynamic_programming/egg_dropping_puzzle.cpp b/dynamic_programming/egg_dropping_puzzle.cpp index 7a769ea472e..e83f14af84b 100644 --- a/dynamic_programming/egg_dropping_puzzle.cpp +++ b/dynamic_programming/egg_dropping_puzzle.cpp @@ -4,10 +4,13 @@ #include #include +#include + using namespace std; int eggDrop(int n, int k) { - int eggFloor[n + 1][k + 1]; + std::vector > eggFloor(n + 1, std::vector(k + 1)); + int result; for (int i = 1; i <= n; i++) { diff --git a/dynamic_programming/floyd_warshall.cpp b/dynamic_programming/floyd_warshall.cpp index d193ebbd589..c314bbf3976 100644 --- a/dynamic_programming/floyd_warshall.cpp +++ b/dynamic_programming/floyd_warshall.cpp @@ -1,6 +1,7 @@ #include +#include #include -#include +#include using std::cin; using std::cout; @@ -24,7 +25,9 @@ class Graph { } ~Graph() { - for (int i = 0; i < vertexNum; i++) delete[] edges[i]; + for (int i = 0; i < vertexNum; i++) { + delete[] edges[i]; + } delete[] edges; } @@ -35,7 +38,7 @@ class Graph { }; // Utility function to print distances -void print(int dist[], int V) { +void print(const std::vector& dist, int V) { cout << "\nThe Distance matrix for Floyd - Warshall" << endl; for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { @@ -52,8 +55,8 @@ void print(int dist[], int V) { // The main function that finds the shortest path from a vertex // to all other vertices using Floyd-Warshall Algorithm. void FloydWarshall(Graph graph) { - int V = graph.vertexNum; - int dist[V][V]; + std::size_t V = graph.vertexNum; + std::vector > dist(V, std::vector(V)); // Initialise distance array for (int i = 0; i < V; i++) @@ -76,7 +79,7 @@ void FloydWarshall(Graph graph) { dist[i][j] = dist[i][k] + dist[k][j]; // Convert 2d array to 1d array for print - int dist1d[V * V]; + std::vector dist1d(V * V); for (int i = 0; i < V; i++) for (int j = 0; j < V; j++) dist1d[i * V + j] = dist[i][j]; diff --git a/dynamic_programming/house_robber.cpp b/dynamic_programming/house_robber.cpp index 0d238b9c13d..806a0a7d63d 100644 --- a/dynamic_programming/house_robber.cpp +++ b/dynamic_programming/house_robber.cpp @@ -11,9 +11,9 @@ #include /// for assert #include /// for std::max +#include /// for std::uint32_t #include /// for io operations #include /// for std::vector - /** * @namespace dynamic_programming * @brief Dynamic Programming algorithms diff --git a/dynamic_programming/kadane.cpp b/dynamic_programming/kadane.cpp index b5272756bcf..d048d0d5b27 100644 --- a/dynamic_programming/kadane.cpp +++ b/dynamic_programming/kadane.cpp @@ -1,29 +1,74 @@ +/** + * @file + * @brief Implementation of [Kadane + * Algorithm](https://en.wikipedia.org/wiki/Kadane%27s_algorithm) + * + * @details + * Kadane algorithm is used to find the maximum sum subarray in an array and + * maximum sum subarray problem is the task of finding a contiguous subarray + * with the largest sum + * + * ### Algorithm + * The simple idea of the algorithm is to search for all positive + * contiguous segments of the array and keep track of maximum sum contiguous + * segment among all positive segments(curr_sum is used for this) + * Each time we get a positive sum we compare it with max_sum and update max_sum + * if it is greater than curr_sum + * + * @author [Ayush Singh](https://github.com/ayush523) + */ +#include #include #include - -int maxSubArraySum(int a[], int size) { - int max_so_far = INT_MIN, max_ending_here = 0; - - for (int i = 0; i < size; i++) { - max_ending_here = max_ending_here + a[i]; - if (max_so_far < max_ending_here) - max_so_far = max_ending_here; - - if (max_ending_here < 0) - max_ending_here = 0; +/** + * @namespace dynamic_programming + * @brief Dynamic Programming algorithms + */ +namespace dynamic_programming { +/** + * @namespace kadane + * @brief Functions for + * [Kadane](https://en.wikipedia.org/wiki/Kadane%27s_algorithm) algorithm. + */ +namespace kadane { +/** + * @brief maxSubArray function is used to calculate the maximum sum subarray + * and returns the value of maximum sum which is stored in the variable max_sum + * @tparam N number of array size + * @param n array where numbers are saved + * @returns the value of maximum subarray sum + */ +template +int maxSubArray(const std::array &n) { + int curr_sum = + 0; // declaring a variable named as curr_sum and initialized it to 0 + int max_sum = INT_MIN; // Initialized max_sum to INT_MIN + for (int i : n) { // for loop to iterate over the elements of the array + curr_sum += n[i]; + max_sum = std::max(max_sum, curr_sum); // getting the maximum value + curr_sum = std::max(curr_sum, 0); // updating the value of curr_sum } - return max_so_far; + return max_sum; // returning the value of max_sum } +} // namespace kadane +} // namespace dynamic_programming +/** + * @brief Main function + * @returns 0 on exit + */ int main() { - int n, i; - std::cout << "Enter the number of elements \n"; - std::cin >> n; - int a[n]; // NOLINT - for (i = 0; i < n; i++) { - std::cin >> a[i]; + const int N = 5; + std::array n{}; // declaring array + // taking values of elements from user + for (int i = 0; i < n.size(); i++) { + std::cout << "Enter value of n[" << i << "]" + << "\n"; + std::cin >> n[i]; } - int max_sum = maxSubArraySum(a, n); - std::cout << "Maximum contiguous sum is " << max_sum; + int max_sum = dynamic_programming::kadane::maxSubArray( + n); // calling maxSubArray function + std::cout << "Maximum subarray sum is " << max_sum; // Printing the answer + return 0; } diff --git a/dynamic_programming/kadane2.cpp b/dynamic_programming/kadane2.cpp deleted file mode 100644 index d048d0d5b27..00000000000 --- a/dynamic_programming/kadane2.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file - * @brief Implementation of [Kadane - * Algorithm](https://en.wikipedia.org/wiki/Kadane%27s_algorithm) - * - * @details - * Kadane algorithm is used to find the maximum sum subarray in an array and - * maximum sum subarray problem is the task of finding a contiguous subarray - * with the largest sum - * - * ### Algorithm - * The simple idea of the algorithm is to search for all positive - * contiguous segments of the array and keep track of maximum sum contiguous - * segment among all positive segments(curr_sum is used for this) - * Each time we get a positive sum we compare it with max_sum and update max_sum - * if it is greater than curr_sum - * - * @author [Ayush Singh](https://github.com/ayush523) - */ -#include -#include -#include -/** - * @namespace dynamic_programming - * @brief Dynamic Programming algorithms - */ -namespace dynamic_programming { -/** - * @namespace kadane - * @brief Functions for - * [Kadane](https://en.wikipedia.org/wiki/Kadane%27s_algorithm) algorithm. - */ -namespace kadane { -/** - * @brief maxSubArray function is used to calculate the maximum sum subarray - * and returns the value of maximum sum which is stored in the variable max_sum - * @tparam N number of array size - * @param n array where numbers are saved - * @returns the value of maximum subarray sum - */ -template -int maxSubArray(const std::array &n) { - int curr_sum = - 0; // declaring a variable named as curr_sum and initialized it to 0 - int max_sum = INT_MIN; // Initialized max_sum to INT_MIN - for (int i : n) { // for loop to iterate over the elements of the array - curr_sum += n[i]; - max_sum = std::max(max_sum, curr_sum); // getting the maximum value - curr_sum = std::max(curr_sum, 0); // updating the value of curr_sum - } - return max_sum; // returning the value of max_sum -} -} // namespace kadane -} // namespace dynamic_programming - -/** - * @brief Main function - * @returns 0 on exit - */ -int main() { - const int N = 5; - std::array n{}; // declaring array - // taking values of elements from user - for (int i = 0; i < n.size(); i++) { - std::cout << "Enter value of n[" << i << "]" - << "\n"; - std::cin >> n[i]; - } - int max_sum = dynamic_programming::kadane::maxSubArray( - n); // calling maxSubArray function - std::cout << "Maximum subarray sum is " << max_sum; // Printing the answer - - return 0; -} diff --git a/dynamic_programming/longest_common_subsequence.cpp b/dynamic_programming/longest_common_subsequence.cpp index 662c26ad2c3..89a57dc0e03 100644 --- a/dynamic_programming/longest_common_subsequence.cpp +++ b/dynamic_programming/longest_common_subsequence.cpp @@ -1,5 +1,6 @@ // Longest common subsequence - Dynamic Programming #include +#include using namespace std; void Print(int trace[20][20], int m, int n, string a) { @@ -18,7 +19,7 @@ void Print(int trace[20][20], int m, int n, string a) { int lcs(string a, string b) { int m = a.length(), n = b.length(); - int res[m + 1][n + 1]; + std::vector > res(m + 1, std::vector(n + 1)); int trace[20][20]; // fills up the arrays with zeros. diff --git a/dynamic_programming/longest_increasing_subsequence.cpp b/dynamic_programming/longest_increasing_subsequence.cpp index a93c139c428..8c8f97c438e 100644 --- a/dynamic_programming/longest_increasing_subsequence.cpp +++ b/dynamic_programming/longest_increasing_subsequence.cpp @@ -21,6 +21,7 @@ #include /// for assert #include /// for std::max +#include /// for std::uint64_t #include /// for IO operations #include /// for std::vector diff --git a/dynamic_programming/longest_increasing_subsequence_(nlogn).cpp b/dynamic_programming/longest_increasing_subsequence_nlogn.cpp similarity index 92% rename from dynamic_programming/longest_increasing_subsequence_(nlogn).cpp rename to dynamic_programming/longest_increasing_subsequence_nlogn.cpp index 5bc72345c23..b0a49d2dab0 100644 --- a/dynamic_programming/longest_increasing_subsequence_(nlogn).cpp +++ b/dynamic_programming/longest_increasing_subsequence_nlogn.cpp @@ -3,9 +3,11 @@ // tested on : https://cses.fi/problemset/task/1145/ #include +#include +#include using namespace std; -int LIS(int arr[], int n) { +int LIS(const std::vector& arr, int n) { set active; // The current built LIS. active.insert(arr[0]); // Loop through every element. @@ -31,7 +33,7 @@ int main(int argc, char const* argv[]) { int n; cout << "Enter size of array: "; cin >> n; - int a[n]; + std::vector a(n); cout << "Enter array elements: "; for (int i = 0; i < n; ++i) { cin >> a[i]; diff --git a/dynamic_programming/minimum_edit_distance.cpp b/dynamic_programming/minimum_edit_distance.cpp index db9dd665dfb..8664ccb4513 100644 --- a/dynamic_programming/minimum_edit_distance.cpp +++ b/dynamic_programming/minimum_edit_distance.cpp @@ -1,6 +1,8 @@ /** * @file - * @brief Implementation of [Minimum Edit Distance](https://en.wikipedia.org/wiki/Edit_distance) using Dynamic Programing + * @brief Implementation of [Minimum Edit + * Distance](https://en.wikipedia.org/wiki/Edit_distance) using Dynamic + * Programing * * @details * @@ -32,9 +34,11 @@ * @author [Nirjas Jakilim](github.com/nirzak) */ -#include /// for assert -#include /// for IO operations +#include /// for assert +#include /// for std::uint64_t +#include /// for IO operations #include /// for std::vector + /** * @namespace dynamic_programming * @brief Dynamic Programming algorithms @@ -44,7 +48,8 @@ namespace dynamic_programming { /** * @namespace Minimum Edit Distance - * @brief Implementation of [Minimum Edit Distance](https://en.wikipedia.org/wiki/Edit_distance) algorithm + * @brief Implementation of [Minimum Edit + * Distance](https://en.wikipedia.org/wiki/Edit_distance) algorithm */ namespace minimum_edit_distance { @@ -61,15 +66,14 @@ namespace minimum_edit_distance { * @returns z if `z` is the minimum value */ uint64_t min(uint64_t x, uint64_t y, uint64_t z) { - if (x <= y && x <= z) { - return x; /// returns x, if x is the minimum value - } - if (y <= x && y <= z) { - return y; /// returns y, if y is the minimum value - } - else { - return z; /// returns z if z is the minimum value - } + if (x <= y && x <= z) { + return x; /// returns x, if x is the minimum value + } + if (y <= x && y <= z) { + return y; /// returns y, if y is the minimum value + } else { + return z; /// returns z if z is the minimum value + } } /** @@ -85,42 +89,48 @@ uint64_t min(uint64_t x, uint64_t y, uint64_t z) { * @returns dp[m][n] the minimum cost of operations * needed to convert str1 to str2 */ -uint64_t editDistDP(std::string str1, std::string str2, uint64_t m, uint64_t n) { - /// Create a table to store results of subproblems - std::vector>dp(m+1, std::vector(n+1)); /// creasting 2D vector dp to store the results of subproblems +uint64_t editDistDP(std::string str1, std::string str2, uint64_t m, + uint64_t n) { + /// Create a table to store results of subproblems + std::vector> dp( + m + 1, + std::vector( + n + + 1)); /// creasting 2D vector dp to store the results of subproblems - /// Fill d[][] in bottom up manner - for (uint64_t i = 0; i <= m; i++) { - for (uint64_t j = 0; j <= n; j++) { - /// If first string is empty, only option is to - /// insert all characters of second string - if (i == 0) { - dp[i][j] = j; /// Minimum operations = j - } + /// Fill d[][] in bottom up manner + for (uint64_t i = 0; i <= m; i++) { + for (uint64_t j = 0; j <= n; j++) { + /// If first string is empty, only option is to + /// insert all characters of second string + if (i == 0) { + dp[i][j] = j; /// Minimum operations = j + } - /// If second string is empty, only option is to - /// remove all characters of second string - else if (j == 0) { - dp[i][j] = i; /// Minimum operations = i - } + /// If second string is empty, only option is to + /// remove all characters of second string + else if (j == 0) { + dp[i][j] = i; /// Minimum operations = i + } - /// If last characters are same, ignore last char - /// and recur for remaining string - else if (str1[i - 1] == str2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1]; - } + /// If last characters are same, ignore last char + /// and recur for remaining string + else if (str1[i - 1] == str2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1]; + } - /// If the last character is different, consider all - /// possibilities and find the minimum - else { - dp[i][j] = 1 + min(dp[i][j - 1], // Insert - dp[i - 1][j], // Remove - dp[i - 1][j - 1]); // Replace - } + /// If the last character is different, consider all + /// possibilities and find the minimum + else { + dp[i][j] = 1 + min(dp[i][j - 1], // Insert + dp[i - 1][j], // Remove + dp[i - 1][j - 1]); // Replace + } + } } - } - return dp[m][n]; /// returning the minimum cost of operations needed to convert str1 to str2 + return dp[m][n]; /// returning the minimum cost of operations needed to + /// convert str1 to str2 } } // namespace minimum_edit_distance } // namespace dynamic_programming @@ -130,25 +140,28 @@ uint64_t editDistDP(std::string str1, std::string str2, uint64_t m, uint64_t n) * @returns void */ static void test() { - // 1st test - std::string str1 = "INTENTION"; // Sample input of 1st string - std::string str2 = "EXECUTION"; // Sample input of 2nd string - uint64_t expected_output1 = 5; // Expected minimum cost - uint64_t output1 = dynamic_programming::minimum_edit_distance::editDistDP( - str1, str2, str1.length(), str2.length()); // calling the editDistDP function and storing the result on output1 - assert(output1 == expected_output1); // comparing the output with the expected output - std::cout << "Minimum Number of Operations Required: " << output1 - << std::endl; + // 1st test + std::string str1 = "INTENTION"; // Sample input of 1st string + std::string str2 = "EXECUTION"; // Sample input of 2nd string + uint64_t expected_output1 = 5; // Expected minimum cost + uint64_t output1 = dynamic_programming::minimum_edit_distance::editDistDP( + str1, str2, str1.length(), + str2.length()); // calling the editDistDP function and storing the + // result on output1 + assert(output1 == + expected_output1); // comparing the output with the expected output + std::cout << "Minimum Number of Operations Required: " << output1 + << std::endl; - // 2nd test - std::string str3 = "SATURDAY"; - std::string str4 = "SUNDAY"; - uint64_t expected_output2 = 3; - uint64_t output2 = dynamic_programming::minimum_edit_distance::editDistDP( - str3, str4, str3.length(), str4.length()); - assert(output2 == expected_output2); - std::cout << "Minimum Number of Operations Required: " << output2 - << std::endl; + // 2nd test + std::string str3 = "SATURDAY"; + std::string str4 = "SUNDAY"; + uint64_t expected_output2 = 3; + uint64_t output2 = dynamic_programming::minimum_edit_distance::editDistDP( + str3, str4, str3.length(), str4.length()); + assert(output2 == expected_output2); + std::cout << "Minimum Number of Operations Required: " << output2 + << std::endl; } /** @@ -158,6 +171,6 @@ static void test() { * @returns 0 on exit */ int main(int argc, char *argv[]) { - test(); // run self-test implementations - return 0; + test(); // run self-test implementations + return 0; } diff --git a/dynamic_programming/partition_problem.cpp b/dynamic_programming/partition_problem.cpp index 586a1800ba3..0dbfaa1d740 100644 --- a/dynamic_programming/partition_problem.cpp +++ b/dynamic_programming/partition_problem.cpp @@ -28,10 +28,10 @@ * *******************************************************************************/ #include /// for assert +#include /// for std::uint64_t #include /// for IO Operations #include /// for std::accumulate #include /// for std::vector - /****************************************************************************** * @namespace dp * @brief Dynamic programming algorithms diff --git a/dynamic_programming/subset_sum.cpp b/dynamic_programming/subset_sum_dynamic.cpp similarity index 100% rename from dynamic_programming/subset_sum.cpp rename to dynamic_programming/subset_sum_dynamic.cpp diff --git a/dynamic_programming/unbounded_0_1_knapsack.cpp b/dynamic_programming/unbounded_0_1_knapsack.cpp index 96588fe3936..384ea997884 100644 --- a/dynamic_programming/unbounded_0_1_knapsack.cpp +++ b/dynamic_programming/unbounded_0_1_knapsack.cpp @@ -1,33 +1,33 @@ /** * @file * @brief Implementation of the Unbounded 0/1 Knapsack Problem - * - * @details - * The Unbounded 0/1 Knapsack problem allows taking unlimited quantities of each item. - * The goal is to maximize the total value without exceeding the given knapsack capacity. - * Unlike the 0/1 knapsack, where each item can be taken only once, in this variation, - * any item can be picked any number of times as long as the total weight stays within - * the knapsack's capacity. - * - * Given a set of N items, each with a weight and a value, represented by the arrays - * `wt` and `val` respectively, and a knapsack with a weight limit W, the task is to - * fill the knapsack to maximize the total value. * - * @note weight and value of items is greater than zero + * @details + * The Unbounded 0/1 Knapsack problem allows taking unlimited quantities of each + * item. The goal is to maximize the total value without exceeding the given + * knapsack capacity. Unlike the 0/1 knapsack, where each item can be taken only + * once, in this variation, any item can be picked any number of times as long + * as the total weight stays within the knapsack's capacity. + * + * Given a set of N items, each with a weight and a value, represented by the + * arrays `wt` and `val` respectively, and a knapsack with a weight limit W, the + * task is to fill the knapsack to maximize the total value. + * + * @note weight and value of items is greater than zero * * ### Algorithm - * The approach uses dynamic programming to build a solution iteratively. - * A 2D array is used for memoization to store intermediate results, allowing + * The approach uses dynamic programming to build a solution iteratively. + * A 2D array is used for memoization to store intermediate results, allowing * the function to avoid redundant calculations. - * + * * @author [Sanskruti Yeole](https://github.com/yeolesanskruti) * @see dynamic_programming/0_1_knapsack.cpp */ +#include // For using assert function to validate test cases +#include // For fixed-width integer types like std::uint16_t #include // Standard input-output stream -#include // Standard library for using dynamic arrays (vectors) -#include // For using assert function to validate test cases -#include // For fixed-width integer types like std::uint16_t +#include // Standard library for using dynamic arrays (vectors) /** * @namespace dynamic_programming @@ -42,7 +42,7 @@ namespace dynamic_programming { namespace unbounded_knapsack { /** - * @brief Recursive function to calculate the maximum value obtainable using + * @brief Recursive function to calculate the maximum value obtainable using * an unbounded knapsack approach. * * @param i Current index in the value and weight vectors. @@ -52,27 +52,33 @@ namespace unbounded_knapsack { * @param wt Vector of weights corresponding to the items. * @note "wt" data type can be changed according to the size of the input. * @param dp 2D vector for memoization to avoid redundant calculations. - * @return The maximum value that can be obtained for the given index and capacity. + * @return The maximum value that can be obtained for the given index and + * capacity. */ -std::uint16_t KnapSackFilling(std::uint16_t i, std::uint16_t W, - const std::vector& val, - const std::vector& wt, - std::vector>& dp) { +std::uint16_t KnapSackFilling(std::uint16_t i, std::uint16_t W, + const std::vector& val, + const std::vector& wt, + std::vector>& dp) { if (i == 0) { if (wt[0] <= W) { - return (W / wt[0]) * val[0]; // Take as many of the first item as possible + return (W / wt[0]) * + val[0]; // Take as many of the first item as possible } else { - return 0; // Can't take the first item + return 0; // Can't take the first item } } - if (dp[i][W] != -1) return dp[i][W]; // Return result if available + if (dp[i][W] != -1) + return dp[i][W]; // Return result if available - int nottake = KnapSackFilling(i - 1, W, val, wt, dp); // Value without taking item i + int nottake = + KnapSackFilling(i - 1, W, val, wt, dp); // Value without taking item i int take = 0; if (W >= wt[i]) { - take = val[i] + KnapSackFilling(i, W - wt[i], val, wt, dp); // Value taking item i + take = val[i] + KnapSackFilling(i, W - wt[i], val, wt, + dp); // Value taking item i } - return dp[i][W] = std::max(take, nottake); // Store and return the maximum value + return dp[i][W] = + std::max(take, nottake); // Store and return the maximum value } /** @@ -84,17 +90,19 @@ std::uint16_t KnapSackFilling(std::uint16_t i, std::uint16_t W, * @param wt Vector of weights corresponding to the items. * @return The maximum value that can be obtained for the given capacity. */ -std::uint16_t unboundedKnapsack(std::uint16_t N, std::uint16_t W, - const std::vector& val, - const std::vector& wt) { - if(N==0)return 0; // Expect 0 since no items - std::vector> dp(N, std::vector(W + 1, -1)); // Initialize memoization table - return KnapSackFilling(N - 1, W, val, wt, dp); // Start the calculation +std::uint16_t unboundedKnapsack(std::uint16_t N, std::uint16_t W, + const std::vector& val, + const std::vector& wt) { + if (N == 0) + return 0; // Expect 0 since no items + std::vector> dp( + N, std::vector(W + 1, -1)); // Initialize memoization table + return KnapSackFilling(N - 1, W, val, wt, dp); // Start the calculation } -} // unbounded_knapsack +} // namespace unbounded_knapsack -} // dynamic_programming +} // namespace dynamic_programming /** * @brief self test implementation @@ -102,42 +110,57 @@ std::uint16_t unboundedKnapsack(std::uint16_t N, std::uint16_t W, */ static void tests() { // Test Case 1 - std::uint16_t N1 = 4; // Number of items - std::vector wt1 = {1, 3, 4, 5}; // Weights of the items - std::vector val1 = {6, 1, 7, 7}; // Values of the items - std::uint16_t W1 = 8; // Maximum capacity of the knapsack + std::uint16_t N1 = 4; // Number of items + std::vector wt1 = {1, 3, 4, 5}; // Weights of the items + std::vector val1 = {6, 1, 7, 7}; // Values of the items + std::uint16_t W1 = 8; // Maximum capacity of the knapsack // Test the function and assert the expected output - assert(unboundedKnapsack(N1, W1, val1, wt1) == 48); - std::cout << "Maximum Knapsack value " << unboundedKnapsack(N1, W1, val1, wt1) << std::endl; + assert(dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N1, W1, val1, wt1) == 48); + std::cout << "Maximum Knapsack value " + << dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N1, W1, val1, wt1) + << std::endl; // Test Case 2 - std::uint16_t N2 = 3; // Number of items - std::vector wt2 = {10, 20, 30}; // Weights of the items - std::vector val2 = {60, 100, 120}; // Values of the items - std::uint16_t W2 = 5; // Maximum capacity of the knapsack + std::uint16_t N2 = 3; // Number of items + std::vector wt2 = {10, 20, 30}; // Weights of the items + std::vector val2 = {60, 100, 120}; // Values of the items + std::uint16_t W2 = 5; // Maximum capacity of the knapsack // Test the function and assert the expected output - assert(unboundedKnapsack(N2, W2, val2, wt2) == 0); - std::cout << "Maximum Knapsack value " << unboundedKnapsack(N2, W2, val2, wt2) << std::endl; + assert(dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N2, W2, val2, wt2) == 0); + std::cout << "Maximum Knapsack value " + << dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N2, W2, val2, wt2) + << std::endl; // Test Case 3 - std::uint16_t N3 = 3; // Number of items - std::vector wt3 = {2, 4, 6}; // Weights of the items - std::vector val3 = {5, 11, 13};// Values of the items - std::uint16_t W3 = 27;// Maximum capacity of the knapsack + std::uint16_t N3 = 3; // Number of items + std::vector wt3 = {2, 4, 6}; // Weights of the items + std::vector val3 = {5, 11, 13}; // Values of the items + std::uint16_t W3 = 27; // Maximum capacity of the knapsack // Test the function and assert the expected output - assert(unboundedKnapsack(N3, W3, val3, wt3) == 27); - std::cout << "Maximum Knapsack value " << unboundedKnapsack(N3, W3, val3, wt3) << std::endl; + assert(dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N3, W3, val3, wt3) == 27); + std::cout << "Maximum Knapsack value " + << dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N3, W3, val3, wt3) + << std::endl; // Test Case 4 - std::uint16_t N4 = 0; // Number of items - std::vector wt4 = {}; // Weights of the items - std::vector val4 = {}; // Values of the items - std::uint16_t W4 = 10; // Maximum capacity of the knapsack - assert(unboundedKnapsack(N4, W4, val4, wt4) == 0); - std::cout << "Maximum Knapsack value for empty arrays: " << unboundedKnapsack(N4, W4, val4, wt4) << std::endl; - - std::cout << "All test cases passed!" << std::endl; + std::uint16_t N4 = 0; // Number of items + std::vector wt4 = {}; // Weights of the items + std::vector val4 = {}; // Values of the items + std::uint16_t W4 = 10; // Maximum capacity of the knapsack + assert(dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N4, W4, val4, wt4) == 0); + std::cout << "Maximum Knapsack value for empty arrays: " + << dynamic_programming::unbounded_knapsack::unboundedKnapsack( + N4, W4, val4, wt4) + << std::endl; + std::cout << "All test cases passed!" << std::endl; } /** @@ -145,7 +168,6 @@ static void tests() { * @return 0 on successful exit */ int main() { - tests(); // Run self test implementation + tests(); // Run self test implementation return 0; } - diff --git a/dynamic_programming/word_break.cpp b/dynamic_programming/word_break.cpp index 5291f665f59..2ec355a4b5f 100644 --- a/dynamic_programming/word_break.cpp +++ b/dynamic_programming/word_break.cpp @@ -105,7 +105,7 @@ bool check(const std::string &s, const std::unordered_set &strSet, // if the prefix till current position is present in the dictionary // and the remaining substring can also be segmented legally, then // set solution at position pos in the memo, and return true - if (exists(wordTillNow, strSet) and check(s, strSet, i + 1, dp)) { + if (exists(wordTillNow, strSet) && check(s, strSet, i + 1, dp)) { dp->at(pos) = 1; return true; } diff --git a/greedy_algorithms/CMakeLists.txt b/greedy_algorithms/CMakeLists.txt new file mode 100644 index 00000000000..bd45da6d4e9 --- /dev/null +++ b/greedy_algorithms/CMakeLists.txt @@ -0,0 +1,18 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".cpp" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX) + if(OpenMP_CXX_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_CXX) + endif() + install(TARGETS ${testname} DESTINATION "bin/greedy_algorithms") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/greedy_algorithms/dijkstra.cpp b/greedy_algorithms/dijkstra_greedy.cpp similarity index 100% rename from greedy_algorithms/dijkstra.cpp rename to greedy_algorithms/dijkstra_greedy.cpp diff --git a/greedy_algorithms/knapsack.cpp b/greedy_algorithms/knapsack.cpp index 74be4fee0e0..b5e9f6374ec 100644 --- a/greedy_algorithms/knapsack.cpp +++ b/greedy_algorithms/knapsack.cpp @@ -44,7 +44,7 @@ int main() { cout << "\n Enter the number of Items : "; int n; cin >> n; - Item itemArray[n]; + Item *itemArray = new Item[n]; for (int i = 0; i < n; i++) { cout << "\nEnter the weight and profit of item " << i + 1 << " : "; cin >> itemArray[i].weight; @@ -73,6 +73,6 @@ int main() { } cout << "\nMax Profit : " << maxProfit; - + delete[] itemArray; return 0; } diff --git a/operations_on_datastructures/CMakeLists.txt b/operations_on_datastructures/CMakeLists.txt new file mode 100644 index 00000000000..09119bc4300 --- /dev/null +++ b/operations_on_datastructures/CMakeLists.txt @@ -0,0 +1,15 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".cpp" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX) + install(TARGETS ${testname} DESTINATION "bin/operations_on_datastructures") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/operations_on_datastructures/circular_queue_using_array.cpp b/operations_on_datastructures/circular_queue_using_array.cpp index e0e049611da..58abbd7b649 100644 --- a/operations_on_datastructures/circular_queue_using_array.cpp +++ b/operations_on_datastructures/circular_queue_using_array.cpp @@ -1,5 +1,6 @@ #include -using namespace std; +using std::cin; +using std::cout; int queue[10]; int front = 0; diff --git a/operations_on_datastructures/trie_multiple_search.cpp b/operations_on_datastructures/trie_multiple_search.cpp index 854354fdfff..6dbb9d338d6 100644 --- a/operations_on_datastructures/trie_multiple_search.cpp +++ b/operations_on_datastructures/trie_multiple_search.cpp @@ -1,6 +1,7 @@ /** * @file - * @brief [Trie datastructure](https://iq.opengenus.org/autocomplete-using-trie-data-structure/) + * @brief [Trie + * datastructure](https://iq.opengenus.org/autocomplete-using-trie-data-structure/) * with search variants * @details * This provides multiple variants of search functions @@ -12,6 +13,7 @@ #include /// for std::count #include /// for assert #include /// for tolower +#include /// for std::uint32_t #include /// for string operations #include /// for IO Operations #include /// for std::priority_queue @@ -23,7 +25,8 @@ namespace operations_on_datastructures { /** * @namespace trie_operations - * @brief Functions for [Trie datastructure](https://iq.opengenus.org/autocomplete-using-trie-data-structure/) + * @brief Functions for [Trie + * datastructure](https://iq.opengenus.org/autocomplete-using-trie-data-structure/) * implementation */ namespace trie_operations { diff --git a/others/fast_integer_input.cpp b/others/fast_integer_input.cpp index 87963c9ad88..c929305c75b 100644 --- a/others/fast_integer_input.cpp +++ b/others/fast_integer_input.cpp @@ -11,7 +11,7 @@ void fastinput(int *number) { // variable to indicate sign of input integer bool negative = false; - register int c; + int c; *number = 0; // extract current character from buffer diff --git a/range_queries/CMakeLists.txt b/range_queries/CMakeLists.txt new file mode 100644 index 00000000000..c9f0c86f0a8 --- /dev/null +++ b/range_queries/CMakeLists.txt @@ -0,0 +1,18 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".cpp" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX) + if(OpenMP_CXX_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_CXX) + endif() + install(TARGETS ${testname} DESTINATION "bin/range_queries") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/range_queries/mo.cpp b/range_queries/mo.cpp index d281ef077ee..10abf0a96c3 100644 --- a/range_queries/mo.cpp +++ b/range_queries/mo.cpp @@ -1,4 +1,7 @@ +#include +#include #include + using namespace std; const int N = 1e6 + 5; int a[N], bucket[N], cnt[N]; diff --git a/range_queries/segtree.cpp b/range_queries/segtree.cpp index 71e6890fb1f..785d5325f8e 100644 --- a/range_queries/segtree.cpp +++ b/range_queries/segtree.cpp @@ -21,6 +21,7 @@ #include /// for assert #include /// for log2 +#include /// for std::uint64_t #include /// for IO operations #include /// for std::vector diff --git a/range_queries/sparse_table.cpp b/range_queries/sparse_table_range_queries.cpp similarity index 100% rename from range_queries/sparse_table.cpp rename to range_queries/sparse_table_range_queries.cpp From 8b1eab204b83e2516366d4b3aec97fe76c600099 Mon Sep 17 00:00:00 2001 From: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:11:14 +0530 Subject: [PATCH 72/74] doc: Use the doxygen awesome theme (#2807) * chore: remove cppreference * feat: add doxyfile * feat: add doxygen-awesome theme * chore: remove unneccessary doxygen config form cmake * test: for doxygen test purposes Note: revert before merging to main * fix: try removing css from rm * fix: set style sheet via cmake * feat: make doxygen theme finally work * fix: remove mathjax from doxyfile * feat: add sidebar and make mathjax work * doc: add transparency and make output svg of dot * fix: make dots interactive * chore: move math jax from cmake to doxyfile * feat: add header file * chore: add header file to cmake * chore: remove redundant transparency config * fix: force cmake to use config file * chore: remove working directory * fix: use old add_docs command * feat: fix doxygen build * fix: re enable clang assited parsing * fix: use relative paths * fix: relative paths arent necessary * feat: add project logo and favicon * fix: revert gh-pages to master * fix: add dot to doxyfile * fix: add lib clang to doxygen * fix: use source browser * fix: add clang as compiler * docs: remove headers from source browser * revert: branch to master --- .github/workflows/gh-pages.yml | 6 +- CMakeLists.txt | 33 +- doc/Doxyfile | 2926 ++ doc/assets/favicon.svg | 5 + doc/assets/project_logo.png | Bin 0 -> 7452 bytes doc/cppreference-doxygen-web.tag.xml | 35489 ------------------------- doc/html/header.html | 84 + doc/styles/doxygen-awesome.css | 2681 ++ 8 files changed, 5707 insertions(+), 35517 deletions(-) create mode 100644 doc/Doxyfile create mode 100644 doc/assets/favicon.svg create mode 100644 doc/assets/project_logo.png delete mode 100644 doc/cppreference-doxygen-web.tag.xml create mode 100644 doc/html/header.html create mode 100644 doc/styles/doxygen-awesome.css diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 3384cf859bf..b9c3fe03f52 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -1,6 +1,6 @@ name: Doxygen CI -on: +on: push: branches: [master] @@ -15,7 +15,7 @@ jobs: run: | brew install graphviz ninja doxygen - name: configure - run: cmake -G Ninja -B ./build -S . + run: cmake -G Ninja -Duse_libclang=ON -DCMAKE_CXX_COMPILER=clang++ -B ./build -S . - name: build run: cmake --build build -t doc - name: gh-pages @@ -28,7 +28,7 @@ jobs: git config --global user.name "$GITHUB_ACTOR" git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com" git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY - rm -rf d* && rm *.html && rm *.svg && rm *.map && rm *.md5 && rm *.png && rm *.js && rm *.css + rm -rf d* && rm *.html && rm *.svg && rm *.map && rm *.md5 && rm *.png && rm *.js git add . cp -rp ./build/html/* . && rm -rf ./build && ls -lah git add . diff --git a/CMakeLists.txt b/CMakeLists.txt index 95038fbab78..ba3ec4b7e24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.22) -project(Algorithms_in_C++ +project(TheAlgorithms/C++ LANGUAGES CXX VERSION 1.0.0 DESCRIPTION "Set of algorithms implemented in C++." @@ -54,47 +54,30 @@ add_subdirectory(physics) cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0057 NEW) + find_package(Doxygen OPTIONAL_COMPONENTS dot dia) -if(DOXYGEN_FOUND) - set(DOXYGEN_GENERATE_MAN NO) - set(DOXYGEN_USE_MATHJAX YES) - set(DOXYGEN_GENERATE_HTML YES) - # set(DOXYGEN_HTML_TIMESTAMP YES) - set(DOXYGEN_EXTRACT_STATIC YES) - set(DOXYGEN_INLINE_SOURCES YES) - set(DOXYGEN_CREATE_SUBDIRS YES) - set(DOXYGEN_EXTRACT_PRIVATE YES) - set(DOXYGEN_GENERATE_TREEVIEW YES) - set(DOXYGEN_STRIP_CODE_COMMENTS NO) - set(DOXYGEN_EXT_LINKS_IN_WINDOW YES) - set(DOXYGEN_BUILTIN_STL_SUPPORT YES) - set(DOXYGEN_EXCLUDE_PATTERNS */build/*) - set(DOXYGEN_ENABLE_PREPROCESSING YES) - set(DOXYGEN_CLANG_ASSISTED_PARSING YES) - set(DOXYGEN_FILE_PATTERNS *.cpp *.h *.hpp *.md) - set(DOXYGEN_MATHJAX_EXTENSIONS TeX/AMSmath TeX/AMSsymbols) - set(DOXYGEN_TAGFILES "doc/cppreference-doxygen-web.tag.xml=http://en.cppreference.com/w/") +if(DOXYGEN_FOUND) if(MSVC) set(DOXYGEN_CPP_CLI_SUPPORT YES) endif() - set(DOXYGEN_MATHJAX_RELPATH "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML") + if(Doxygen_dot_FOUND) set(DOXYGEN_HAVE_DOT YES) - set(DOXYGEN_CALL_GRAPH YES) - set(DOXYGEN_INTERACTIVE_SVG YES) - set(DOXYGEN_DOT_IMAGE_FORMAT "svg") endif() + if(OPENMP_FOUND) set(DOXYGEN_PREDEFINED "_OPENMP=1") endif() + if(GLUT_FOUND) set(DOXYGEN_PREDEFINED ${DOXYGEN_PREDEFINED} "GLUT_FOUND=1") endif() doxygen_add_docs( doc - ${PROJECT_SOURCE_DIR} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMENT "Generate documentation" + CONFIG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile ) endif() diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 00000000000..14101f4c753 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,2926 @@ +# Doxyfile 1.12.0 + +# This file describes the settings to be used by the documentation system +# Doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use Doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use Doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "TheAlgorithms/C++" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 1.0.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = All the algorithms implemented in C++ + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = doc/assets/project_logo.png + +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = doc/assets/favicon.svg + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where Doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = build/ + +# If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this +# option can be useful when feeding Doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. +# The default value is: NO. + +CREATE_SUBDIRS = YES + +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + +# If the ALLOW_UNICODE_NAMES tag is set to YES, Doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by Doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, Doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, Doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, Doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, Doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which Doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where Doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, Doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then Doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by Doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and Doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# Doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as Doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then Doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by Doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make Doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by Doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by Doxygen, so you can +# mix Doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 6. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 6 + +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled Doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let Doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also makes the inheritance and +# collaboration diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software) sources only. Doxygen will parse +# them like normal C++ but will assume all classes use public instead of private +# inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# Doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then Doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, Doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# Doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run Doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number of threads Doxygen is allowed to use +# during processing. When set to 0 Doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, Doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES Doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and macOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. + +CASE_SENSE_NAMES = SYSTEM + +# If the HIDE_SCOPE_NAMES tag is set to NO then Doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then Doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE = NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then Doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then Doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then Doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then Doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then Doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and Doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING Doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# Doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by Doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by Doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents Doxygen's defaults, run Doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run Doxygen from a directory containing a file called +# DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +# The EXTERNAL_TOOL_PATH tag can be used to extend the search path (PATH +# environment variable) so that external tools such as latex and gs can be +# found. +# Note: Directories specified with EXTERNAL_TOOL_PATH are added in front of the +# path already specified by the PATH variable, and are added in the order +# specified. +# Note: This option is particularly useful for macOS version 14 (Sonoma) and +# higher, when running Doxygen from Doxywizard, because in this case any user- +# defined changes to the PATH are ignored. A typical example on macOS is to set +# EXTERNAL_TOOL_PATH = /Library/TeX/texbin /usr/local/bin +# together with the standard path, the full search path used by doxygen when +# launching external tools will then become +# PATH=/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + +EXTERNAL_TOOL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by Doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by Doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then Doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, Doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# If WARN_IF_INCOMPLETE_DOC is set to YES, Doxygen will warn about incomplete +# function parameter documentation. If set to NO, Doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, Doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. + +WARN_NO_PARAMDOC = YES + +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, Doxygen will warn about +# undocumented enumeration values. If set to NO, Doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = YES + +# If the WARN_AS_ERROR tag is set to YES then Doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then Doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the Doxygen process Doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then Doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined Doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that Doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of Doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# This tag can be used to specify the character encoding of the source files +# that Doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). +# See also: INPUT_ENCODING for further information on supported encodings. + +INPUT_FILE_ENCODING = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by Doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, +# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to +# be provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cxxm \ + *.cpp \ + *.cppm \ + *.ccm \ + *.c++ \ + *.c++m \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.ixx \ + *.l \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which Doxygen is +# run. + +EXCLUDE = + + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = */build/* \ + */doc/* \ + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# ANamespace::AClass, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that Doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that Doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by Doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by Doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the Doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# multi-line macros, enums or list initialized variables directly into the +# documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct Doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of Doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by Doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then Doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then Doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which Doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not Doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then Doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by Doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not Doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, Doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank Doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that Doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that Doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of Doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = doc/html/header.html + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank Doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that Doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank Doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that Doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by Doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = doc/styles/doxygen-awesome.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generates light mode output, DARK always +# generates dark mode output, AUTO_LIGHT automatically sets the mode according +# to the user preference, uses light mode if no preference is set (the default), +# AUTO_DARK automatically sets the mode according to the user preference, uses +# dark mode if no preference is set and TOGGLE allows a user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = LIGHT + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then Doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# Doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, Doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then Doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by Doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# Doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty Doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by Doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# Doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# When the SHOW_ENUM_VALUES tag is set doxygen will show the specified +# enumeration values besides the enumeration mnemonics. +# The default value is: NO. + +SHOW_ENUM_VALUES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, Doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = YES + +# If the OBFUSCATE_EMAILS tag is set to YES, Doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, Doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# Doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = YES + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_3 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@3 + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = ams + +# The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled Doxygen will generate a search box for +# the HTML output. The underlying search engine uses JavaScript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the JavaScript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /