From 1433ef22106c140121ecaba64cc2116fd0c39aa9 Mon Sep 17 00:00:00 2001 From: Rp-sushil Date: Thu, 20 Aug 2020 17:21:30 +0530 Subject: [PATCH 01/10] [BUG] #804 search/median_search.cpp FIXED --- search/median_search.cpp | 158 +++++++++++++++++++++++---------------- 1 file changed, 95 insertions(+), 63 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index 7379cad26..3190afa2d 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -1,78 +1,110 @@ /** * \file * \brief [Median search](https://en.wikipedia.org/wiki/Median_search) algorithm - * \warning This core is erroneous and gives invorrect answers. Tested using * cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) * \ingroup median search - * \{ */ -#include + #include +#include #include +using namespace std; -/** - * @todo add documentation - */ -template -void comp(X x, std::vector *s1, std::vector *s2, - std::vector *s3) { - if (s1->size() >= x && s1->size() + s2->size() < x) { - std::cout << (*s2)[0] << " is the " << x + 1 << "th element from front"; - } else if (s1->size() > x) { - std::sort(s1->begin(), s1->end()); - std::cout << (*s1)[x] << " is the " << x + 1 << "th element from front"; - } else if (s1->size() + s2->size() <= x && s3->size() > x) { - std::sort(s3->begin(), s3->end()); - std::cout << (*s3)[x - s1->size() - s2->size()] << " is the " << x + 1 - << "th element from front"; - } else { - std::cout << x + 1 << " is invalid location"; - } +/* Assume that all the elements of A are distinct + def median_of_medians(A, i): + + #divide A into sublists of len 5 + sublists = [A[j:j+5] for j in range(0, len(A), 5)] + medians = [sorted(sublist)[len(sublist)/2] for sublist in sublists] + if len(medians) <= 5: + pivot = sorted(medians)[len(medians)/2] + else: + #the pivot is the median of the medians + pivot = median_of_medians(medians, len(medians)/2) + + #partitioning step + low = [j for j in A if j < pivot] + high = [j for j in A if j > pivot] + + k = len(low) + if i < k: + return median_of_medians(low,i) + elif i > k: + return median_of_medians(high,i-k-1) + else: #pivot = k + return pivot +*/ + +/* + * Here are some example lists you can use to see how the algorithm works + * A = [1,2,3,4,5,1000,8,9,99] (Contain Unique Elements) + * B = [1,2,3,4,5,6] (Contains Unique Elements) + * print median_of_medians(A, 0) #should be 1 + * print median_of_medians(A,7) #should be 99 + * print median_of_medians(B,4) #should be 5 +*/ + +int median_of_medians(vector a, int idx){ + int pivot; + vector m; + int r = a.size(); + for(int i = 0; i < r; i += 5){ + sort(a.begin() + i, a.begin() + min(r, i + 5)); + int mid = (i + min(r, i + 5)) / 2; + m.push_back(a[mid]); + } + int sz = int(m.size()); + if(sz <= 5){ + sort(m.begin(), m.end()); + pivot = m[(sz- 1) / 2]; + } + else{ + pivot = median_of_medians(m, idx); + } + vector low; + vector high; + for(int i = 0; i < r; i++){ + if(a[i] < pivot) + low.push_back(a[i]); + else if(a[i] > pivot) + high.push_back(a[i]); + } + int k = int(low.size()); + if(idx < k) + return median_of_medians(low, idx); + else if(idx > k) + return median_of_medians(high, idx-k-1); + else + return pivot; } -#define MAX_NUM 20 ///< maximum number of values to sort from +/* Main function*/ -/** - * Main function - */ -int main() { - std::vector v{25, 21, 98, 100, 76, 22, 43, 60, 89, 87}; - std::vector s1; - std::vector s2; - std::vector s3; +int main() +{ + int n; + cout << "Enter Size of Array: "; + cin >> n; + vector a(n); + cout << "Enter Array: "; + for(int i = 0; i < n; i++) + cin >> a[i]; - // creates an array of random numbers - // for (int i = 0; i < MAX_NUM; i++) { - // int r = std::rand() % 1000; - // v.push_back(r); - // std::cout << r << " "; - // } - for (int r : v) std::cout << r << " "; + cout << "Median: "; + int x = median_of_medians(a, (n - 1) / 2); + if(n % 2 == 0){ + int y = median_of_medians(a, n / 2); + cout << (float(x) + float(y))/2.0; + } + else + cout << x; - int median = std::rand() % 1000; // initialize to a random numnber - - std::cout << "\nmedian=" << median << std::endl; - int avg1, avg2, avg3, sum1 = 0, sum2 = 0, sum3 = 0; - - for (int i = 0; i < v.size(); i++) { // iterate through all numbers - if (v.back() == v[median]) { - avg1 = sum1 + v.back(); - s2.push_back(v.back()); - } else if (v.back() < v[median]) { - avg2 = sum2 + v.back(); - s1.push_back(v.back()); - } else { - avg3 = sum3 + v.back(); - s3.push_back(v.back()); - } - v.pop_back(); - } - - int x; - std::cout << "enter the no. to be searched form begining:- "; - std::cin >> x; - comp(x - 1, &s1, &s2, &s3); - - return 0; + cout << "\nTo find i-th smallest element "; + cout << "\nEnter i: "; + int idx; + cin >> idx; + idx--; + cout << "i-th smallest element: " << median_of_medians(a, idx) << endl; + return 0; } -/// } + From 0d61b0494f01149fe78a3e3132e095392ed06cfd Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Fri, 21 Aug 2020 10:45:00 +0530 Subject: [PATCH 02/10] fixed clang-tidy warnings --- search/median_search.cpp | 68 +++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index 3190afa2d..c67ad170b 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -8,7 +8,6 @@ #include #include #include -using namespace std; /* Assume that all the elements of A are distinct def median_of_medians(A, i): @@ -44,67 +43,72 @@ using namespace std; * print median_of_medians(B,4) #should be 5 */ -int median_of_medians(vector a, int idx){ - int pivot; - vector m; +int median_of_medians(std::vector a, int idx){ + int pivot = 0; // initialized with zero + std::vector m; int r = a.size(); for(int i = 0; i < r; i += 5){ - sort(a.begin() + i, a.begin() + min(r, i + 5)); - int mid = (i + min(r, i + 5)) / 2; + std::sort(a.begin() + i, a.begin() + std::min(r, i + 5)); + int mid = (i + std::min(r, i + 5)) / 2; m.push_back(a[mid]); } int sz = int(m.size()); if(sz <= 5){ - sort(m.begin(), m.end()); + std::sort(m.begin(), m.end()); pivot = m[(sz- 1) / 2]; } else{ pivot = median_of_medians(m, idx); } - vector low; - vector high; + std::vector low; + std::vector high; for(int i = 0; i < r; i++){ - if(a[i] < pivot) + if(a[i] < pivot){ low.push_back(a[i]); - else if(a[i] > pivot) + } + else if(a[i] > pivot){ high.push_back(a[i]); + } } int k = int(low.size()); - if(idx < k) + if(idx < k){ return median_of_medians(low, idx); - else if(idx > k) + } + else if(idx > k){ return median_of_medians(high, idx-k-1); - else + } + else{ return pivot; + } } /* Main function*/ int main() { - int n; - cout << "Enter Size of Array: "; - cin >> n; - vector a(n); - cout << "Enter Array: "; - for(int i = 0; i < n; i++) - cin >> a[i]; - - cout << "Median: "; + int n = 0; + std::cout << "Enter Size of Array: "; + std::cin >> n; + std::vector a(n); + std::cout << "Enter Array: "; + for(int i = 0; i < n; i++){ + std::cin >> a[i]; + } + std::cout << "Median: "; // Median defination: https://en.wikipedia.org/wiki/Median int x = median_of_medians(a, (n - 1) / 2); if(n % 2 == 0){ int y = median_of_medians(a, n / 2); - cout << (float(x) + float(y))/2.0; + std::cout << (float(x) + float(y))/2.0; } - else - cout << x; - - cout << "\nTo find i-th smallest element "; - cout << "\nEnter i: "; - int idx; - cin >> idx; + else{ + std::cout << x; + } + std::cout << "\nTo find i-th smallest element "; + std::cout << "\nEnter i: "; + int idx = 0; + std::cin >> idx; idx--; - cout << "i-th smallest element: " << median_of_medians(a, idx) << endl; + std::cout << idx + 1<< "-th smallest element: " << median_of_medians(a, idx) << '\n'; return 0; } From 406ad387db413690247cc77ba6ba6d34cac186c6 Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Fri, 21 Aug 2020 12:08:06 +0530 Subject: [PATCH 03/10] Suggested changes has been made. --- search/median_search.cpp | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index c67ad170b..4ef73ac08 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -1,14 +1,20 @@ -/** - * \file - * \brief [Median search](https://en.wikipedia.org/wiki/Median_search) algorithm - * cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) - * \ingroup median search - */ +// Given an array A[1,...,n] of n numbers and an index idx, idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. #include #include #include +/** + * @namespace search + * @brief Search algorithms + */ +namespace search { +/** + * @namespace median_search + * @brief Functions for [Median search](https://en.wikipedia.org/wiki/Median_search) algorithm + * @cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) + */ +namespace median_search { /* Assume that all the elements of A are distinct def median_of_medians(A, i): @@ -43,8 +49,8 @@ * print median_of_medians(B,4) #should be 5 */ -int median_of_medians(std::vector a, int idx){ - int pivot = 0; // initialized with zero +int median_of_medians(std::vector a, int idx){ // Search the element in **a** whose index is **idx** and return element at index **idx** in **a** (a[idx]) + int pivot = 0; // initialized with zero std::vector m; int r = a.size(); for(int i = 0; i < r; i += 5){ @@ -81,9 +87,12 @@ int median_of_medians(std::vector a, int idx){ return pivot; } } +} // namespace median_search +} // namespace search -/* Main function*/ - +/** + * Main function + */ int main() { int n = 0; @@ -95,9 +104,9 @@ int main() std::cin >> a[i]; } std::cout << "Median: "; // Median defination: https://en.wikipedia.org/wiki/Median - int x = median_of_medians(a, (n - 1) / 2); + int x = search::median_search::median_of_medians(a, (n - 1) / 2); if(n % 2 == 0){ - int y = median_of_medians(a, n / 2); + int y = search::median_search::median_of_medians(a, n / 2); std::cout << (float(x) + float(y))/2.0; } else{ @@ -108,7 +117,7 @@ int main() int idx = 0; std::cin >> idx; idx--; - std::cout << idx + 1<< "-th smallest element: " << median_of_medians(a, idx) << '\n'; + std::cout << idx + 1<< "-th smallest element: " << search::median_search::median_of_medians(a, idx) << '\n'; return 0; } From b631eee388da277a66e781dd8e8bb9ebcb2f1d75 Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Fri, 21 Aug 2020 23:47:07 +0530 Subject: [PATCH 04/10] added a comment block like in #962. --- search/median_search.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index 4ef73ac08..0488a5188 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -1,5 +1,14 @@ -// Given an array A[1,...,n] of n numbers and an index idx, idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. - +/** + * @file median_search.cpp + * @brief Implementation of [Median search](https://en.wikipedia.org/wiki/Median_search) algorithm. + * @cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) + * + * @details + * Given an array A[1,...,n] of n numbers and an index idx, idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. + * \note this algorithm implements median search for only arrays which have distinct elements + * + * @author [Sushil Kumar](https://github.com/Rp-sushil) + */ #include #include #include @@ -12,7 +21,6 @@ namespace search { /** * @namespace median_search * @brief Functions for [Median search](https://en.wikipedia.org/wiki/Median_search) algorithm - * @cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) */ namespace median_search { /* Assume that all the elements of A are distinct From caed3ddadd2e2ff8d3a43062aab27a68efd6294b Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Sat, 22 Aug 2020 01:53:54 +0530 Subject: [PATCH 05/10] Changed has been made (#962 as a reference) --- search/median_search.cpp | 77 ++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index 0488a5188..28f74b17a 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -1,14 +1,43 @@ /** * @file median_search.cpp - * @brief Implementation of [Median search](https://en.wikipedia.org/wiki/Median_search) algorithm. + * @brief Implementation of [Median search](https://en.wikipedia.org/wiki/Median_of_medians) algorithm. * @cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) * * @details - * Given an array A[1,...,n] of n numbers and an index idx, idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. + * Given an array A[1,...,n] of n numbers and an index idx, idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. + * median_of_medians(A, i): + * #divide A into sublists of len 5 + * sublists = [A[j:j+5] for j in range(0, len(A), 5)] + * medians = [sorted(sublist)[len(sublist)/2] for sublist in sublists] + * if len(medians) <= 5: + * pivot = sorted(medians)[len(medians)/2] + * else: + * #the pivot is the median of the medians + * pivot = median_of_medians(medians, len(medians)/2) + * #partitioning step + * low = [j for j in A if j < pivot] + * high = [j for j in A if j > pivot] + * k = len(low) + * if i < k: + * return median_of_medians(low,i) + * elif i > k: + * return median_of_medians(high,i-k-1) + * else: #pivot = k + * return pivot + * * \note this algorithm implements median search for only arrays which have distinct elements - * + * + * Here are some example lists you can use to see how the algorithm works + * A = [1,2,3,4,5,1000,8,9,99] (Contain Unique Elements) + * B = [1,2,3,4,5,6] (Contains Unique Elements) + * print median_of_medians(A, 0) #should be 1 + * print median_of_medians(A,7) #should be 99 + * print median_of_medians(B,4) #should be 5 + * + * @author Unknown author * @author [Sushil Kumar](https://github.com/Rp-sushil) */ + #include #include #include @@ -23,42 +52,14 @@ namespace search { * @brief Functions for [Median search](https://en.wikipedia.org/wiki/Median_search) algorithm */ namespace median_search { -/* Assume that all the elements of A are distinct - def median_of_medians(A, i): - - #divide A into sublists of len 5 - sublists = [A[j:j+5] for j in range(0, len(A), 5)] - medians = [sorted(sublist)[len(sublist)/2] for sublist in sublists] - if len(medians) <= 5: - pivot = sorted(medians)[len(medians)/2] - else: - #the pivot is the median of the medians - pivot = median_of_medians(medians, len(medians)/2) - - #partitioning step - low = [j for j in A if j < pivot] - high = [j for j in A if j > pivot] - - k = len(low) - if i < k: - return median_of_medians(low,i) - elif i > k: - return median_of_medians(high,i-k-1) - else: #pivot = k - return pivot -*/ - -/* - * Here are some example lists you can use to see how the algorithm works - * A = [1,2,3,4,5,1000,8,9,99] (Contain Unique Elements) - * B = [1,2,3,4,5,6] (Contains Unique Elements) - * print median_of_medians(A, 0) #should be 1 - * print median_of_medians(A,7) #should be 99 - * print median_of_medians(B,4) #should be 5 -*/ - -int median_of_medians(std::vector a, int idx){ // Search the element in **a** whose index is **idx** and return element at index **idx** in **a** (a[idx]) +/** +* This function Search the element in **a** whose index is **idx** and return element at index **idx** in **a** (a[idx]) +* @param A(list) and idx(index) of element which we want to search +* @return corresponding element which we want to search. +*/ +int median_of_medians(const std::vector& A, const int& idx) { int pivot = 0; // initialized with zero + std::vector a(A.begin(), A.end()); std::vector m; int r = a.size(); for(int i = 0; i < r; i += 5){ From 498db114f3e053dc215ca8871ca5d8b9ca49a0b3 Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Sat, 22 Aug 2020 02:22:47 +0530 Subject: [PATCH 06/10] updated median_search (#962 as reference) --- search/median_search.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index 28f74b17a..3cf1ea994 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -53,8 +53,9 @@ namespace search { */ namespace median_search { /** -* This function Search the element in **a** whose index is **idx** and return element at index **idx** in **a** (a[idx]) -* @param A(list) and idx(index) of element which we want to search +* This function search the element in an array for the given index. +* @param A an array +* @param idx the index * @return corresponding element which we want to search. */ int median_of_medians(const std::vector& A, const int& idx) { From 306de24e703f6fba5366d4dcf96f08a3211a09ad Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Sat, 22 Aug 2020 02:39:13 +0530 Subject: [PATCH 07/10] Suggested changes has been made. --- search/median_search.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index 3cf1ea994..f252e8430 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -54,9 +54,9 @@ namespace search { namespace median_search { /** * This function search the element in an array for the given index. -* @param A an array -* @param idx the index -* @return corresponding element which we want to search. +* @param A array where numbers are saved +* @param idx current index in array +* @returns corresponding element which we want to search. */ int median_of_medians(const std::vector& A, const int& idx) { int pivot = 0; // initialized with zero From 37b252697da4638bebc26531f7859314bfbc2ba7 Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Sun, 23 Aug 2020 00:29:00 +0530 Subject: [PATCH 08/10] test added --- search/median_search.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index f252e8430..08cb676c9 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -4,7 +4,7 @@ * @cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) * * @details - * Given an array A[1,...,n] of n numbers and an index idx, idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. + * Given an array A[1,...,n] of n numbers and an index idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. * median_of_medians(A, i): * #divide A into sublists of len 5 * sublists = [A[j:j+5] for j in range(0, len(A), 5)] @@ -41,6 +41,7 @@ #include #include #include +#include /** * @namespace search @@ -100,11 +101,33 @@ int median_of_medians(const std::vector& A, const int& idx) { } // namespace median_search } // namespace search +/** + * Function to test above algorithm + */ +void test(){ + std::vector A{25,21,98,100,76,22,43,60,89,87}; + int i = 3; + assert(A[6] == search::median_search::median_of_medians(A, i)); // A[6] = 43, is the fourth smallest element. + std::cout << "test case:1 passed\n"; + + std::vector B{1,2,3,4,5,6}; + int j = 4; + assert(B[4] == search::median_search::median_of_medians(B, j)); // B[4] = 5, is the fifth smallest element. + std::cout << "test case:2 passed\n"; + + std::vector C{1,2,3,4,5,1000,8,9,99}; + int k = 3; + assert(C[3] == search::median_search::median_of_medians(C, k)); // C[3] = 4, is the fourth smallest element. + std::cout << "test case:3 passed\n"; + std::cout << "--All tests passed--\n"; +} + /** * Main function */ int main() { + test(); int n = 0; std::cout << "Enter Size of Array: "; std::cin >> n; From a1242904e1faad3c4391244477dd428f4f6b3f72 Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Sun, 23 Aug 2020 00:37:46 +0530 Subject: [PATCH 09/10] repeated constraints removed. --- search/median_search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index 08cb676c9..c20bcfeaa 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -4,7 +4,7 @@ * @cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) * * @details - * Given an array A[1,...,n] of n numbers and an index idx, where 1≤idx≤ n, 1≤idx≤ n, find the i-th smallest element of A. + * Given an array A[1,...,n] of n numbers and an index idx, where 1≤idx≤ n, find the i-th smallest element of A. * median_of_medians(A, i): * #divide A into sublists of len 5 * sublists = [A[j:j+5] for j in range(0, len(A), 5)] From b50591dfcedd55ed86ba7c119a1da3ff986305de Mon Sep 17 00:00:00 2001 From: Sushil Kumar Date: Sun, 23 Aug 2020 15:49:52 +0530 Subject: [PATCH 10/10] Suggested changes has been made. --- search/median_search.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/search/median_search.cpp b/search/median_search.cpp index c20bcfeaa..479de8107 100644 --- a/search/median_search.cpp +++ b/search/median_search.cpp @@ -4,7 +4,7 @@ * @cases from [here](https://brilliant.org/wiki/median-finding-algorithm/) * * @details - * Given an array A[1,...,n] of n numbers and an index idx, where 1≤idx≤ n, find the i-th smallest element of A. + * Given an array A[1,...,n] of n numbers and an index i, where 1 ≤ i ≤ n, find the i-th smallest element of A. * median_of_medians(A, i): * #divide A into sublists of len 5 * sublists = [A[j:j+5] for j in range(0, len(A), 5)] @@ -107,12 +107,12 @@ int median_of_medians(const std::vector& A, const int& idx) { void test(){ std::vector A{25,21,98,100,76,22,43,60,89,87}; int i = 3; - assert(A[6] == search::median_search::median_of_medians(A, i)); // A[6] = 43, is the fourth smallest element. + assert(A[6] == search::median_search::median_of_medians(A, i)); // A[6] = 43, is the fourth smallest element. std::cout << "test case:1 passed\n"; std::vector B{1,2,3,4,5,6}; int j = 4; - assert(B[4] == search::median_search::median_of_medians(B, j)); // B[4] = 5, is the fifth smallest element. + assert(B[4] == search::median_search::median_of_medians(B, j)); // B[4] = 5, is the fifth smallest element. std::cout << "test case:2 passed\n"; std::vector C{1,2,3,4,5,1000,8,9,99};