From 7309ef13707b8f2e03d894d2b457740013d13cc5 Mon Sep 17 00:00:00 2001 From: Yaniv Hollander Date: Wed, 6 Oct 2021 19:55:45 -0400 Subject: [PATCH 1/4] feat: Add the Windowed Median algorithm (#1649) * Create windowed_median.cpp * Update windowed_median.cpp * Update windowed_median.cpp * updating DIRECTORY.md * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update windowed_median.cpp * Update windowed_median.cpp * Update windowed_median.cpp * Update windowed_median.cpp * Update windowed_median.cpp * Update windowed_median.cpp * Update probability/windowed_median.cpp Co-authored-by: David Leal * clang-format and clang-tidy fixes for 7634ece0 * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update probability/windowed_median.cpp Co-authored-by: David Leal * Update windowed_median.cpp * Update windowed_median.cpp Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal --- DIRECTORY.md | 1 + probability/windowed_median.cpp | 226 ++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 probability/windowed_median.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index 528fb0add..7d206c91c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -267,6 +267,7 @@ * [Bayes Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/bayes_theorem.cpp) * [Binomial Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/binomial_dist.cpp) * [Poisson Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/poisson_dist.cpp) + * [Windowed Median](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/windowed_median.cpp) ## Range Queries * [Fenwick Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/range_queries/fenwick_tree.cpp) diff --git a/probability/windowed_median.cpp b/probability/windowed_median.cpp new file mode 100644 index 000000000..8945b063e --- /dev/null +++ b/probability/windowed_median.cpp @@ -0,0 +1,226 @@ +/** + * @file + * @brief An implementation of a median calculation of a sliding window along a + * data stream + * + * @details + * Given a stream of integers, the algorithm calculates the median of a fixed size + * window at the back of the stream. The leading time complexity of this + * algorithm is O(log(N), and it is inspired by the known algorithm to [find + * median from (infinite) data + * stream](https://www.tutorialcup.com/interview/algorithm/find-median-from-data-stream.htm), + * with the proper modifications to account for the finite window size for which + * the median is requested + * + * ### Algorithm + * The sliding window is managed by a list, which guarantees O(1) for both + * pushing and popping. Each new value is pushed to the window back, while a + * value from the front of the window is popped. In addition, the algorithm + * manages a multi-value binary search tree (BST), implemented by std::multiset. + * For each new value that is inserted into the window, it is also inserted to the + * BST. When a value is popped from the window, it is also erased from the BST. + * Both insertion and erasion to/from the BST are O(logN) in time, with N the + * size of the window. Finally, the algorithm keeps a pointer to the root of the + * BST, and updates its position whenever values are inserted or erased to/from + * BST. The root of the tree is the median! Hence, median retrieval is always + * O(1) + * + * Time complexity: O(logN). Space complexity: O(N). N - size of window + * @author [Yaniv Hollander](https://github.com/YanivHollander) + */ +#include /// for assert +#include /// for std::rand - needed in testing +#include /// for std::time - needed in testing +#include /// for std::list - used to manage sliding window +#include /// for std::multiset - used to manage multi-value sorted sliding window values +#include /// for std::vector - needed in testing + +/** + * @namespace probability + * @brief Probability algorithms + */ +namespace probability { +/** + * @namespace windowed_median + * @brief Functions for the Windowed Median algorithm implementation + */ +namespace windowed_median { +using Window = std::list; +using size_type = Window::size_type; + +/** + * @class WindowedMedian + * @brief A class to calculate the median of a leading sliding window at the + * back of a stream of integer values. + */ +class WindowedMedian { + const size_type _windowSize; ///< sliding window size + Window _window; ///< a sliding window of values along the stream + std::multiset _sortedValues; ///< a DS to represent a balanced + /// multi-value binary search tree (BST) + std::multiset::const_iterator + _itMedian; ///< an iterator that points to the root of the multi-value + /// BST + + /** + * @brief Inserts a value to a sorted multi-value BST + * @param value Value to insert + */ + void insertToSorted(int value) { + _sortedValues.insert(value); /// Insert value to BST - O(logN) + const auto sz = _sortedValues.size(); + if (sz == 1) { /// For the first value, set median iterator to BST root + _itMedian = _sortedValues.begin(); + return; + } + + /// If new value goes to left tree branch, and number of elements is + /// even, the new median in the balanced tree is the left child of the + /// median before the insertion + if (value < *_itMedian && sz % 2 == 0) { + --_itMedian; // O(1) - traversing one step to the left child + } + + /// However, if the new value goes to the right branch, the previous + /// median's right child is the new median in the balanced tree + else if (value >= *_itMedian && sz % 2 != 0) { + ++_itMedian; /// O(1) - traversing one step to the right child + } + } + + /** + * @brief Erases a value from a sorted multi-value BST + * @param value Value to insert + */ + void eraseFromSorted(int value) { + const auto sz = _sortedValues.size(); + + /// If the erased value is on the left branch or the median itself and + /// the number of elements is even, the new median will be the right + /// child of the current one + if (value <= *_itMedian && sz % 2 == 0) { + ++_itMedian; /// O(1) - traversing one step to the right child + } + + /// However, if the erased value is on the right branch or the median + /// itself, and the number of elements is odd, the new median will be the + /// left child of the current one + else if (value >= *_itMedian && sz % 2 != 0) { + --_itMedian; // O(1) - traversing one step to the left child + } + + /// Find the (first) position of the value we want to erase, and erase it + const auto it = _sortedValues.find(value); // O(logN) + _sortedValues.erase(it); // O(logN) + } + + public: + /** + * @brief Constructs a WindowedMedian object + * @param windowSize Sliding window size + */ + explicit WindowedMedian(size_type windowSize) : _windowSize(windowSize){}; + + /** + * @brief Insert a new value to the stream + * @param value New value to insert + */ + void insert(int value) { + + /// Push new value to the back of the sliding window - O(1) + _window.push_back(value); + insertToSorted(value); // Insert value to the multi-value BST - O(logN) + if (_window.size() > _windowSize) { /// If exceeding size of window, pop + /// from its left side + eraseFromSorted(_window.front()); /// Erase from the multi-value BST + /// the window left side value + _window + .pop_front(); /// Pop the left side value from the window - O(1) + } + } + + /** + * @brief Gets the median of the values in the sliding window + * @return Median of sliding window. For even window size return the average + * between the two values in the middle + */ + float getMedian() const { + if (_sortedValues.size() % 2 != 0) { + return *_itMedian; // O(1) + } + return 0.5f * *_itMedian + 0.5f * *next(_itMedian); /// O(1) + } + + /** + * @brief A naive and inefficient method to obtain the median of the sliding + * window. Used for testing! + * @return Median of sliding window. For even window size return the average + * between the two values in the middle + */ + float getMedianNaive() const { + auto window = _window; + window.sort(); /// Sort window - O(NlogN) + auto median = + *next(window.begin(), + window.size() / 2); /// Find value in the middle - O(N) + if (window.size() % 2 != 0) { + return median; + } + return 0.5f * median + + 0.5f * *next(window.begin(), window.size() / 2 - 1); /// O(N) + } +}; +} /// namespace windowed_median +} /// namespace probability + +/** + * @brief Self-test implementations + * @param vals Stream of values + * @param windowSize Size of sliding window + */ +static void test(const std::vector &vals, int windowSize) { + probability::windowed_median::WindowedMedian windowedMedian(windowSize); + for (const auto val : vals) { + windowedMedian.insert(val); + + /// Comparing medians: efficient function vs. Naive one + assert(windowedMedian.getMedian() == windowedMedian.getMedianNaive()); + } +} + +/** + * @brief Main function + * @param argc command line argument count (ignored) + * @param argv command line array of arguments (ignored) + * @returns 0 on exit + */ +int main(int argc, const char *argv[]) { + + /// A few fixed test cases + test({1, 2, 3, 4, 5, 6, 7, 8, 9}, 3); /// Array of sorted values; odd window size + test({9, 8, 7, 6, 5, 4, 3, 2, 1}, 3); /// Array of sorted values - decreasing; odd window size + test({9, 8, 7, 6, 5, 4, 5, 6}, 4); /// Even window size + test({3, 3, 3, 3, 3, 3, 3, 3, 3}, 3); /// Array with repeating values + test({3, 3, 3, 3, 7, 3, 3, 3, 3}, 3); /// Array with same values except one + test({4, 3, 3, -5, -5, 1, 3, 4, 5}, 5); /// Array that includes repeating values including negatives + + /// Array with large values - sum of few pairs exceeds MAX_INT. Window size is even - testing calculation of + /// average median between two middle values + test({470211272, 101027544, 1457850878, 1458777923, 2007237709, 823564440, + 1115438165, 1784484492, 74243042, 114807987}, 6); + + /// Random test cases + std::srand(static_cast(std::time(nullptr))); + std::vector vals; + for (int i = 8; i < 100; i++) { + const auto n = 1 + std::rand() / ((RAND_MAX + 5u) / 20); /// Array size in the range [5, 20] + auto windowSize = 1 + std::rand() / ((RAND_MAX + 3u) / 10); /// Window size in the range [3, 10] + vals.clear(); + vals.reserve(n); + for (int i = 0; i < n; i++) { + vals.push_back(rand() - RAND_MAX); /// Random array values (positive/negative) + } + test(vals, windowSize); /// Testing randomized test + } + return 0; +} From 7ab098bc947fd94b82c871c0ac4cedf4492090d0 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 7 Oct 2021 05:42:14 +0000 Subject: [PATCH 2/4] updating DIRECTORY.md --- DIRECTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 528fb0add..a77c97982 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -29,6 +29,9 @@ * [Vigenere Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/vigenere_cipher.cpp) * [Xor Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/xor_cipher.cpp) +## Cpu Scheduling Algorithms + * [Fcfs Scheduling](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/cpu_scheduling_algorithms/fcfs_scheduling.cpp) + ## Data Structures * [Avltree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/avltree.cpp) * [Binary Search Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/binary_search_tree.cpp) From 9ff928ff589b92221bd0126cb71cc1987b99098e Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 7 Oct 2021 05:42:24 +0000 Subject: [PATCH 3/4] clang-format and clang-tidy fixes for c95495b4 --- cpu_scheduling_algorithms/fcfs_scheduling.cpp | 170 +++++++++--------- 1 file changed, 88 insertions(+), 82 deletions(-) diff --git a/cpu_scheduling_algorithms/fcfs_scheduling.cpp b/cpu_scheduling_algorithms/fcfs_scheduling.cpp index bba34c0dd..a3ee90c95 100644 --- a/cpu_scheduling_algorithms/fcfs_scheduling.cpp +++ b/cpu_scheduling_algorithms/fcfs_scheduling.cpp @@ -1,41 +1,41 @@ -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include using std::cin; using std::cout; -using std::get; -using std::priority_queue; -using std::unordered_set; -using std::make_tuple; -using std::vector; -using std::tuple; using std::endl; +using std::get; using std::left; +using std::make_tuple; +using std::priority_queue; +using std::tuple; +using std::unordered_set; +using std::vector; -/** +/** * @brief Comparator class for Priority queue * S: Data type of Process id * T: Data type of Arrival time - * E: Data type of Burst time -*/ -template -class Compare{ - public: + * E: Data type of Burst time + */ +template +class Compare { + public: /** * @param t1 = first tuple - * @param t2 = second tuple + * @param t2 = second tuple * @brief checks whether to swap two tuples or not - */ - bool operator () (tuple& t1, tuple& t2){ - if(get<1>(t2) < get<1>(t1)){ + */ + bool operator()(tuple& t1, + tuple& t2) { + if (get<1>(t2) < get<1>(t1)) { return true; - } - else if(get<1>(t2) == get<1>(t1)){ + } else if (get<1>(t2) == get<1>(t1)) { return get<0>(t2) < get<0>(t1); } return false; @@ -46,10 +46,10 @@ class Compare{ * @brief Class which implements the FCFS scheduling algorithm * S: Data type of Process id * T: Data type of Arrival time - * E: Data type of Burst time -*/ -template -class FCFS{ + * E: Data type of Burst time + */ +template +class FCFS { /** * Priority queue of schedules(stored as tuples) of processes. * In each tuple @@ -59,62 +59,72 @@ class FCFS{ * 4th element: Completion time * 5th element: Turnaround time * 6th element: Waiting time - */ - priority_queue, vector>, Compare> schedule; + */ + priority_queue, + vector>, + Compare> + schedule; // Stores final status of all the processes after completing execution. - vector> result; - - // Stores process ids. Used for confirming absence of a process while adding it. + vector> result; + + // Stores process ids. Used for confirming absence of a process while adding + // it. unordered_set idList; - public: + + public: /** * @brief add the process to the ready queue if it isn't already there * @param id: Process id * @param arrival: Arrival time of the process * @param burst: Burst time of the process - * - */ - void addProcess(S id, T arrival, E burst){ + * + */ + void addProcess(S id, T arrival, E burst) { // Add if process with process id not found in idList. - if(idList.find(id) == idList.end()) { - tuple t = make_tuple(id, arrival, burst, 0, 0, 0); + if (idList.find(id) == idList.end()) { + tuple t = + make_tuple(id, arrival, burst, 0, 0, 0); schedule.push(t); idList.insert(id); } - } /** - * @brief Algorithm for scheduling CPU processes according to the First Come First Serve(FCFS) scheduling algorithm. - * - * @description FCFS is a non -preemptive algorithm in which the process which arrives first gets executed first. If two or - * more processes arrive together then the process with smaller process id runs first (each process has a unique proces id). - * - * I used a min priority queue of tuples to accomplish this task. The processes are ordered by their arrival times. If arrival - * times of some processes are equal, then they are ordered by their process id. - */ - void scheduleForFcfs(){ + * @brief Algorithm for scheduling CPU processes according to the First Come + * First Serve(FCFS) scheduling algorithm. + * + * @description FCFS is a non -preemptive algorithm in which the process + * which arrives first gets executed first. If two or more processes arrive + * together then the process with smaller process id runs first (each + * process has a unique proces id). + * + * I used a min priority queue of tuples to accomplish this task. The + * processes are ordered by their arrival times. If arrival times of some + * processes are equal, then they are ordered by their process id. + */ + void scheduleForFcfs() { // Variable to keep track of time elepsed so far double timeElapsed = 0; - while(!schedule.empty()){ + while (!schedule.empty()) { tuple cur = schedule.top(); - - // If the next process arrived at time t2, the last process completed its execution at time t1, and t2 > t1. - if(get<1>(cur) > timeElapsed){ + + // If the next process arrived at time t2, the last process + // completed its execution at time t1, and t2 > t1. + if (get<1>(cur) > timeElapsed) { timeElapsed += get<1>(cur) - timeElapsed; } // Add Burst time to time elapsed timeElapsed += get<2>(cur); - + get<3>(cur) = timeElapsed; - + // Turnaround time = Completion time - Arrival time get<4>(cur) = get<3>(cur) - get<1>(cur); - //Waiting time = Turnaround time - Burst time + // Waiting time = Turnaround time - Burst time get<5>(cur) = get<4>(cur) - get<2>(cur); result.push_back(cur); @@ -124,43 +134,39 @@ class FCFS{ } // Utility function for printing the status of each process after execution - void printResult(){ - cout << "Status of all the proceses post completion is as follows:" << endl; + void printResult() { + cout << "Status of all the proceses post completion is as follows:" + << endl; - cout << std::setw(17) << left << "Process Id" - << std::setw(17) << left << "Arrival Time" - << std::setw(17) << left << "Burst Time" - << std::setw(17) << left << "Completion Time" - << std::setw(17) << left << "Turnaround Time" - << std::setw(17) << left << "Waiting Time" << endl; - - for(size_t i{}; i < result.size(); i++){ - cout << std::setprecision(2) << std::fixed - << std::setw(17) << left << get<0>(result[i]) - << std::setw(17) << left << get<1>(result[i]) - << std::setw(17) << left << get<2>(result[i]) - << std::setw(17) << left << get<3>(result[i]) - << std::setw(17) << left << get<4>(result[i]) - << std::setw(17) << left << get<5>(result[i]) << endl; + cout << std::setw(17) << left << "Process Id" << std::setw(17) << left + << "Arrival Time" << std::setw(17) << left << "Burst Time" + << std::setw(17) << left << "Completion Time" << std::setw(17) + << left << "Turnaround Time" << std::setw(17) << left + << "Waiting Time" << endl; + + for (size_t i{}; i < result.size(); i++) { + cout << std::setprecision(2) << std::fixed << std::setw(17) << left + << get<0>(result[i]) << std::setw(17) << left + << get<1>(result[i]) << std::setw(17) << left + << get<2>(result[i]) << std::setw(17) << left + << get<3>(result[i]) << std::setw(17) << left + << get<4>(result[i]) << std::setw(17) << left + << get<5>(result[i]) << endl; } } - - }; -int main(){ - FCFS readyQueue; +int main() { + FCFS readyQueue; - //Sample test case + // Sample test case int n = 3; vector> input = { - make_tuple(1, 0, 30), - make_tuple(2, 0, 5), - make_tuple(3, 0, 5) - }; + make_tuple(1, 0, 30), make_tuple(2, 0, 5), make_tuple(3, 0, 5)}; - for(int i{}; i < n; i++){ - readyQueue.addProcess(get<0>(input[i]), get<1>(input[i]), get<2>(input[i])); + for (int i{}; i < n; i++) { + readyQueue.addProcess(get<0>(input[i]), get<1>(input[i]), + get<2>(input[i])); } readyQueue.scheduleForFcfs(); From d51f98e365a3d9c16d8d364e3377b91e0d747186 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 7 Oct 2021 05:55:39 +0000 Subject: [PATCH 4/4] clang-format and clang-tidy fixes for 732f247d --- probability/windowed_median.cpp | 90 ++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/probability/windowed_median.cpp b/probability/windowed_median.cpp index 8945b063e..52c70ae24 100644 --- a/probability/windowed_median.cpp +++ b/probability/windowed_median.cpp @@ -4,8 +4,8 @@ * data stream * * @details - * Given a stream of integers, the algorithm calculates the median of a fixed size - * window at the back of the stream. The leading time complexity of this + * Given a stream of integers, the algorithm calculates the median of a fixed + * size window at the back of the stream. The leading time complexity of this * algorithm is O(log(N), and it is inspired by the known algorithm to [find * median from (infinite) data * stream](https://www.tutorialcup.com/interview/algorithm/find-median-from-data-stream.htm), @@ -17,13 +17,13 @@ * pushing and popping. Each new value is pushed to the window back, while a * value from the front of the window is popped. In addition, the algorithm * manages a multi-value binary search tree (BST), implemented by std::multiset. - * For each new value that is inserted into the window, it is also inserted to the - * BST. When a value is popped from the window, it is also erased from the BST. - * Both insertion and erasion to/from the BST are O(logN) in time, with N the - * size of the window. Finally, the algorithm keeps a pointer to the root of the - * BST, and updates its position whenever values are inserted or erased to/from - * BST. The root of the tree is the median! Hence, median retrieval is always - * O(1) + * For each new value that is inserted into the window, it is also inserted to + * the BST. When a value is popped from the window, it is also erased from the + * BST. Both insertion and erasion to/from the BST are O(logN) in time, with N + * the size of the window. Finally, the algorithm keeps a pointer to the root of + * the BST, and updates its position whenever values are inserted or erased + * to/from BST. The root of the tree is the median! Hence, median retrieval is + * always O(1) * * Time complexity: O(logN). Space complexity: O(N). N - size of window * @author [Yaniv Hollander](https://github.com/YanivHollander) @@ -32,8 +32,8 @@ #include /// for std::rand - needed in testing #include /// for std::time - needed in testing #include /// for std::list - used to manage sliding window -#include /// for std::multiset - used to manage multi-value sorted sliding window values -#include /// for std::vector - needed in testing +#include /// for std::multiset - used to manage multi-value sorted sliding window values +#include /// for std::vector - needed in testing /** * @namespace probability @@ -55,7 +55,7 @@ using size_type = Window::size_type; */ class WindowedMedian { const size_type _windowSize; ///< sliding window size - Window _window; ///< a sliding window of values along the stream + Window _window; ///< a sliding window of values along the stream std::multiset _sortedValues; ///< a DS to represent a balanced /// multi-value binary search tree (BST) std::multiset::const_iterator @@ -103,13 +103,14 @@ class WindowedMedian { } /// However, if the erased value is on the right branch or the median - /// itself, and the number of elements is odd, the new median will be the - /// left child of the current one + /// itself, and the number of elements is odd, the new median will be + /// the left child of the current one else if (value >= *_itMedian && sz % 2 != 0) { --_itMedian; // O(1) - traversing one step to the left child } - /// Find the (first) position of the value we want to erase, and erase it + /// Find the (first) position of the value we want to erase, and erase + /// it const auto it = _sortedValues.find(value); // O(logN) _sortedValues.erase(it); // O(logN) } @@ -126,16 +127,16 @@ class WindowedMedian { * @param value New value to insert */ void insert(int value) { - /// Push new value to the back of the sliding window - O(1) _window.push_back(value); insertToSorted(value); // Insert value to the multi-value BST - O(logN) - if (_window.size() > _windowSize) { /// If exceeding size of window, pop - /// from its left side - eraseFromSorted(_window.front()); /// Erase from the multi-value BST - /// the window left side value - _window - .pop_front(); /// Pop the left side value from the window - O(1) + if (_window.size() > _windowSize) { /// If exceeding size of window, + /// pop from its left side + eraseFromSorted( + _window.front()); /// Erase from the multi-value BST + /// the window left side value + _window.pop_front(); /// Pop the left side value from the window - + /// O(1) } } @@ -170,8 +171,8 @@ class WindowedMedian { 0.5f * *next(window.begin(), window.size() / 2 - 1); /// O(N) } }; -} /// namespace windowed_median -} /// namespace probability +} // namespace windowed_median +} // namespace probability /** * @brief Self-test implementations @@ -195,32 +196,41 @@ static void test(const std::vector &vals, int windowSize) { * @returns 0 on exit */ int main(int argc, const char *argv[]) { - /// A few fixed test cases - test({1, 2, 3, 4, 5, 6, 7, 8, 9}, 3); /// Array of sorted values; odd window size - test({9, 8, 7, 6, 5, 4, 3, 2, 1}, 3); /// Array of sorted values - decreasing; odd window size - test({9, 8, 7, 6, 5, 4, 5, 6}, 4); /// Even window size - test({3, 3, 3, 3, 3, 3, 3, 3, 3}, 3); /// Array with repeating values - test({3, 3, 3, 3, 7, 3, 3, 3, 3}, 3); /// Array with same values except one - test({4, 3, 3, -5, -5, 1, 3, 4, 5}, 5); /// Array that includes repeating values including negatives - - /// Array with large values - sum of few pairs exceeds MAX_INT. Window size is even - testing calculation of - /// average median between two middle values + test({1, 2, 3, 4, 5, 6, 7, 8, 9}, + 3); /// Array of sorted values; odd window size + test({9, 8, 7, 6, 5, 4, 3, 2, 1}, + 3); /// Array of sorted values - decreasing; odd window size + test({9, 8, 7, 6, 5, 4, 5, 6}, 4); /// Even window size + test({3, 3, 3, 3, 3, 3, 3, 3, 3}, 3); /// Array with repeating values + test({3, 3, 3, 3, 7, 3, 3, 3, 3}, 3); /// Array with same values except one + test({4, 3, 3, -5, -5, 1, 3, 4, 5}, + 5); /// Array that includes repeating values including negatives + + /// Array with large values - sum of few pairs exceeds MAX_INT. Window size + /// is even - testing calculation of average median between two middle + /// values test({470211272, 101027544, 1457850878, 1458777923, 2007237709, 823564440, - 1115438165, 1784484492, 74243042, 114807987}, 6); - + 1115438165, 1784484492, 74243042, 114807987}, + 6); + /// Random test cases std::srand(static_cast(std::time(nullptr))); std::vector vals; for (int i = 8; i < 100; i++) { - const auto n = 1 + std::rand() / ((RAND_MAX + 5u) / 20); /// Array size in the range [5, 20] - auto windowSize = 1 + std::rand() / ((RAND_MAX + 3u) / 10); /// Window size in the range [3, 10] + const auto n = + 1 + std::rand() / + ((RAND_MAX + 5u) / 20); /// Array size in the range [5, 20] + auto windowSize = + 1 + std::rand() / ((RAND_MAX + 3u) / + 10); /// Window size in the range [3, 10] vals.clear(); vals.reserve(n); for (int i = 0; i < n; i++) { - vals.push_back(rand() - RAND_MAX); /// Random array values (positive/negative) + vals.push_back( + rand() - RAND_MAX); /// Random array values (positive/negative) } - test(vals, windowSize); /// Testing randomized test + test(vals, windowSize); /// Testing randomized test } return 0; }