From d11e8cb40a11415ac82888033977d23d52b3c8b5 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 13:30:42 +0400 Subject: [PATCH 01/67] added skip_list.cpp --- data_structures/skip_list.cpp | 185 ++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 data_structures/skip_list.cpp diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp new file mode 100644 index 000000000..8b6ec1f70 --- /dev/null +++ b/data_structures/skip_list.cpp @@ -0,0 +1,185 @@ +/** + * A skip list is a data structure that is used for storing a sorted list of items with a + * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items + * + * References used: GeeksForGeeks, https://iq.opengenus.org/skip-list/ Pseudo Code, https://ideone.com/XnXIFl from CodeForces. +*/ + +#include +#include +#include +#include +using namespace std; + +#define MAXLVL 2 +#define P 0.5 + + +/** + * Node structure [Key][Node*, Node*...] +*/ +class Node { +public: + int key; + void* value; + /*Forward Array*/ + vector forward; + Node(int key, int level, void* value); +}; + + +Node::Node(int key, int level, void* value) { + this->key = key; + + /*Initialization of forward vector*/ + for (int i = 0; i < sizeof(Node*)*(level+1); i++){ + forward.push_back(NULL); + } +}; + +// Class for Skip list +class SkipList { + int level; + Node *header; +public: + SkipList(); + int randomLevel(); + void insertElement(int, void*); + void deleteElement(int); + void* searchElement(int); + void displayList(); +}; + +SkipList::SkipList() { + level = 0; + /* Header initialization*/ + header = new Node(-1, MAXLVL, NULL); +}; + + +/** + * Returns random level for skip list; +*/ +int SkipList::randomLevel() { + int lvl = 0; + while(rand()%2 < P && lvl < MAXLVL) lvl++; + return lvl; +}; + + +// Insert given key in skip list +void SkipList::insertElement(int key, void* value) { + printf("Inserting %d key ... ", key); + Node *x = header; + Node *update[MAXLVL+1]; + memset(update, 0, sizeof(Node*)*(MAXLVL+1)); + + + for(int i = level; i >= 0; i--) { + while(x->forward[i] != NULL && x->forward[i]->key < key) x = x->forward[i]; + update[i] = x; + } + + x = x->forward[0]; + + bool doesnt_exist = (x == NULL || x->key != key); + if (doesnt_exist) { + int rlevel = randomLevel(); + + if(rlevel > level) { + for(int i=level+1;iforward[i] = update[i]->forward[i]; + update[i]->forward[i] = n; + } + printf(" Inserted\n"); + } else { + printf("Exists\n"); + } +}; + +// Delete element from skip list +void SkipList::deleteElement(int key) +{ + Node *x = header; + + Node *update[MAXLVL+1]; + memset(update, 0, sizeof(Node*)*(MAXLVL+1)); + + for(int i = level; i >= 0; i--) { + while(x->forward[i] != NULL && x->forward[i]->key < key) x = x->forward[i]; + update[i] = x; + } + + x = x->forward[0]; + + bool doesnt_exist = (x == NULL || x->key != key); + + if(!doesnt_exist) { + for(int i=0;i<=level;i++) { + if(update[i]->forward[i] != x) break; + update[i]->forward[i] = x->forward[i]; + } + /*Remove empty levels*/ + while(level>0 && header->forward[level] == 0) level--; + printf("Deleted\n"); + } else { + printf("Doesnt Exists\n"); + } +}; + + +/** + * Searching element in skip list structure +*/ +void* SkipList::searchElement(int key) { + Node *x = header; + printf("Searching for %d\n", key); + + for(int i = level; i >= 0; i--) { + while(x->forward[i] && x->forward[i]->key < key) x = x->forward[i]; + } + + x = x->forward[0]; + if(x && x->key == key){ + printf("FOUND\n"); + return x->value; + } else { + printf("NOT FOUND\n"); + return NULL; + } +}; + +// Display skip list level wise +void SkipList::displayList() { + printf("----SKIP LIST STRUCTURE----\n"); + for(int i=0; i <= level; i++) { + Node *node = header->forward[i]; + printf("Level %d: ", i); + while(node != NULL) { + printf("%d ", node->key); + node = node->forward[i]; + } + printf("\n"); + } +}; + +int main() +{ + srand((unsigned)time(0)); + + SkipList lst; + + for (int j = 0; j < (1 << (MAXLVL+1)); j++){ + int k = (rand() % (1 << (MAXLVL+1) + 1)); + lst.insertElement(k, &j); + } + + lst.displayList(); +} \ No newline at end of file From ec04afc54fccb6ff4c2f5fe32833e0116ac174b3 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 13:34:13 +0400 Subject: [PATCH 02/67] added skip-list --- data_structures/skip_list.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 8b6ec1f70..31e6d06f4 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -2,7 +2,7 @@ * A skip list is a data structure that is used for storing a sorted list of items with a * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * - * References used: GeeksForGeeks, https://iq.opengenus.org/skip-list/ Pseudo Code, https://ideone.com/XnXIFl from CodeForces. + * References used: GeeksForGeeks skip list code, https://iq.opengenus.org/skip-list/ Pseudo Code. */ #include @@ -104,7 +104,7 @@ void SkipList::insertElement(int key, void* value) { } }; -// Delete element from skip list + void SkipList::deleteElement(int key) { Node *x = header; From 94338f527bcd26191ed9136722cb7fba985c4233 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 13:43:27 +0400 Subject: [PATCH 03/67] skip_list --- data_structures/skip_list.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 31e6d06f4..603d1f2c3 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -9,10 +9,12 @@ #include #include #include -using namespace std; #define MAXLVL 2 #define P 0.5 + +using std::endl; +using std::vector; /** From 2c6b8c3bf74d2875def9d296e8bac7adcf45ecbe Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 13:46:52 +0400 Subject: [PATCH 04/67] skip_list --- data_structures/skip_list.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 603d1f2c3..bae1a7bbe 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -27,7 +27,7 @@ public: /*Forward Array*/ vector forward; Node(int key, int level, void* value); -}; +} Node::Node(int key, int level, void* value) { @@ -37,7 +37,7 @@ Node::Node(int key, int level, void* value) { for (int i = 0; i < sizeof(Node*)*(level+1); i++){ forward.push_back(NULL); } -}; +} // Class for Skip list class SkipList { @@ -50,14 +50,13 @@ public: void deleteElement(int); void* searchElement(int); void displayList(); -}; +} SkipList::SkipList() { level = 0; /* Header initialization*/ header = new Node(-1, MAXLVL, NULL); -}; - +} /** * Returns random level for skip list; @@ -66,7 +65,7 @@ int SkipList::randomLevel() { int lvl = 0; while(rand()%2 < P && lvl < MAXLVL) lvl++; return lvl; -}; +} // Insert given key in skip list @@ -104,8 +103,7 @@ void SkipList::insertElement(int key, void* value) { } else { printf("Exists\n"); } -}; - +} void SkipList::deleteElement(int key) { @@ -134,7 +132,7 @@ void SkipList::deleteElement(int key) } else { printf("Doesnt Exists\n"); } -}; +} /** @@ -156,7 +154,7 @@ void* SkipList::searchElement(int key) { printf("NOT FOUND\n"); return NULL; } -}; +} // Display skip list level wise void SkipList::displayList() { @@ -170,10 +168,9 @@ void SkipList::displayList() { } printf("\n"); } -}; +} -int main() -{ +int main() { srand((unsigned)time(0)); SkipList lst; @@ -184,4 +181,5 @@ int main() } lst.displayList(); + return 0; } \ No newline at end of file From f13964cab2546754e08e61eda061a260473eb7e5 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 14:04:44 +0400 Subject: [PATCH 05/67] skip-list --- data_structures/skip_list.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index bae1a7bbe..19fdc6276 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -9,12 +9,12 @@ #include #include #include +// using namespace std; +using std::vector; +using std::endl; #define MAXLVL 2 #define P 0.5 - -using std::endl; -using std::vector; /** @@ -27,7 +27,7 @@ public: /*Forward Array*/ vector forward; Node(int key, int level, void* value); -} +}; Node::Node(int key, int level, void* value) { @@ -37,7 +37,7 @@ Node::Node(int key, int level, void* value) { for (int i = 0; i < sizeof(Node*)*(level+1); i++){ forward.push_back(NULL); } -} +}; // Class for Skip list class SkipList { @@ -50,13 +50,14 @@ public: void deleteElement(int); void* searchElement(int); void displayList(); -} +}; SkipList::SkipList() { level = 0; /* Header initialization*/ header = new Node(-1, MAXLVL, NULL); -} +}; + /** * Returns random level for skip list; @@ -65,7 +66,7 @@ int SkipList::randomLevel() { int lvl = 0; while(rand()%2 < P && lvl < MAXLVL) lvl++; return lvl; -} +}; // Insert given key in skip list @@ -103,7 +104,8 @@ void SkipList::insertElement(int key, void* value) { } else { printf("Exists\n"); } -} +}; + void SkipList::deleteElement(int key) { @@ -132,7 +134,7 @@ void SkipList::deleteElement(int key) } else { printf("Doesnt Exists\n"); } -} +}; /** @@ -154,7 +156,7 @@ void* SkipList::searchElement(int key) { printf("NOT FOUND\n"); return NULL; } -} +}; // Display skip list level wise void SkipList::displayList() { @@ -168,9 +170,10 @@ void SkipList::displayList() { } printf("\n"); } -} +}; -int main() { +int main() +{ srand((unsigned)time(0)); SkipList lst; @@ -181,5 +184,5 @@ int main() { } lst.displayList(); - return 0; -} \ No newline at end of file + +} From 2fb95a2bf3ba4dd411dd1123a412e28e4ae9560a Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 14:29:08 +0400 Subject: [PATCH 06/67] skip_list --- data_structures/skip_list.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 19fdc6276..723958866 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -37,7 +37,7 @@ Node::Node(int key, int level, void* value) { for (int i = 0; i < sizeof(Node*)*(level+1); i++){ forward.push_back(NULL); } -}; +} // Class for Skip list class SkipList { @@ -50,13 +50,13 @@ public: void deleteElement(int); void* searchElement(int); void displayList(); -}; +}; SkipList::SkipList() { level = 0; /* Header initialization*/ header = new Node(-1, MAXLVL, NULL); -}; +} /** @@ -64,9 +64,10 @@ SkipList::SkipList() { */ int SkipList::randomLevel() { int lvl = 0; - while(rand()%2 < P && lvl < MAXLVL) lvl++; + thread_local unsigned int seed = time(NULL); + while(rand_r(&seed)%2 < P && lvl < MAXLVL) lvl++; return lvl; -}; +} // Insert given key in skip list @@ -104,7 +105,7 @@ void SkipList::insertElement(int key, void* value) { } else { printf("Exists\n"); } -}; +} void SkipList::deleteElement(int key) @@ -134,7 +135,7 @@ void SkipList::deleteElement(int key) } else { printf("Doesnt Exists\n"); } -}; +} /** @@ -156,7 +157,7 @@ void* SkipList::searchElement(int key) { printf("NOT FOUND\n"); return NULL; } -}; +} // Display skip list level wise void SkipList::displayList() { @@ -170,16 +171,17 @@ void SkipList::displayList() { } printf("\n"); } -}; +} int main() { - srand((unsigned)time(0)); + thread_local unsigned int seed = time(NULL); + SkipList lst; for (int j = 0; j < (1 << (MAXLVL+1)); j++){ - int k = (rand() % (1 << (MAXLVL+1) + 1)); + int k = (rand_r(&seed) % (1 << (MAXLVL+1) + 1)); lst.insertElement(k, &j); } From 2c3d72b102c48b6c4329f5b89b45a546da11eeac Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 14:38:58 +0400 Subject: [PATCH 07/67] Added fibonacci search --- search/fibonacci_search.cpp | 61 +++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 search/fibonacci_search.cpp diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp new file mode 100644 index 000000000..29f10c370 --- /dev/null +++ b/search/fibonacci_search.cpp @@ -0,0 +1,61 @@ +#include +#include + +/* +Input: a sorted array and a value +Output: if the array contains the value, returns its index (index of its first occurence) + else returns -1 +*/ + +int fibonacchi_search(std::vector arr, int value){ + int last = 0, current = 1, offset = -1, index; + int length = arr.size(); + int next = last + current; + + while(next < length){ + last = current; + current = next; + next = last + current; + } + + while(next > 1){ + index = std::min(offset + last, length-1); + if(arr[index] < value){ + next = current; + current = last; + last = next - current; + offset = index; + } else if(arr[index] > value){ + next = last; + current = current - last; + last = next - current; + } else { + return index; + } + } + if(current && !arr.empty() && arr[offset+1] == value){ + return offset+1; + } + return -1; +} + +int main() { + int size, value; + std::cout << "Enter size of a sorted array: " << std::endl; + std::cin >> size; + std::cout << "Enter array elements: " << std::endl; + + std::vector arr(size); + for(int i = 0; i < size; i++){ + std::cin >> arr[i]; + } + std::cout << "Enter the value you're looking for: " << std::endl; + std::cin >> value; + int index = fibonacchi_search(arr, value); + if(index != -1){ + std::cout << "Index of the given value is " << index << std::endl; + } else { + std::cout << "Array does not contain the value" << std::endl; + } + return 0; +} From 420915fa0ddff92b6be4922f540c651136f9f6a6 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 14:48:30 +0400 Subject: [PATCH 08/67] skip_list --- data_structures/skip_list.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 723958866..550a5c9d3 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include // using namespace std; using std::vector; using std::endl; @@ -58,6 +60,8 @@ SkipList::SkipList() { header = new Node(-1, MAXLVL, NULL); } + + /** * Returns random level for skip list; @@ -187,4 +191,6 @@ int main() lst.displayList(); + + } From 910180ff214ae669eb0a9ec6a923a7d00755d746 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 14:54:44 +0400 Subject: [PATCH 09/67] skip_list --- data_structures/skip_list.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 550a5c9d3..3b4ba500f 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -11,6 +11,8 @@ #include #include #include +#include + // using namespace std; using std::vector; using std::endl; From 363f43c942879a2ee92253588896fb3c81c8780a Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 14:57:57 +0400 Subject: [PATCH 10/67] min function implemented --- search/fibonacci_search.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index 29f10c370..af3858e74 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -7,7 +7,15 @@ Output: if the array contains the value, returns its index (index of its first o else returns -1 */ -int fibonacchi_search(std::vector arr, int value){ +int min(int first, int second){ + if(first > second){ + return first; + } else { + return second; + } +} + +int fibonacci_search(std::vector arr, int value){ int last = 0, current = 1, offset = -1, index; int length = arr.size(); int next = last + current; @@ -19,7 +27,7 @@ int fibonacchi_search(std::vector arr, int value){ } while(next > 1){ - index = std::min(offset + last, length-1); + index = min(offset + last, length-1); if(arr[index] < value){ next = current; current = last; @@ -51,7 +59,7 @@ int main() { } std::cout << "Enter the value you're looking for: " << std::endl; std::cin >> value; - int index = fibonacchi_search(arr, value); + int index = fibonacci_search(arr, value); if(index != -1){ std::cout << "Index of the given value is " << index << std::endl; } else { From 1002126449a0599630df669397aa49a1586e3e90 Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 15:05:07 +0400 Subject: [PATCH 11/67] min function corrected --- search/fibonacci_search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index af3858e74..0bf33c494 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -8,7 +8,7 @@ Output: if the array contains the value, returns its index (index of its first o */ int min(int first, int second){ - if(first > second){ + if(first < second){ return first; } else { return second; From 8e99383dbf8f373fc7a99fd2db8187f3f88441f4 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 15:13:01 +0400 Subject: [PATCH 12/67] skip_list --- data_structures/skip_list.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 3b4ba500f..fe5820b43 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -70,8 +70,7 @@ SkipList::SkipList() { */ int SkipList::randomLevel() { int lvl = 0; - thread_local unsigned int seed = time(NULL); - while(rand_r(&seed)%2 < P && lvl < MAXLVL) lvl++; + while((float)rand()/RAND_MAX < P && lvl < MAXLVL) lvl++; return lvl; } @@ -181,13 +180,12 @@ void SkipList::displayList() { int main() { - thread_local unsigned int seed = time(NULL); + srand((unsigned)time(0)); - SkipList lst; for (int j = 0; j < (1 << (MAXLVL+1)); j++){ - int k = (rand_r(&seed) % (1 << (MAXLVL+1) + 1)); + int k = (rand()% (1 << (MAXLVL+1) + 1)); lst.insertElement(k, &j); } From 2fc0d5bffeaff3845fd8b3ca774b0f9f50cc2299 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 16:40:47 +0400 Subject: [PATCH 13/67] skip-list corrected --- data_structures/skip_list.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index fe5820b43..69836e13a 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -180,12 +180,12 @@ void SkipList::displayList() { int main() { - srand((unsigned)time(0)); + std::srand(time(nullptr)); SkipList lst; for (int j = 0; j < (1 << (MAXLVL+1)); j++){ - int k = (rand()% (1 << (MAXLVL+1) + 1)); + int k = (std::rand()% (1 << (MAXLVL+1) + 1)); lst.insertElement(k, &j); } From ba65d559c5912861bad589e7832becdf321bc01f Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 16:51:47 +0400 Subject: [PATCH 14/67] skip-list documentation-polish --- data_structures/skip_list.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 69836e13a..988165db3 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -70,14 +70,14 @@ SkipList::SkipList() { */ int SkipList::randomLevel() { int lvl = 0; - while((float)rand()/RAND_MAX < P && lvl < MAXLVL) lvl++; + while(static_cast(rand())/RAND_MAX < P && lvl < MAXLVL) lvl++; return lvl; } // Insert given key in skip list void SkipList::insertElement(int key, void* value) { - printf("Inserting %d key ... ", key); + std::cout << "Inserting" << key << "..."; Node *x = header; Node *update[MAXLVL+1]; memset(update, 0, sizeof(Node*)*(MAXLVL+1)); @@ -106,13 +106,14 @@ void SkipList::insertElement(int key, void* value) { n->forward[i] = update[i]->forward[i]; update[i]->forward[i] = n; } - printf(" Inserted\n"); + std::cout << "Inserted" << endl; + } else { - printf("Exists\n"); + std::cout << "Exists" << endl; } } - + /**Delete document by key*/ void SkipList::deleteElement(int key) { Node *x = header; @@ -136,9 +137,9 @@ void SkipList::deleteElement(int key) } /*Remove empty levels*/ while(level>0 && header->forward[level] == 0) level--; - printf("Deleted\n"); + std::cout << "Deleted" << endl; } else { - printf("Doesnt Exists\n"); + std::cout << "Doesn't exist" << endl; } } @@ -148,7 +149,7 @@ void SkipList::deleteElement(int key) */ void* SkipList::searchElement(int key) { Node *x = header; - printf("Searching for %d\n", key); + std::cout << "Searching for " + key << endl; for(int i = level; i >= 0; i--) { while(x->forward[i] && x->forward[i]->key < key) x = x->forward[i]; @@ -156,25 +157,25 @@ void* SkipList::searchElement(int key) { x = x->forward[0]; if(x && x->key == key){ - printf("FOUND\n"); + std::cout << "Found" << endl; return x->value; } else { - printf("NOT FOUND\n"); + std::cout << "Not Found" << endl; return NULL; } } // Display skip list level wise void SkipList::displayList() { - printf("----SKIP LIST STRUCTURE----\n"); + std::cout << "Displaying list:\n" << endl; for(int i=0; i <= level; i++) { Node *node = header->forward[i]; - printf("Level %d: ", i); + std::cout << "Level " << (i) << ": "; while(node != NULL) { - printf("%d ", node->key); + std::cout << node->key << " "; node = node->forward[i]; } - printf("\n"); + std::cout << endl; } } From 5068ddc14d093c2434edcb359fca0d3594dff86c Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 16:55:52 +0400 Subject: [PATCH 15/67] skip-list documentation-polish --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 988165db3..d2ba820f4 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -70,7 +70,7 @@ SkipList::SkipList() { */ int SkipList::randomLevel() { int lvl = 0; - while(static_cast(rand())/RAND_MAX < P && lvl < MAXLVL) lvl++; + while(static_cast(std::rand())/RAND_MAX < P && lvl < MAXLVL) lvl++; return lvl; } From dcdebae395ae9edbf40461b8a1cd31659ad20526 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 17:24:13 +0400 Subject: [PATCH 16/67] skip-list documentation-polish --- data_structures/skip_list.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index d2ba820f4..782486632 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -54,7 +54,10 @@ public: void deleteElement(int); void* searchElement(int); void displayList(); + ~SkipList(); }; + + SkipList::SkipList() { level = 0; @@ -63,6 +66,18 @@ SkipList::SkipList() { } +SkipList::~SkipList(){ + delete header; + for(int i=0; i <= level; i++) { + Node *node = header->forward[i]; + Node* temp; + while(node != NULL) { + temp = node; + node = node->forward[i]; + delete temp; + } + } +} /** From 86c6af46e865d78e9a41256414690ded7916efb3 Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 17:27:45 +0400 Subject: [PATCH 17/67] doxygen documentation and tests added --- search/fibonacci_search.cpp | 140 +++++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 24 deletions(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index 0bf33c494..2a3ba7207 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -1,12 +1,19 @@ +/** + * Copyright 2020 @author sprintyaf + * @file + * @brief [Fibonacci search + * algorithm](https://en.wikipedia.org/wiki/Fibonacci_search_technique) + */ + #include -#include +#include // for std::vector class +#include // for assert -/* -Input: a sorted array and a value -Output: if the array contains the value, returns its index (index of its first occurence) - else returns -1 -*/ + +/** + * Returns minimum of the two numbers + */ int min(int first, int second){ if(first < second){ return first; @@ -15,7 +22,12 @@ int min(int first, int second){ } } -int fibonacci_search(std::vector arr, int value){ +/** + * Input: a sorted array and a value + * Output: if the array contains the value, returns its index + * else returns -1 + */ +int fibonacci_search(std::vector &arr, int value){ int last = 0, current = 1, offset = -1, index; int length = arr.size(); int next = last + current; @@ -47,23 +59,103 @@ int fibonacci_search(std::vector arr, int value){ return -1; } -int main() { - int size, value; - std::cout << "Enter size of a sorted array: " << std::endl; - std::cin >> size; - std::cout << "Enter array elements: " << std::endl; +/** + * Tests where given value occurs only once + */ +bool one_occurence_test(){ + // declarations + int value, index; + bool passed = true; + std::vector arr; + // last element + arr = {1, 2, 3}; + value = 3; + index = fibonacci_search(arr, value); + passed = passed && (index == 2); + // first element + value = 1; + index = fibonacci_search(arr, value); + passed = passed && (index == 0); + // somewhere in the middle element + arr = {1, 3, 5, 7}; + value = 3; + index = fibonacci_search(arr, value); + passed = passed && (index == 1); + // arr size is 1 + arr = {10}; + value = 10; + index = fibonacci_search(arr, value); + passed = passed && (index == 0); - std::vector arr(size); - for(int i = 0; i < size; i++){ - std::cin >> arr[i]; - } - std::cout << "Enter the value you're looking for: " << std::endl; - std::cin >> value; - int index = fibonacci_search(arr, value); - if(index != -1){ - std::cout << "Index of the given value is " << index << std::endl; - } else { - std::cout << "Array does not contain the value" << std::endl; - } + return passed; +} + +/** + * Tests where given value occurs more than once + */ +bool many_occurence_test(){ + // declarations + int value, index; + bool passed = true; + std::vector arr; + // last element + arr = {1, 1, 10, 10}; + value = 10; + index = fibonacci_search(arr, value); + passed = passed && (index == 2 || index == 3); + // first element + value = 1; + index = fibonacci_search(arr, value); + passed = passed && (index == 0 || index == 1); + // somewhere in the middle element + arr = {1, 3, 3, 7}; + value = 3; + index = fibonacci_search(arr, value); + passed = passed && (index == 1 || index == 2); + // all elements are the same + arr = {10, 10, 10}; + value = 10; + index = fibonacci_search(arr, value); + passed = passed && (index >= 0 && index <= 2); + + return passed; +} + +/** + * Tests where the array doesn't contain given value + */ +bool no_occurence_test(){ + // declarations + int value, index; + bool passed = true; + std::vector arr; + // many elements + arr = {1, 2, 4, 5}; + value = 3; + index = fibonacci_search(arr, value); + passed = passed && (index == -1); + // one element + arr = {1}; + value = 2; + index = fibonacci_search(arr, value); + passed = passed && (index == -1); + // empty array + arr.clear(); + value = 10; + index = fibonacci_search(arr, value); + passed = passed && (index == -1); + + return passed; +} + + +/** + * Main Function + * testing the algorithm + */ +int main() { + assert(one_occurence_test()); + assert(many_occurence_test()); + assert(no_occurence_test()); return 0; } From 8e53f4da833c4e5410a74e26dce8b15cb46b41a0 Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 17:54:55 +0400 Subject: [PATCH 18/67] converted from vector to array --- search/fibonacci_search.cpp | 65 ++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index 2a3ba7207..5cdc93ae9 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -23,13 +23,12 @@ int min(int first, int second){ } /** - * Input: a sorted array and a value + * Input: a sorted array, a value we're looking for and size of the array * Output: if the array contains the value, returns its index * else returns -1 */ -int fibonacci_search(std::vector &arr, int value){ +int fibonacci_search(int *arr, int value, int length){ int last = 0, current = 1, offset = -1, index; - int length = arr.size(); int next = last + current; while(next < length){ @@ -53,7 +52,7 @@ int fibonacci_search(std::vector &arr, int value){ return index; } } - if(current && !arr.empty() && arr[offset+1] == value){ + if(current && (length > 0) && arr[offset+1] == value){ return offset+1; } return -1; @@ -64,27 +63,29 @@ int fibonacci_search(std::vector &arr, int value){ */ bool one_occurence_test(){ // declarations - int value, index; + int value, index, length; bool passed = true; - std::vector arr; // last element - arr = {1, 2, 3}; + length = 3; + int arr1[length] = {1, 2, 3}; value = 3; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr1, value, length); passed = passed && (index == 2); // first element value = 1; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr1, value, length); passed = passed && (index == 0); // somewhere in the middle element - arr = {1, 3, 5, 7}; + length = 4; + int arr2[length] = {1, 3, 5, 7}; value = 3; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr2, value, length); passed = passed && (index == 1); // arr size is 1 - arr = {10}; + length = 1; + int arr3[length] = {10}; value = 10; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr3, value, length); passed = passed && (index == 0); return passed; @@ -95,27 +96,29 @@ bool one_occurence_test(){ */ bool many_occurence_test(){ // declarations - int value, index; + int value, index, length; bool passed = true; - std::vector arr; // last element - arr = {1, 1, 10, 10}; + length = 4; + int arr1[length] = {1, 1, 10, 10}; value = 10; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr1, value, length); passed = passed && (index == 2 || index == 3); // first element value = 1; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr1, value, length); passed = passed && (index == 0 || index == 1); // somewhere in the middle element - arr = {1, 3, 3, 7}; + length = 4; + int arr2[length] = {1, 3, 3, 7}; value = 3; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr2, value, length); passed = passed && (index == 1 || index == 2); // all elements are the same - arr = {10, 10, 10}; + length = 3; + int arr3[length] = {10, 10, 10}; value = 10; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr3, value, length); passed = passed && (index >= 0 && index <= 2); return passed; @@ -126,23 +129,25 @@ bool many_occurence_test(){ */ bool no_occurence_test(){ // declarations - int value, index; + int value, index, length; bool passed = true; - std::vector arr; // many elements - arr = {1, 2, 4, 5}; + length = 4; + int arr1[length] = {1, 2, 4, 5}; value = 3; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr1, value, length); passed = passed && (index == -1); // one element - arr = {1}; + length = 1; + int arr2[length] = {1}; value = 2; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr2, value, length); passed = passed && (index == -1); // empty array - arr.clear(); + length = 0; + int arr3[length]; value = 10; - index = fibonacci_search(arr, value); + index = fibonacci_search(arr3, value, length); passed = passed && (index == -1); return passed; From 4b3749ed49d863bbfd2090c56151586962c7b78d Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 17:59:49 +0400 Subject: [PATCH 19/67] variable-length arrays fixed --- search/fibonacci_search.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index 5cdc93ae9..f8525a6b4 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -67,7 +67,7 @@ bool one_occurence_test(){ bool passed = true; // last element length = 3; - int arr1[length] = {1, 2, 3}; + int arr1[3] = {1, 2, 3}; value = 3; index = fibonacci_search(arr1, value, length); passed = passed && (index == 2); @@ -77,13 +77,13 @@ bool one_occurence_test(){ passed = passed && (index == 0); // somewhere in the middle element length = 4; - int arr2[length] = {1, 3, 5, 7}; + int arr2[4] = {1, 3, 5, 7}; value = 3; index = fibonacci_search(arr2, value, length); passed = passed && (index == 1); // arr size is 1 length = 1; - int arr3[length] = {10}; + int arr3[1] = {10}; value = 10; index = fibonacci_search(arr3, value, length); passed = passed && (index == 0); @@ -100,7 +100,7 @@ bool many_occurence_test(){ bool passed = true; // last element length = 4; - int arr1[length] = {1, 1, 10, 10}; + int arr1[4] = {1, 1, 10, 10}; value = 10; index = fibonacci_search(arr1, value, length); passed = passed && (index == 2 || index == 3); @@ -110,13 +110,13 @@ bool many_occurence_test(){ passed = passed && (index == 0 || index == 1); // somewhere in the middle element length = 4; - int arr2[length] = {1, 3, 3, 7}; + int arr2[4] = {1, 3, 3, 7}; value = 3; index = fibonacci_search(arr2, value, length); passed = passed && (index == 1 || index == 2); // all elements are the same length = 3; - int arr3[length] = {10, 10, 10}; + int arr3[3] = {10, 10, 10}; value = 10; index = fibonacci_search(arr3, value, length); passed = passed && (index >= 0 && index <= 2); @@ -133,19 +133,19 @@ bool no_occurence_test(){ bool passed = true; // many elements length = 4; - int arr1[length] = {1, 2, 4, 5}; + int arr1[4] = {1, 2, 4, 5}; value = 3; index = fibonacci_search(arr1, value, length); passed = passed && (index == -1); // one element length = 1; - int arr2[length] = {1}; + int arr2[1] = {1}; value = 2; index = fibonacci_search(arr2, value, length); passed = passed && (index == -1); // empty array length = 0; - int arr3[length]; + int arr3[10] = {}; value = 10; index = fibonacci_search(arr3, value, length); passed = passed && (index == -1); From f7ab869d90db9666592980e87ce3465f76de2aaf Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 18:16:38 +0400 Subject: [PATCH 20/67] skip list update --- data_structures/skip_list.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 782486632..480e9dedf 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -7,25 +7,22 @@ #include #include -#include #include #include #include -#include // using namespace std; using std::vector; using std::endl; -#define MAXLVL 2 -#define P 0.5 +#define MAXLVL 2 ///< maximum level of skip list +#define P 0.5 ///< current probability for "coin toss" /** * Node structure [Key][Node*, Node*...] */ -class Node { -public: +struct Node { int key; void* value; /*Forward Array*/ @@ -38,7 +35,7 @@ Node::Node(int key, int level, void* value) { this->key = key; /*Initialization of forward vector*/ - for (int i = 0; i < sizeof(Node*)*(level+1); i++){ + for (int i = 0; i < (level+1); i++){ forward.push_back(NULL); } } @@ -67,7 +64,6 @@ SkipList::SkipList() { SkipList::~SkipList(){ - delete header; for(int i=0; i <= level; i++) { Node *node = header->forward[i]; Node* temp; @@ -77,6 +73,7 @@ SkipList::~SkipList(){ delete temp; } } + delete header; } @@ -201,12 +198,10 @@ int main() SkipList lst; for (int j = 0; j < (1 << (MAXLVL+1)); j++){ - int k = (std::rand()% (1 << (MAXLVL+1) + 1)); + int k = (std::rand()%( 1 << (MAXLVL+2)) + 1); lst.insertElement(k, &j); } lst.displayList(); - - } From fd8affb59d86b90f244adcd3ccb49dc2b1acf09a Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 18:20:21 +0400 Subject: [PATCH 21/67] skip_list --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 480e9dedf..9d829349e 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include // using namespace std; using std::vector; From 4cebe7c68270e5474e1b0a3c65355157a741b23b Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 18:21:12 +0400 Subject: [PATCH 22/67] skip_list --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 9d829349e..180d9c32d 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -193,7 +193,7 @@ void SkipList::displayList() { int main() { - std::srand(time(nullptr)); + std::srand(std::time(nullptr)); SkipList lst; From ac0d11977d0b8fcc3396855bed490bfc690b2ad4 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 19:17:37 +0400 Subject: [PATCH 23/67] skip_list --- data_structures/skip_list.cpp | 66 ++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 180d9c32d..c41d3c2e1 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -2,7 +2,7 @@ * A skip list is a data structure that is used for storing a sorted list of items with a * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * - * References used: GeeksForGeeks skip list code, https://iq.opengenus.org/skip-list/ Pseudo Code. + * References used: GeeksForGeeks skip list code, https://iq.opengenus.org/skip-list/ Code and PseudoCode. */ #include @@ -15,28 +15,31 @@ using std::vector; using std::endl; -#define MAXLVL 2 ///< maximum level of skip list -#define P 0.5 ///< current probability for "coin toss" +#define MAX_LEVEL 2 ///< maximum level of skip list +#define PROBABILITY 0.5 ///< current probability for "coin toss" /** * Node structure [Key][Node*, Node*...] */ struct Node { - int key; + int key; + /* pointer of value */ void* value; /*Forward Array*/ vector forward; Node(int key, int level, void* value); }; - +/** + * Creates node with provided key, level and value; +*/ Node::Node(int key, int level, void* value) { this->key = key; /*Initialization of forward vector*/ for (int i = 0; i < (level+1); i++){ - forward.push_back(NULL); + forward.push_back(nullptr); } } @@ -55,11 +58,13 @@ public: }; - +/**\ + * Skeep List constructor; +*/ SkipList::SkipList() { level = 0; /* Header initialization*/ - header = new Node(-1, MAXLVL, NULL); + header = new Node(-1, MAX_LEVEL, nullptr); } @@ -67,7 +72,7 @@ SkipList::~SkipList(){ for(int i=0; i <= level; i++) { Node *node = header->forward[i]; Node* temp; - while(node != NULL) { + while(node != nullptr) { temp = node; node = node->forward[i]; delete temp; @@ -82,27 +87,31 @@ SkipList::~SkipList(){ */ int SkipList::randomLevel() { int lvl = 0; - while(static_cast(std::rand())/RAND_MAX < P && lvl < MAXLVL) lvl++; + while(static_cast(std::rand())/RAND_MAX < PROBABILITY && lvl < MAX_LEVEL) lvl++; return lvl; } -// Insert given key in skip list + +/** + * Inserts elements with given key and value; + * It's level is computed by randomLevel() function. +*/ void SkipList::insertElement(int key, void* value) { std::cout << "Inserting" << key << "..."; Node *x = header; - Node *update[MAXLVL+1]; - memset(update, 0, sizeof(Node*)*(MAXLVL+1)); + Node *update[MAX_LEVEL+1]; + memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); for(int i = level; i >= 0; i--) { - while(x->forward[i] != NULL && x->forward[i]->key < key) x = x->forward[i]; + while(x->forward[i] != nullptr && x->forward[i]->key < key) x = x->forward[i]; update[i] = x; } x = x->forward[0]; - bool doesnt_exist = (x == NULL || x->key != key); + bool doesnt_exist = (x == nullptr || x->key != key); if (doesnt_exist) { int rlevel = randomLevel(); @@ -130,17 +139,17 @@ void SkipList::deleteElement(int key) { Node *x = header; - Node *update[MAXLVL+1]; - memset(update, 0, sizeof(Node*)*(MAXLVL+1)); + Node *update[MAX_LEVEL+1]; + memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); for(int i = level; i >= 0; i--) { - while(x->forward[i] != NULL && x->forward[i]->key < key) x = x->forward[i]; + while(x->forward[i] != nullptr && x->forward[i]->key < key) x = x->forward[i]; update[i] = x; } x = x->forward[0]; - bool doesnt_exist = (x == NULL || x->key != key); + bool doesnt_exist = (x == nullptr || x->key != key); if(!doesnt_exist) { for(int i=0;i<=level;i++) { @@ -173,32 +182,39 @@ void* SkipList::searchElement(int key) { return x->value; } else { std::cout << "Not Found" << endl; - return NULL; + return nullptr; } } -// Display skip list level wise +/** + * Display skip list level wise + */ void SkipList::displayList() { std::cout << "Displaying list:\n" << endl; for(int i=0; i <= level; i++) { Node *node = header->forward[i]; std::cout << "Level " << (i) << ": "; - while(node != NULL) { + while(node != nullptr) { std::cout << node->key << " "; node = node->forward[i]; } std::cout << endl; } } - + + +/** + * Main function: + * Creates and inserts random 2^[number of levels] elements into the skip lists and than displays it + */ int main() { std::srand(std::time(nullptr)); SkipList lst; - for (int j = 0; j < (1 << (MAXLVL+1)); j++){ - int k = (std::rand()%( 1 << (MAXLVL+2)) + 1); + for (int j = 0; j < (1 << (MAX_LEVEL+1)); j++){ + int k = (std::rand()%( 1 << (MAX_LEVEL+2)) + 1); lst.insertElement(k, &j); } From d5b897d40e3354e64c6c1bb1bf91435a2bb769b4 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 19:22:32 +0400 Subject: [PATCH 24/67] improve --- data_structures/skip_list.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index c41d3c2e1..5881f5d27 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -7,8 +7,7 @@ #include #include -#include -#include +#include #include // using namespace std; From ea57ad29cd350a265be297a49bc8c65c8dfcc825 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 19:55:47 +0400 Subject: [PATCH 25/67] improve --- data_structures/skip_list.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 5881f5d27..eb8e5cd87 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -23,26 +23,28 @@ using std::endl; */ struct Node { int key; - /* pointer of value */ + //pointer of value void* value; - /*Forward Array*/ + //Forward Array vector forward; Node(int key, int level, void* value); }; /** - * Creates node with provided key, level and value; + * Creates node with provided key, level and value */ Node::Node(int key, int level, void* value) { this->key = key; - /*Initialization of forward vector*/ + //Initialization of forward vector for (int i = 0; i < (level+1); i++){ forward.push_back(nullptr); } } -// Class for Skip list +/** + * SkipList class +*/ class SkipList { int level; Node *header; @@ -57,12 +59,12 @@ public: }; -/**\ - * Skeep List constructor; +/** + * Skeep List constructor */ SkipList::SkipList() { level = 0; - /* Header initialization*/ + // Header initialization header = new Node(-1, MAX_LEVEL, nullptr); } @@ -117,7 +119,7 @@ void SkipList::insertElement(int key, void* value) { if(rlevel > level) { for(int i=level+1;i Date: Tue, 7 Jul 2020 19:58:10 +0400 Subject: [PATCH 26/67] improve --- data_structures/skip_list.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index eb8e5cd87..25a9aae2a 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -1,4 +1,4 @@ -/** +/* * A skip list is a data structure that is used for storing a sorted list of items with a * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * @@ -18,7 +18,7 @@ using std::endl; #define PROBABILITY 0.5 ///< current probability for "coin toss" -/** +/* * Node structure [Key][Node*, Node*...] */ struct Node { @@ -30,7 +30,7 @@ struct Node { Node(int key, int level, void* value); }; -/** +/* * Creates node with provided key, level and value */ Node::Node(int key, int level, void* value) { @@ -42,7 +42,7 @@ Node::Node(int key, int level, void* value) { } } -/** +/* * SkipList class */ class SkipList { @@ -59,7 +59,7 @@ public: }; -/** +/* * Skeep List constructor */ SkipList::SkipList() { @@ -83,7 +83,7 @@ SkipList::~SkipList(){ } -/** +/* * Returns random level for skip list; */ int SkipList::randomLevel() { @@ -94,7 +94,7 @@ int SkipList::randomLevel() { -/** +/* * Inserts elements with given key and value; * It's level is computed by randomLevel() function. */ @@ -135,7 +135,9 @@ void SkipList::insertElement(int key, void* value) { } } - /**Delete document by key*/ +/* + * Delete document by key +*/ void SkipList::deleteElement(int key) { Node *x = header; @@ -166,7 +168,7 @@ void SkipList::deleteElement(int key) } -/** +/* * Searching element in skip list structure */ void* SkipList::searchElement(int key) { @@ -187,7 +189,7 @@ void* SkipList::searchElement(int key) { } } -/** +/* * Display skip list level wise */ void SkipList::displayList() { @@ -204,7 +206,7 @@ void SkipList::displayList() { } -/** +/* * Main function: * Creates and inserts random 2^[number of levels] elements into the skip lists and than displays it */ From 662841bac7e69b6414ab09ed9871b63de7b6b65d Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 19:59:54 +0400 Subject: [PATCH 27/67] improve --- data_structures/skip_list.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 25a9aae2a..729ce1d80 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -18,7 +18,7 @@ using std::endl; #define PROBABILITY 0.5 ///< current probability for "coin toss" -/* +/** * Node structure [Key][Node*, Node*...] */ struct Node { @@ -30,7 +30,7 @@ struct Node { Node(int key, int level, void* value); }; -/* +/** * Creates node with provided key, level and value */ Node::Node(int key, int level, void* value) { @@ -42,7 +42,7 @@ Node::Node(int key, int level, void* value) { } } -/* +/** * SkipList class */ class SkipList { @@ -59,7 +59,7 @@ public: }; -/* +/** * Skeep List constructor */ SkipList::SkipList() { @@ -68,7 +68,9 @@ SkipList::SkipList() { header = new Node(-1, MAX_LEVEL, nullptr); } - +/** + * Destructor for skiplist class +*/ SkipList::~SkipList(){ for(int i=0; i <= level; i++) { Node *node = header->forward[i]; @@ -83,7 +85,7 @@ SkipList::~SkipList(){ } -/* +/** * Returns random level for skip list; */ int SkipList::randomLevel() { @@ -94,7 +96,7 @@ int SkipList::randomLevel() { -/* +/** * Inserts elements with given key and value; * It's level is computed by randomLevel() function. */ @@ -135,7 +137,7 @@ void SkipList::insertElement(int key, void* value) { } } -/* +/** * Delete document by key */ void SkipList::deleteElement(int key) @@ -168,7 +170,7 @@ void SkipList::deleteElement(int key) } -/* +/** * Searching element in skip list structure */ void* SkipList::searchElement(int key) { @@ -206,7 +208,7 @@ void SkipList::displayList() { } -/* +/** * Main function: * Creates and inserts random 2^[number of levels] elements into the skip lists and than displays it */ From 45b21f287116aaffd52fe8b40a9d5104a5ab31e7 Mon Sep 17 00:00:00 2001 From: enqidu Date: Tue, 7 Jul 2020 20:29:37 +0400 Subject: [PATCH 28/67] improve --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 729ce1d80..1fc9f3e0e 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -1,4 +1,4 @@ -/* +/** * A skip list is a data structure that is used for storing a sorted list of items with a * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * From 8216a3267fb35d471b38b657c9e4aca7a819f5e6 Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 20:38:40 +0400 Subject: [PATCH 29/67] randomized tests, documentation, back to vector --- search/fibonacci_search.cpp | 161 ++++++++++++------------------------ 1 file changed, 54 insertions(+), 107 deletions(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index f8525a6b4..e2796b0ba 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -1,6 +1,6 @@ /** * Copyright 2020 @author sprintyaf - * @file + * @file fibonacci_search.cpp * @brief [Fibonacci search * algorithm](https://en.wikipedia.org/wiki/Fibonacci_search_technique) */ @@ -8,27 +8,21 @@ #include #include // for std::vector class #include // for assert +#include // for random numbers +#include // for sorting /** - * Returns minimum of the two numbers + * @brief using fibonacci search algorithm finds an index of a given element in a sorted array + * + * @param arr sorted array + * @param value value that we're looking for + * @returns if the array contains the value, returns an index of the element. otherwise -1. */ -int min(int first, int second){ - if(first < second){ - return first; - } else { - return second; - } -} - -/** - * Input: a sorted array, a value we're looking for and size of the array - * Output: if the array contains the value, returns its index - * else returns -1 - */ -int fibonacci_search(int *arr, int value, int length){ +int fibonacci_search(const std::vector &arr, int value){ int last = 0, current = 1, offset = -1, index; + int length = arr.size(); int next = last + current; while(next < length){ @@ -38,7 +32,7 @@ int fibonacci_search(int *arr, int value, int length){ } while(next > 1){ - index = min(offset + last, length-1); + index = std::min(offset + last, length-1); if(arr[index] < value){ next = current; current = last; @@ -52,115 +46,68 @@ int fibonacci_search(int *arr, int value, int length){ return index; } } - if(current && (length > 0) && arr[offset+1] == value){ + if(current && !arr.empty() && arr[offset+1] == value){ return offset+1; } return -1; } /** - * Tests where given value occurs only once - */ -bool one_occurence_test(){ - // declarations - int value, index, length; + * @brief random tests for checking performance when an array doesn't contain an element +*/ +bool no_occurence_tests(){ bool passed = true; - // last element - length = 3; - int arr1[3] = {1, 2, 3}; - value = 3; - index = fibonacci_search(arr1, value, length); - passed = passed && (index == 2); - // first element - value = 1; - index = fibonacci_search(arr1, value, length); - passed = passed && (index == 0); - // somewhere in the middle element - length = 4; - int arr2[4] = {1, 3, 5, 7}; - value = 3; - index = fibonacci_search(arr2, value, length); - passed = passed && (index == 1); - // arr size is 1 - length = 1; - int arr3[1] = {10}; - value = 10; - index = fibonacci_search(arr3, value, length); - passed = passed && (index == 0); - + int rand_num, rand_value, index, num_tests = 1000; + std::vector arr; + while(num_tests--){ + arr.clear(); + for(int i = 0; i < 100; i++){ + rand_num = rand() % 1000; + arr.push_back(rand_num); + } + rand_value = rand() % 1000; + while(std::find(arr.begin(), arr.end(), rand_value) != arr.end()){ + std::remove(arr.begin(), arr.end(), rand_value); + } + sort(arr.begin(), arr.end()); + index = fibonacci_search(arr, rand_value); + passed = passed && (index == -1); + } return passed; } /** - * Tests where given value occurs more than once - */ -bool many_occurence_test(){ - // declarations - int value, index, length; + * @brief random tests which cover cases when we have one, multiple or zero occurences of the value we're looking for +*/ +bool random_tests(){ bool passed = true; - // last element - length = 4; - int arr1[4] = {1, 1, 10, 10}; - value = 10; - index = fibonacci_search(arr1, value, length); - passed = passed && (index == 2 || index == 3); - // first element - value = 1; - index = fibonacci_search(arr1, value, length); - passed = passed && (index == 0 || index == 1); - // somewhere in the middle element - length = 4; - int arr2[4] = {1, 3, 3, 7}; - value = 3; - index = fibonacci_search(arr2, value, length); - passed = passed && (index == 1 || index == 2); - // all elements are the same - length = 3; - int arr3[3] = {10, 10, 10}; - value = 10; - index = fibonacci_search(arr3, value, length); - passed = passed && (index >= 0 && index <= 2); - + int rand_num, rand_value, index, real_value, num_tests = 10000; + std::vector arr; + while(num_tests--){ + arr.clear(); + for(int i = 0; i < 100; i++){ + rand_num = rand() % 1000; + arr.push_back(rand_num); + } + rand_value = rand() % 1000; + sort(arr.begin(), arr.end()); + index = fibonacci_search(arr, rand_value); + if(index != -1){ + real_value = arr[index]; + passed = passed && (real_value == rand_value); + } else { + passed = passed && (std::find(arr.begin(), arr.end(), rand_value) == arr.end()); + } + } return passed; } -/** - * Tests where the array doesn't contain given value - */ -bool no_occurence_test(){ - // declarations - int value, index, length; - bool passed = true; - // many elements - length = 4; - int arr1[4] = {1, 2, 4, 5}; - value = 3; - index = fibonacci_search(arr1, value, length); - passed = passed && (index == -1); - // one element - length = 1; - int arr2[1] = {1}; - value = 2; - index = fibonacci_search(arr2, value, length); - passed = passed && (index == -1); - // empty array - length = 0; - int arr3[10] = {}; - value = 10; - index = fibonacci_search(arr3, value, length); - passed = passed && (index == -1); - - return passed; -} - - /** * Main Function * testing the algorithm */ int main() { - assert(one_occurence_test()); - assert(many_occurence_test()); - assert(no_occurence_test()); + assert(no_occurence_tests()); + assert(random_tests()); return 0; } From cf6b77a7dce59afb35cb62a8bb6bc780ad958ec5 Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 20:45:03 +0400 Subject: [PATCH 30/67] rand fixed --- search/fibonacci_search.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index e2796b0ba..067d8e636 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -62,10 +62,10 @@ bool no_occurence_tests(){ while(num_tests--){ arr.clear(); for(int i = 0; i < 100; i++){ - rand_num = rand() % 1000; + rand_num = std::rand() % 1000; arr.push_back(rand_num); } - rand_value = rand() % 1000; + rand_value = std::rand() % 1000; while(std::find(arr.begin(), arr.end(), rand_value) != arr.end()){ std::remove(arr.begin(), arr.end(), rand_value); } @@ -86,11 +86,11 @@ bool random_tests(){ while(num_tests--){ arr.clear(); for(int i = 0; i < 100; i++){ - rand_num = rand() % 1000; + rand_num = std::rand() % 1000; arr.push_back(rand_num); } - rand_value = rand() % 1000; - sort(arr.begin(), arr.end()); + rand_value = std::rand() % 1000; + std::sort(arr.begin(), arr.end()); index = fibonacci_search(arr, rand_value); if(index != -1){ real_value = arr[index]; From 644524337a9112491b59d87df3890d276078007d Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Tue, 7 Jul 2020 22:53:12 +0400 Subject: [PATCH 31/67] copyright removed --- search/fibonacci_search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index 067d8e636..dd1b06f11 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2020 @author sprintyaf + * @author sprintyaf * @file fibonacci_search.cpp * @brief [Fibonacci search * algorithm](https://en.wikipedia.org/wiki/Fibonacci_search_technique) From 59a8b3d4a295e7af34437151e0f50c973eb7e77d Mon Sep 17 00:00:00 2001 From: enqidu Date: Wed, 8 Jul 2020 20:43:52 +0400 Subject: [PATCH 32/67] Update data_structures/skip_list.cpp Co-authored-by: David Leal --- data_structures/skip_list.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 1fc9f3e0e..62ae51ea9 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -210,7 +210,8 @@ void SkipList::displayList() { /** * Main function: - * Creates and inserts random 2^[number of levels] elements into the skip lists and than displays it + * Creates and inserts random 2^[number of levels] + * elements into the skip lists and than displays it */ int main() { From a5ca794aa4e27e6fb5d9c6e591449458ee5b8fe4 Mon Sep 17 00:00:00 2001 From: enqidu Date: Wed, 8 Jul 2020 20:46:50 +0400 Subject: [PATCH 33/67] sk --- data_structures/skip_list.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 1fc9f3e0e..b7aab7882 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -10,7 +10,6 @@ #include #include -// using namespace std; using std::vector; using std::endl; @@ -23,9 +22,9 @@ using std::endl; */ struct Node { int key; - //pointer of value + // pointer of value void* value; - //Forward Array + // Forward Array vector forward; Node(int key, int level, void* value); }; From bba0db36ec5aa125fa4acdb35191e8348aaa670b Mon Sep 17 00:00:00 2001 From: enqidu Date: Wed, 8 Jul 2020 20:47:43 +0400 Subject: [PATCH 34/67] sk --- data_structures/skip_list.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 3e13ee696..922c5a1e3 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -120,7 +120,7 @@ void SkipList::insertElement(int key, void* value) { if(rlevel > level) { for(int i=level+1;iforward[i] != x) break; update[i]->forward[i] = x->forward[i]; } - /*Remove empty levels*/ + /* Remove empty levels*/ while(level>0 && header->forward[level] == 0) level--; std::cout << "Deleted" << endl; } else { From 497d627ebde140b14dde08e25d98b7049886601d Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 9 Jul 2020 18:15:05 -0400 Subject: [PATCH 35/67] [improvement] updated contribution guidelines (#945) * updated contribution guidelines * fix case --- CONTRIBUTING.md | 87 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f0205bfd..35d875d43 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,8 +28,85 @@ We are very happy that you consider implementing algorithms and data structures - Strictly use snake_case (underscore_separated) in filenames. - If you have added or modified code, please make sure the code compiles before submitting. - Our automated testing runs [__cpplint__](https://github.com/cpplint/cpplint) on all pull requests so please be sure that your code passes before submitting. +- Please conform to [doxygen](https://www.doxygen.nl/manual/docblocks.html) standard and document the code as much as possible. This not only facilitates the readers but also generates the correct info on website. - **Be consistent in use of these guidelines.** +#### Documentation +- Make sure you put useful comments in your code. Do not comment things that are obvious. +- Please avoid creating new directories if at all possible. Try to fit your work into the existing directory structure. If you want to create a new directory, then please check if a similar category has been recently suggested or created by other pull requests. +- If you have modified/added documentation, please ensure that your language is concise and contains no grammar errors. +- Do not update README.md along with other changes, first create an issue and then link to that issue in your pull request to suggest specific changes required to README.md +- The repository follows [Doxygen](https://www.doxygen.nl/manual/docblocks.html) standards and auto-generates the [repo website](https://thealgorithms.github.io/C-Plus-Plus). Please ensure the code is documented in this structure. Sample implementation is given below. + +#### Test +- Make sure to add examples and test cases in your main() function. +- If you find any algorithm or document without tests, please feel free to create a pull request or issue describing suggested changes. +- Please try to add one or more `test()` functions that will invoke the algorithm implementation on random test data with expected output. Use `assert()` function to confirm that the tests will pass. + +#### Typical structure of a program: +```cpp +/** + * @file + * @brief Add one line description here + * @details + * This is a multi line + * description containing links, references, + * math equations, etc + * @author [Name](https://github.com/handle) + * @see related_file.cpp, another_file.cpp + */ + +#include + +/** + * @namespace + */ +namespace name { + +/** + * Class documentation + */ +class cls_name{ + private: + int var1; ///< short info of this variable + char *msg; ///< short info + + public: + // other members also documented as below +} + +/** + * Function documentation + * @tparam T this is a one-line info about T + * @param param1 on-line info about param1 + * @param param2 on-line info about param2 + * @returns `true` if ... + * @returns `false` if ... + */ +template +bool func(int param1, T param2) { + // function statements here + if(/*something bad*/) + return false; + + return true; +} + +/** Test function */ +void test() { + /* some statements */ + assert(func(...) == ...); // this ensures that the algorithm works as expected + + // can have multiple checks +} + +/** Main function */ +int main(int argc, char *argv[]) { + // code here + return 0; +} +``` + #### New File Name guidelines - Use lowercase words with ``"_"`` as separator - For instance @@ -70,16 +147,6 @@ Common prefixes: - docs: Documentation changes - test: Correct existing tests or add new ones -#### Documentation -- Make sure you put useful comments in your code. Do not comment things that are obvious. -- Please avoid creating new directories if at all possible. Try to fit your work into the existing directory structure. If you want to create a new directory, then please check if a similar category has been recently suggested or created by other pull requests. -- If you have modified/added documentation, please ensure that your language is concise and contains no grammar errors. -- Do not update README.md along with other changes, first create an issue and then link to that issue in your pull request to suggest specific changes required to README.md - -#### Test -- Make sure to add examples and test cases in your main() function. -- If you find any algorithm or document without tests, please feel free to create a pull request or issue describing suggested changes. - ### Pull Requests - Checkout our [pull request template](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/.github/pull_request_template.md) From bf2dac6de238cabf81092ca76176c91596771543 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 10:43:05 -0400 Subject: [PATCH 36/67] enable gitpod for all branches --- .gitpod.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitpod.yml b/.gitpod.yml index 40750258c..ece107997 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -7,6 +7,7 @@ github: addComment: false addCheck: false master: true + branches: true pullRequestsFromForks: true vscode: From ebd13a7e241df3a3963f6fc728bd37c826291927 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Fri, 10 Jul 2020 20:32:59 +0530 Subject: [PATCH 37/67] Improved sieve_of_eratosthenes.cpp (#933) * Update sieve_of_eratosthenes.cpp * removed unwanted spaces * removed init function Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> --- math/sieve_of_eratosthenes.cpp | 49 +++++++++++++++------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/math/sieve_of_eratosthenes.cpp b/math/sieve_of_eratosthenes.cpp index d8fa70531..e30bc1891 100644 --- a/math/sieve_of_eratosthenes.cpp +++ b/math/sieve_of_eratosthenes.cpp @@ -10,25 +10,21 @@ * @see primes_up_to_billion.cpp prime_numbers.cpp */ -#include - -/** Maximum number of primes */ -#define MAX 10000000 - -/** array to store the primes */ -bool isprime[MAX]; +#include // for io operations /** * This is the function that finds the primes and eliminates * the multiples. + * @param N number of primes to check + * @param [out] isprime a boolean array of size `N` identifying if `i`^th number is prime or not */ -void sieve(uint32_t N) { - isprime[0] = false; - isprime[1] = false; - for (uint32_t i = 2; i <= N; i++) { - if (isprime[i]) { - for (uint32_t j = (i << 1); j <= N; j += i) { - isprime[j] = false; +void sieve(uint32_t N, bool *isprime) { + isprime[0] = true; + isprime[1] = true; + for (uint32_t i = 2; i * i <= N; i++) { + if (!isprime[i]) { + for (uint32_t j = (i << 1); j <= N; j = j + i) { + isprime[j] = true; } } } @@ -36,10 +32,12 @@ void sieve(uint32_t N) { /** * This function prints out the primes to STDOUT + * @param N number of primes to check + * @param [in] isprime a boolean array of size `N` identifying if `i`^th number is prime or not */ -void print(uint32_t N) { - for (uint32_t i = 1; i <= N; i++) { - if (isprime[i]) { +void print(uint32_t N, const bool *isprime) { + for (uint32_t i = 2; i <= N; i++) { + if (!isprime[i]) { std::cout << i << ' '; } } @@ -47,19 +45,14 @@ void print(uint32_t N) { } /** - * Initialize the array + * Main function */ -void init() { - for (uint32_t i = 1; i < MAX; i++) { - isprime[i] = true; - } -} - -/** main function */ int main() { uint32_t N = 100; - init(); - sieve(N); - print(N); + bool *isprime = new bool[N]; + sieve(N, isprime); + print(N, isprime); + delete[] isprime; + return 0; } From 58099884dd626ba94602fa00351d8e6c5f49c9e9 Mon Sep 17 00:00:00 2001 From: sprintyaf Date: Fri, 10 Jul 2020 19:13:16 +0400 Subject: [PATCH 38/67] comments added --- search/fibonacci_search.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp index dd1b06f11..be181a47d 100644 --- a/search/fibonacci_search.cpp +++ b/search/fibonacci_search.cpp @@ -21,34 +21,48 @@ * @returns if the array contains the value, returns an index of the element. otherwise -1. */ int fibonacci_search(const std::vector &arr, int value){ - int last = 0, current = 1, offset = -1, index; - int length = arr.size(); - int next = last + current; + // initialize last and current members of Fibonacci sequence + int last = 0, current = 1; + int length = arr.size(); // array size + // next member of Fibonacci sequence which is "last" + "current" + int next = last + current; + // "next" will store the smallest Fibonacci number greater or equal to "length" while(next < length){ last = current; current = next; next = last + current; } + // "offset" is the end of eliminated range from front + int offset = -1, index; + // while loop until there are elements left to consider. + // when "next" becomes 1, last is equal to 0, so search is done, + // because arr[offset] will already be eliminated while(next > 1){ + // check if "last" is valid location index = std::min(offset + last, length-1); + // if value is greater than the value at "index", eliminate the subarray from offset to index if(arr[index] < value){ next = current; current = last; last = next - current; offset = index; + // if value is less than the value at "index", eliminate the subarray after index+1 } else if(arr[index] > value){ next = last; current = current - last; last = next - current; + // element is found } else { return index; } } + // comparing the last element if(current && !arr.empty() && arr[offset+1] == value){ return offset+1; } + // value was not found, return -1 return -1; } From 02d947777befbf0ed7a3d3f85e7474579cf01cf0 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 11:32:37 -0400 Subject: [PATCH 39/67] [enhancement] Replace cpplint with clang-tidy (#943) * test commit for using clang-tidy instead of cpplint * add suffix -- to clang-tidy & commit * fixes to git commit * commenting redundant clang-format as clang-tidy will take care of that * add clang-tidy config file * use clang-tidy config file * test dump config to ensure config is read correctly * move test to top * test passed, removing test code Test link: https://github.com/TheAlgorithms/C-Plus-Plus/pull/943/checks?check_run_id=851231578 * fix clang-tidy config * set clang-tidy standard to c++11 * provide clang-tidy with compilation details * fix build path argument & Use clang-9 (cherry picked from commit 5eddf0cd9536f328a6a3485b5ed59705618a1433) * Merge commit '433568f9fa7c3e7f1b2e0c86c1864e92ad2668c8' * Use clang-9 * fix subprocess.STDOUT * remove pipe for stdout * bumot o clang-tidy-10 * Revert "Merge commit '433568f9fa7c3e7f1b2e0c86c1864e92ad2668c8'" This reverts commit 2a7462056a58fc9f5eda1ab8e723df2f28f34c2c. * add docs --- .clang-tidy | 6 ++++ .github/workflows/awesome_workflow.yml | 46 +++++++++++--------------- 2 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..02bb3916f --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,6 @@ +--- +Checks: '-*,google-*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' +WarningsAsErrors: '' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: '{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, AlignConsecutiveMacros: true }' diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index f8feb1d3e..2e0792e17 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -16,7 +16,9 @@ jobs: - name: requirements run: | sudo apt -qq -y update - sudo apt -qq install clang-format + sudo apt -qq install clang-tidy-10 + # checks are passing with less errors when used with this version. + # The default installs v6.0 which did not work out well in my tests - name: Setup Git Specs run: | git config --global user.name github-actions @@ -43,18 +45,6 @@ jobs: fi done git commit -am "formatting filenames $GITHUB_SHA" || true - - name: Clang Formatter - run: | - for fname in $(find . -name '*.cpp' -o -name '*.h') - do - clang-format --verbose -i --style="$line1 $line2 $line3 $line4" "$fname" - done - git commit -am "formatting source-code for $GITHUB_SHA" || true - env: - line1: "{ BasedOnStyle: Google, UseTab: Never," - line2: "IndentWidth: 4, TabWidth: 4, " - line3: "AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false," - line4: "ColumnLimit: 80, AccessModifierOffset: -3 }" - name: Update DIRECTORY.md shell: python @@ -100,24 +90,21 @@ jobs: with open("DIRECTORY.md", "w") as out_file: out_file.write(build_directory_md(".") + "\n") - - name: Update DIRECTORY.md + - name: Commit DIRECTORY.md + run: git commit -m "updating DIRECTORY.md" DIRECTORY.md || true + - name: Get file changes run: | - cat DIRECTORY.md - git config --global user.name github-actions - 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 - git add DIRECTORY.md - git commit -am "updating DIRECTORY.md" || true - git push --force origin HEAD:$GITHUB_REF || true - - name: Install CPPLINT - run: | - python -m pip install cpplint git remote -v git branch git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY git diff --diff-filter=dr --name-only origin/master > git_diff.txt echo "Files changed-- `cat git_diff.txt`" - - name: cpplint_modified_files + - name: Configure for static lint checks + # compiling first gives clang-tidy access to all the header files and settings used to compile the programs. + # This will check for macros, if any, on linux and not for Windows. But the use of portability checks should + # be able to catch any errors for other platforms. + run: cmake -B build -S . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + - name: Lint modified files shell: python run: | import os @@ -135,9 +122,9 @@ jobs: if not cpp_files: sys.exit(0) - print("cpplint:") for cpp_file in cpp_files: - subprocess.run(["cpplint", "--filter=-legal/copyright,-build/include", cpp_file], check=True, text=True) + subprocess.run(["clang-tidy-10", "--fix", "-p=build", cpp_file, "--"], + check=True, text=True, stderr=subprocess.STDOUT) # print("g++:") # compile_exts = tuple(".c .c++ .cc .cpp .cu .cxx".split()) @@ -163,6 +150,11 @@ jobs: bad_files = len(upper_files + space_files + nodir_files) if bad_files: sys.exit(bad_files) + - name: Commit and push changes + run: | + git diff DIRECTORY.md + git commit -am "clang-tidy fixes for $GITHUB_SHA" || true + git push --force origin HEAD:$GITHUB_REF || true build: name: Compile checks From ab1ddb364f3116e08bd52f6424f5cfbaca484157 Mon Sep 17 00:00:00 2001 From: enqidu Date: Fri, 10 Jul 2020 20:39:33 +0400 Subject: [PATCH 40/67] documentation --- data_structures/skip_list.cpp | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 922c5a1e3..dc9b06776 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -13,8 +13,8 @@ using std::vector; using std::endl; -#define MAX_LEVEL 2 ///< maximum level of skip list -#define PROBABILITY 0.5 ///< current probability for "coin toss" +#define MAX_LEVEL 2 ///< Maximum level of skip list +#define PROBABILITY 0.5 ///< Current probability for "coin toss" /** @@ -24,13 +24,18 @@ struct Node { int key; // pointer of value void* value; - // Forward Array + // Forward Array points to the neighbour (right) + // nodes of the given one in all levels vector forward; + // Constructor of the node Node(int key, int level, void* value); }; /** * Creates node with provided key, level and value + * @param key is number that is used for comparision + * @param level is the maximum level node's going to added + * */ Node::Node(int key, int level, void* value) { this->key = key; @@ -42,10 +47,12 @@ Node::Node(int key, int level, void* value) { } /** - * SkipList class + * SkipList class implementation with basic methods */ class SkipList { + // Maximum level of the skiplist int level; + // Pointer to the header node Node *header; public: SkipList(); @@ -59,7 +66,8 @@ public: /** - * Skeep List constructor + * Skeep List constructor. Initializes header, start + * Node for searching in the list */ SkipList::SkipList() { level = 0; @@ -85,7 +93,9 @@ SkipList::~SkipList(){ /** - * Returns random level for skip list; + * Returns random level of the skip list. + * Every higher level is 2 times less likely. + * @return lvl: random level for skip list; */ int SkipList::randomLevel() { int lvl = 0; @@ -98,6 +108,8 @@ int SkipList::randomLevel() { /** * Inserts elements with given key and value; * It's level is computed by randomLevel() function. + * @param key is number that is used for comparision + * @param value pointer to a value, that can be any type */ void SkipList::insertElement(int key, void* value) { std::cout << "Inserting" << key << "..."; @@ -137,10 +149,10 @@ void SkipList::insertElement(int key, void* value) { } /** - * Delete document by key + * Deletes an element by key and prints if has been removed successfully + * @param key is number that is used for comparision. */ -void SkipList::deleteElement(int key) -{ +void SkipList::deleteElement(int key) { Node *x = header; Node *update[MAX_LEVEL+1]; @@ -171,6 +183,8 @@ void SkipList::deleteElement(int key) /** * Searching element in skip list structure + * @param key is number that is used for comparision + * @return pointer to the value of the node */ void* SkipList::searchElement(int key) { Node *x = header; @@ -191,7 +205,7 @@ void* SkipList::searchElement(int key) { } /* - * Display skip list level wise + * Display skip list level */ void SkipList::displayList() { std::cout << "Displaying list:\n" << endl; From d59005678d7b2f294df26c088842ab3e44f85f31 Mon Sep 17 00:00:00 2001 From: enqidu Date: Fri, 10 Jul 2020 20:40:00 +0400 Subject: [PATCH 41/67] documentation --- data_structures/skip_list.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index dc9b06776..80717050a 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -35,7 +35,6 @@ struct Node { * Creates node with provided key, level and value * @param key is number that is used for comparision * @param level is the maximum level node's going to added - * */ Node::Node(int key, int level, void* value) { this->key = key; From 05bb23ca27046c7bb4954d1317ea8108b4c2cd9d Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:47:37 -0400 Subject: [PATCH 42/67] [enhancement] New Graphics implementation with algorithm for spirograph (#936) * added spirograph program * add graphics forlder to cmake * updating DIRECTORY.md * enable VNC for GUI programs on gitpod * fix cpplint error * fix macro definitions for correct documentation * fix filename in docs * move include from namespace to global * download and build freeglut if not available * install opengl libraries for build check * fix syntax error * fix quotes * install mesa-utils instead * use markepplace tool instead of installing * fix syntax * undo changes to github actions * OpenGL not mandatory * add private option to compile definition * fix: corrected to compile definitions instead of options * use the macro USE_GLUT * compile FREEGLUT as a subdirectory. this maintains a consistency * build freeglut_static when GLUT library not available * provide keyboard control * clang-tidy fixes for cb284bddb2a361370d08fe6926036947236bd4c5 Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .gitpod.dockerfile | 14 +- CMakeLists.txt | 51 ++++---- DIRECTORY.md | 3 + graphics/CMakeLists.txt | 83 ++++++++++++ graphics/spirograph.cpp | 284 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 406 insertions(+), 29 deletions(-) create mode 100644 graphics/CMakeLists.txt create mode 100644 graphics/spirograph.cpp diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile index 6d6a4e895..53d336f81 100644 --- a/.gitpod.dockerfile +++ b/.gitpod.dockerfile @@ -1,9 +1,9 @@ -FROM gitpod/workspace-full +FROM gitpod/workspace-full-vnc RUN sudo apt-get update \ - && sudo apt-get install -y \ - doxygen \ - graphviz \ - ninja-build \ - && pip install cpplint \ - && sudo rm -rf /var/lib/apt/lists/* + && sudo apt-get install -y \ + doxygen \ + graphviz \ + ninja-build \ + && pip install cpplint \ + && sudo rm -rf /var/lib/apt/lists/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 712c3db42..d7fa88559 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,28 @@ if(MSVC) endif(MSVC) option(USE_OPENMP "flag to use OpenMP for multithreading" ON) - +if(USE_OPENMP) + find_package(OpenMP) + if (OpenMP_CXX_FOUND) + message(STATUS "Building with OpenMP Multithreading.") + else() + message(STATUS "No OpenMP found, no multithreading.") + endif() +endif() + +add_subdirectory(math) +add_subdirectory(others) +add_subdirectory(search) +add_subdirectory(ciphers) +add_subdirectory(strings) +add_subdirectory(sorting) +add_subdirectory(geometry) +add_subdirectory(graphics) +add_subdirectory(probability) +add_subdirectory(data_structures) +add_subdirectory(machine_learning) +add_subdirectory(numerical_methods) + cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0057 NEW) find_package(Doxygen OPTIONAL_COMPONENTS dot dia) @@ -34,6 +55,7 @@ if(DOXYGEN_FOUND) set(DOXYGEN_STRIP_CODE_COMMENTS NO) set(DOXYGEN_EXT_LINKS_IN_WINDOW YES) set(DOXYGEN_BUILTIN_STL_SUPPORT YES) + 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) @@ -48,6 +70,12 @@ if(DOXYGEN_FOUND) 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 @@ -56,27 +84,6 @@ if(DOXYGEN_FOUND) ) endif() -if(USE_OPENMP) - find_package(OpenMP) - if (OpenMP_CXX_FOUND) - message(STATUS "Building with OpenMP Multithreading.") - else() - message(STATUS "No OpenMP found, no multithreading.") - endif() -endif() - -add_subdirectory(math) -add_subdirectory(others) -add_subdirectory(search) -add_subdirectory(ciphers) -add_subdirectory(strings) -add_subdirectory(sorting) -add_subdirectory(geometry) -add_subdirectory(probability) -add_subdirectory(data_structures) -add_subdirectory(machine_learning) -add_subdirectory(numerical_methods) - set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack) diff --git a/DIRECTORY.md b/DIRECTORY.md index f53d2f7ab..0f7e9a053 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -84,6 +84,9 @@ * [Topological Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/topological_sort.cpp) * [Topological Sort By Kahns Algo](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/topological_sort_by_kahns_algo.cpp) +## Graphics + * [Spirograph](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graphics/spirograph.cpp) + ## Greedy Algorithms * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/greedy_algorithms/dijkstra.cpp) * [Huffman](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/greedy_algorithms/huffman.cpp) diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt new file mode 100644 index 000000000..2ea6ca230 --- /dev/null +++ b/graphics/CMakeLists.txt @@ -0,0 +1,83 @@ +find_package(OpenGL) +if(OpenGL_FOUND) + find_package(GLUT) + if(NOT GLUT_FOUND) + message("FreeGLUT library will be downloaded and built.") + include(ExternalProject) + ExternalProject_Add ( + FREEGLUT-PRJ + URL https://sourceforge.net/projects/freeglut/files/freeglut/3.2.1/freeglut-3.2.1.tar.gz + URL_MD5 cd5c670c1086358598a6d4a9d166949d + CMAKE_GENERATOR ${CMAKE_GENERATOR} + CMAKE_GENERATOR_TOOLSET ${CMAKE_GENERATOR_TOOLSET} + CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM} + CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release + -DFREEGLUT_BUILD_SHARED_LIBS=OFF + -DFREEGLUT_BUILD_STATIC_LIBS=ON + -DFREEGLUT_BUILD_DEMOS=OFF + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/freeglut + # BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/freeglut-build + # BUILD_IN_SOURCE ON + # UPDATE_COMMAND "" + INSTALL_COMMAND "" + # CONFIGURE_COMMAND "" + # BUILD_COMMAND "" + ) + ExternalProject_Get_Property(FREEGLUT-PRJ SOURCE_DIR) + ExternalProject_Get_Property(FREEGLUT-PRJ BINARY_DIR) + set(FREEGLUT_BIN_DIR ${BINARY_DIR}) + set(FREEGLUT_SRC_DIR ${SOURCE_DIR}) + # add_library(libfreeglut STATIC IMPORTED) + # set_target_properties(libfreeglut PROPERTIES IMPORTED_LOCATION ${FREEGLUT_BIN_DIR}) + + # set(FREEGLUT_BUILD_DEMOS OFF CACHE BOOL "") + # set(FREEGLUT_BUILD_SHARED_LIBS OFF CACHE BOOL "") + # set(FREEGLUT_BUILD_STATIC_LIBS ON CACHE BOOL "") + # add_subdirectory(${FREEGLUT_SRC_DIR} ${FREEGLUT_BIN_DIR} EXCLUDE_FROM_ALL) + # add_subdirectory(${BINARY_DIR}) + # find_package(FreeGLUT) + endif(NOT GLUT_FOUND) +else(OpenGL_FOUND) + message(WARNING "OPENGL not found. Will not build graphical outputs.") +endif(OpenGL_FOUND) + +# 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} PRIVATE OpenMP::OpenMP_CXX) + endif() + + if(OpenGL_FOUND) + if(NOT GLUT_FOUND) + add_dependencies(${testname} FREEGLUT-PRJ) + target_compile_definitions(${testname} PRIVATE FREEGLUT_STATIC) + target_include_directories(${testname} PRIVATE ${FREEGLUT_SRC_DIR}/include) + target_link_directories(${testname} PRIVATE ${FREEGLUT_BIN_DIR}/lib) + target_link_libraries(${testname} PRIVATE OpenGL::GL) + target_link_libraries(${testname} INTERFACE FREEGLUT-PRJ) + # target_include_directories(${testname} PRIVATE ${FREEGLUT_INCLUDE_DIRS}) + # target_link_libraries(${testname} INTERFACE freeglut_static) + else() + target_include_directories(${testname} PRIVATE ${GLUT_INCLUDE_DIRS}) + target_link_libraries(${testname} PRIVATE OpenGL::GL ${GLUT_LIBRARIES}) + endif() + target_compile_definitions(${testname} PRIVATE USE_GLUT) + endif(OpenGL_FOUND) + + if(APPLE) + target_compile_options(${testname} PRIVATE -Wno-deprecated) + endif(APPLE) + + install(TARGETS ${testname} DESTINATION "bin/graphics") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/graphics/spirograph.cpp b/graphics/spirograph.cpp new file mode 100644 index 000000000..84c17c4db --- /dev/null +++ b/graphics/spirograph.cpp @@ -0,0 +1,284 @@ +/** + * @file + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief Implementation of + * [Spirograph](https://en.wikipedia.org/wiki/Spirograph) + * + * @details + * Implementation of the program is based on the geometry shown in the figure + * below: + * + * Spirograph geometry from Wikipedia + */ +#ifdef USE_GLUT +#ifdef __APPLE__ +#include // include path on Macs is different +#else +#include +#endif // __APPLE__ +#endif +#define _USE_MATH_DEFINES /**< required for MSVC compiler */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _OPENMP +#include +#endif + +/** + * @namespace spirograph Functions related to spirograph.cpp + */ +namespace spirograph { +/** Generate spirograph curve into arrays `x` and `y` such that the i^th point + * in 2D is represented by `(x[i],y[i])`. The generating function is given by: + * \f{eqnarray*}{ + * x &=& R\left[ (1-k) \cos (t) + l\cdot k\cdot\cos \left(\frac{1-k}{k}t\right) + * \right]\\ + * y &=& R\left[ (1-k) \sin (t) - l\cdot k\cdot\sin \left(\frac{1-k}{k}t\right) + * \right] \f} + * where + * * \f$R\f$ is the scaling parameter that we will consider \f$=1\f$ + * * \f$l=\frac{\rho}{r}\f$ is the relative distance of marker from the centre + * of inner circle and \f$0\le l\le1\f$ + * * \f$\rho\f$ is physical distance of marker from centre of inner circle + * * \f$r\f$ is the radius of inner circle + * * \f$k=\frac{r}{R}\f$ is the ratio of radius of inner circle to outer circle + * and \f$0 +void spirograph(std::array, N> *points, double l, + double k, double rot) { + double dt = rot * 2.f * M_PI / N; + double R = 1.f; + const double k1 = 1.f - k; + int32_t step = 0; + +#ifdef _OPENMP +#pragma omp for +#endif + for (step = 0; step < N; step++) { + double t = dt * step; + double first = R * (k1 * std::cos(t) + l * k * std::cos(k1 * t / k)); + double second = R * (k1 * std::sin(t) - l * k * std::sin(k1 * t / k)); + points[0][step].first = first; + points[0][step].second = second; + } +} + +/** + * @brief Test function to save resulting points to a CSV file. + * + */ +void test() { + const size_t N = 500; + double l = 0.3, k = 0.75, rot = 10.; + std::stringstream fname; + fname << std::setw(3) << "spirograph_" << l << "_" << k << "_" << rot + << ".csv"; + std::ofstream fp(fname.str()); + if (!fp.is_open()) { + perror(fname.str().c_str()); + exit(EXIT_FAILURE); + } + + std::array, N> points; + + spirograph(&points, l, k, rot); + + for (size_t i = 0; i < N; i++) { + fp << points[i].first << "," << points[i].first; + if (i < N - 1) { + fp << '\n'; + } + } + + fp.close(); +} + +#ifdef USE_GLUT +static bool paused = 0; /**< flag to set pause/unpause animation */ +static const int animation_speed = 25; /**< animation delate in ms */ + +static const double step = 0.01; /**< animation step size */ +static double l_ratio = step * 10; /**< the l-ratio defined in docs */ +static double k_ratio = step; /**< the k-ratio defined in docs */ +static const double num_rot = 20.; /**< number of rotations to simulate */ + +/** A wrapper that is not available in all GLUT implementations. + */ +static inline void glutBitmapString(void *font, char *message) { + for (char *ch = message; *ch != '\0'; ch++) glutBitmapCharacter(font, *ch); +} + +/** + * @brief Function to graph (x,y) points on the OpenGL graphics window. + * + * @tparam N number of points = size of array + * @param [in] points Array of 2D points represented as std::pair + * @param l the relative distance of marker from the centre of + * inner circle and \f$0\le l\le1\f$ to display info + * @param k the ratio of radius of inner circle to outer circle and \f$0 +void display_graph(const std::array, N> &points, + double l, double k) { + glClearColor(1.0f, 1.0f, 1.0f, + 0.0f); // Set background color to white and opaque + glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background) + + glBegin(GL_LINES); // draw line segments + glColor3f(0.f, 0.f, 1.f); // blue + glPointSize(2.f); // point size in pixels + + for (size_t i = 1; i < N; i++) { + glVertex2f(points[i - 1].first, points[i - 1].second); // line from + glVertex2f(points[i].first, points[i].second); // line to + } + glEnd(); + + glColor3f(0.f, 0.f, 0.f); + std::stringstream buffer; + buffer << std::setw(3) << "l = " << l; + glRasterPos2f(-.85, .85); + glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, + const_cast(buffer.str().c_str())); + buffer.str(""); + buffer.clear(); + buffer << std::setw(3) << "k = " << k; + glRasterPos2f(-.85, .70); + glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, + const_cast(buffer.str().c_str())); + + glutSwapBuffers(); +} + +/** + * @brief Test function with animation + * + */ +void test2() { + const size_t N = 5000; // number of samples + + static bool direction1 = true; // increment if true, otherwise decrement + static bool direction2 = true; // increment if true, otherwise decrement + + std::array, N> points; + + spirograph(&points, l_ratio, k_ratio, num_rot); + display_graph(points, l_ratio, k_ratio); + + if (paused) + // if paused, do not update l_ratio and k_ratio + return; + + if (direction1) { // increment k_ratio + if (k_ratio >= (1.f - step)) // maximum limit + direction1 = false; // reverse direction of k_ratio + else + k_ratio += step; + } else { // decrement k_ratio + if (k_ratio <= step) { // minimum limit + direction1 = true; // reverse direction of k_ratio + + if (direction2) { // increment l_ratio + if (l_ratio >= (1.f - step)) // max limit of l_ratio + direction2 = false; // reverse direction of l_ratio + else + l_ratio += step; + } else { // decrement l_ratio + if (l_ratio <= step) // minimum limit of l_ratio + direction2 = true; // reverse direction of l_ratio + else + l_ratio -= step; + } + } else { // no min limit of k_ratio + k_ratio -= step; + } + } +} + +/** + * @brief GLUT timer callback function to add animation delay. + */ +void timer_cb(int t) { + glutTimerFunc(animation_speed, timer_cb, 0); + glutPostRedisplay(); +} + +/** + * @brief Keypress event call back function. + * + * @param key ID of the key pressed + * @param x mouse pointer position at event + * @param y mouse pointer position at event + */ +void keyboard_cb(unsigned char key, int x, int y) { + switch (key) { + case ' ': // spacebar toggles pause + paused = !paused; // toggle + break; + case GLUT_KEY_UP: + case '+': // up arrow key + k_ratio += step; + break; + case GLUT_KEY_DOWN: + case '_': // down arrow key + k_ratio -= step; + break; + case GLUT_KEY_RIGHT: + case '=': // left arrow key + l_ratio += step; + break; + case GLUT_KEY_LEFT: + case '-': // right arrow key + l_ratio -= step; + break; + case 0x1B: // escape key exits + exit(EXIT_SUCCESS); + default: + return; + } +} +#endif +} // namespace spirograph + +/** Main function */ +int main(int argc, char **argv) { + spirograph::test(); + +#ifdef USE_GLUT + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("Spirograph"); + glutInitWindowSize(400, 400); + // glutIdleFunc(glutPostRedisplay); + glutTimerFunc(spirograph::animation_speed, spirograph::timer_cb, 0); + glutKeyboardFunc(spirograph::keyboard_cb); + glutDisplayFunc(spirograph::test2); + glutMainLoop(); +#endif + + return 0; +} From a90dcc5f66126049e91e0fa3835a55f6afb7d9fe Mon Sep 17 00:00:00 2001 From: enqidu Date: Fri, 10 Jul 2020 21:10:21 +0400 Subject: [PATCH 43/67] parameters --- data_structures/skip_list.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 80717050a..37839dfdb 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -1,8 +1,12 @@ /** + * @file skip_list.cpp + * @brief data struccture for fast searching and insertion (O(log(n))) + * @details * A skip list is a data structure that is used for storing a sorted list of items with a - * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items + * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * - * References used: GeeksForGeeks skip list code, https://iq.opengenus.org/skip-list/ Code and PseudoCode. + * References used: GeeksForGeeks skip list code, https://iq.opengenus.org/skip-list/ PseudoCode and Code + * . */ #include From 2fecf67a365b9329036d623467dde998903ead98 Mon Sep 17 00:00:00 2001 From: enqidu Date: Fri, 10 Jul 2020 21:11:20 +0400 Subject: [PATCH 44/67] parameters --- data_structures/skip_list.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 37839dfdb..6159506a0 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -6,6 +6,7 @@ * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * * References used: GeeksForGeeks skip list code, https://iq.opengenus.org/skip-list/ PseudoCode and Code + * @author enqidu * . */ From b1b3b310a403398d279cbe6c619d109068fe11e1 Mon Sep 17 00:00:00 2001 From: enqidu Date: Fri, 10 Jul 2020 21:27:22 +0400 Subject: [PATCH 45/67] Update data_structures/skip_list.cpp Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 6159506a0..515c6d138 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -5,7 +5,7 @@ * A skip list is a data structure that is used for storing a sorted list of items with a * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * - * References used: GeeksForGeeks skip list code, https://iq.opengenus.org/skip-list/ PseudoCode and Code + * References used: [GeeksForGeek](https://www.geeksforgeeks.org/skip-list/), [OpenGenus](https://iq.opengenus.org/skip-list) for PseudoCode and Code * @author enqidu * . */ From 5d225aba874d4b74021c1865f62148517a869f30 Mon Sep 17 00:00:00 2001 From: enqidu Date: Fri, 10 Jul 2020 21:27:35 +0400 Subject: [PATCH 46/67] Update data_structures/skip_list.cpp Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 515c6d138..cefd23403 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -6,7 +6,7 @@ * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * * References used: [GeeksForGeek](https://www.geeksforgeeks.org/skip-list/), [OpenGenus](https://iq.opengenus.org/skip-list) for PseudoCode and Code - * @author enqidu + * @author [enqidu](https://github.com/enqidu) * . */ From af49a02ed85b944d88c13393c0ecd2cd30f5a0d7 Mon Sep 17 00:00:00 2001 From: enqidu Date: Fri, 10 Jul 2020 21:27:51 +0400 Subject: [PATCH 47/67] Update data_structures/skip_list.cpp Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index cefd23403..6e6d78e13 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -1,6 +1,6 @@ /** * @file skip_list.cpp - * @brief data struccture for fast searching and insertion (O(log(n))) + * @brief Data structure for fast searching and insertion in \f$O(\log n)\f$ time * @details * A skip list is a data structure that is used for storing a sorted list of items with a * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items From 5fcf15019e3873bf11386193748388e28c30b684 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 16:41:13 -0400 Subject: [PATCH 48/67] added clang-analyzer checks --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 02bb3916f..1412b563a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: '-*,google-*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' +Checks: '-*,google-*,clang-analyzer-*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false From 1fbd0d59ac276e8ca1e6c8f93995b3470c92cbb4 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Fri, 10 Jul 2020 21:38:04 +0000 Subject: [PATCH 49/67] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 0f7e9a053..bc007bc5f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -201,6 +201,7 @@ ## Search * [Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/binary_search.cpp) * [Exponential Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/exponential_search.cpp) + * [Fibonacci Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/fibonacci_search.cpp) * [Hash Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/hash_search.cpp) * [Interpolation Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/interpolation_search.cpp) * [Interpolation Search2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/interpolation_search2.cpp) From bade26eccaf25c0c0b854c6b76e0588835ccc686 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 18:25:13 -0400 Subject: [PATCH 50/67] disable rand error --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 1412b563a..d7dc7996d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: '-*,google-*,clang-analyzer-*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' +Checks: '-*,google-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.rand,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false From 229334cce6028ad80e30f269ef2220f508f68f54 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 18:37:35 -0400 Subject: [PATCH 51/67] treat clang-tidy warnings as errors --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index d7dc7996d..610c6b28f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,6 @@ --- Checks: '-*,google-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.rand,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' -WarningsAsErrors: '' +WarningsAsErrors: '*' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false FormatStyle: '{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, AlignConsecutiveMacros: true }' From 389d50ea1421b6a15dd0b47476a2bd5dfb392425 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 19:05:42 -0400 Subject: [PATCH 52/67] disable all insecureAPI errors --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 610c6b28f..95431d6da 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: '-*,google-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.rand,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' +Checks: '-*,google-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' WarningsAsErrors: '*' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false From 9a5a62cf127444de0372d275f7c8810501784b65 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 21:47:39 -0400 Subject: [PATCH 53/67] pass multiple files --- .github/workflows/awesome_workflow.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index 2e0792e17..97f705877 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -122,9 +122,11 @@ jobs: if not cpp_files: sys.exit(0) - for cpp_file in cpp_files: - subprocess.run(["clang-tidy-10", "--fix", "-p=build", cpp_file, "--"], + subprocess.run(["clang-tidy-10", "--fix", "-p=build", *cpp_files, "--"], check=True, text=True, stderr=subprocess.STDOUT) + # for cpp_file in cpp_files: + # subprocess.run(["clang-tidy-10", "--fix", "-p=build", cpp_file, "--"], + # check=True, text=True, stderr=subprocess.STDOUT) # print("g++:") # compile_exts = tuple(".c .c++ .cc .cpp .cu .cxx".split()) From 523475b18367d573ae21bd8ae8b45ce8fb565e6b Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 21:58:22 -0400 Subject: [PATCH 54/67] mark all warnings as errors except those that are fixable by clang-tidy --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 95431d6da..272502837 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,6 @@ --- Checks: '-*,google-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' -WarningsAsErrors: '*' +WarningsAsErrors: '*,-google-readability-*,-google-explicit-constructor,-modernize-*,modernize-avoid-c-arrays,-google-explicit-constructor,-performance-move-const-arg,-performance-noexcept-move-constructor,-cppcoreguidelines-init-variables,-cppcoreguidelines-pro-*' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false FormatStyle: '{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, AlignConsecutiveMacros: true }' From dc6f32297567a9888eeb8ed24d26ded0ce5d1f43 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 22:00:57 -0400 Subject: [PATCH 55/67] test commit --- numerical_methods/brent_method_extrema.cpp | 5 ++--- numerical_methods/durand_kerner_roots.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/numerical_methods/brent_method_extrema.cpp b/numerical_methods/brent_method_extrema.cpp index 654a69451..399be5b38 100644 --- a/numerical_methods/brent_method_extrema.cpp +++ b/numerical_methods/brent_method_extrema.cpp @@ -180,14 +180,13 @@ void test2() { } /** - * @brief Test function to find *maxima* for the function + * @brief Test function to find *minima* for the function * \f$f(x)= \cos x\f$ * in the interval \f$[0,12]\f$ * \n Expected result: \f$\pi\approx 3.14159265358979312\f$ */ void test3() { - // define the function to maximize as a lambda function - // since we are maximixing, we negated the function return value + // define the function to minimize as a lambda function std::function func = [](double x) { return std::cos(x); }; std::cout << "Test 3.... "; diff --git a/numerical_methods/durand_kerner_roots.cpp b/numerical_methods/durand_kerner_roots.cpp index 9bf0619b8..23419d1ed 100644 --- a/numerical_methods/durand_kerner_roots.cpp +++ b/numerical_methods/durand_kerner_roots.cpp @@ -212,7 +212,7 @@ void test1() { std::complex(0., -2.) // known expected roots }; - /* initialize root approximations with random values */ + /* Initialize root approximations with random values */ for (int n = 0; n < roots.size(); n++) { roots[n] = std::complex(std::rand() % 100, std::rand() % 100); roots[n] -= 50.f; From 2ca13dd45a5a99e6677149ad4020c03e0e63d646 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Fri, 10 Jul 2020 22:16:14 -0400 Subject: [PATCH 56/67] Revert "test commit" This reverts commit dc6f32297567a9888eeb8ed24d26ded0ce5d1f43. --- numerical_methods/brent_method_extrema.cpp | 5 +++-- numerical_methods/durand_kerner_roots.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/numerical_methods/brent_method_extrema.cpp b/numerical_methods/brent_method_extrema.cpp index 399be5b38..654a69451 100644 --- a/numerical_methods/brent_method_extrema.cpp +++ b/numerical_methods/brent_method_extrema.cpp @@ -180,13 +180,14 @@ void test2() { } /** - * @brief Test function to find *minima* for the function + * @brief Test function to find *maxima* for the function * \f$f(x)= \cos x\f$ * in the interval \f$[0,12]\f$ * \n Expected result: \f$\pi\approx 3.14159265358979312\f$ */ void test3() { - // define the function to minimize as a lambda function + // define the function to maximize as a lambda function + // since we are maximixing, we negated the function return value std::function func = [](double x) { return std::cos(x); }; std::cout << "Test 3.... "; diff --git a/numerical_methods/durand_kerner_roots.cpp b/numerical_methods/durand_kerner_roots.cpp index 23419d1ed..9bf0619b8 100644 --- a/numerical_methods/durand_kerner_roots.cpp +++ b/numerical_methods/durand_kerner_roots.cpp @@ -212,7 +212,7 @@ void test1() { std::complex(0., -2.) // known expected roots }; - /* Initialize root approximations with random values */ + /* initialize root approximations with random values */ for (int n = 0; n < roots.size(); n++) { roots[n] = std::complex(std::rand() % 100, std::rand() % 100); roots[n] -= 50.f; From d34bede6f4e2d94e5b7d2073d26cd11ac7f1352a Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sat, 11 Jul 2020 09:11:31 -0400 Subject: [PATCH 57/67] disable error on cppcoreguidelines-owning-memory see https://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-owning-memory.html for details --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 272502837..381337977 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,6 @@ --- Checks: '-*,google-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' -WarningsAsErrors: '*,-google-readability-*,-google-explicit-constructor,-modernize-*,modernize-avoid-c-arrays,-google-explicit-constructor,-performance-move-const-arg,-performance-noexcept-move-constructor,-cppcoreguidelines-init-variables,-cppcoreguidelines-pro-*' +WarningsAsErrors: '*,-google-readability-*,-google-explicit-constructor,-modernize-*,modernize-avoid-c-arrays,-google-explicit-constructor,-performance-move-const-arg,-performance-noexcept-move-constructor,-cppcoreguidelines-init-variables,-cppcoreguidelines-pro-*,-cppcoreguidelines-owning-memory' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false FormatStyle: '{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, AlignConsecutiveMacros: true }' From 4e12f03c6cbfa42d7f77d06edd08e39cfb901f4b Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sat, 11 Jul 2020 15:09:00 -0400 Subject: [PATCH 58/67] disable move error + enforce c++11 for clang-tidy --- .clang-tidy | 2 +- .github/workflows/awesome_workflow.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 381337977..113d688e7 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,6 @@ --- Checks: '-*,google-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-*,openmp-*,performance-*,portability-*,modernize-*,-modernize-use-trailing-*' -WarningsAsErrors: '*,-google-readability-*,-google-explicit-constructor,-modernize-*,modernize-avoid-c-arrays,-google-explicit-constructor,-performance-move-const-arg,-performance-noexcept-move-constructor,-cppcoreguidelines-init-variables,-cppcoreguidelines-pro-*,-cppcoreguidelines-owning-memory' +WarningsAsErrors: '*,-google-readability-*,-google-explicit-constructor,-modernize-*,modernize-avoid-c-arrays,-performance-move-const-arg,-performance-noexcept-move-constructor,-cppcoreguidelines-init-variables,-cppcoreguidelines-pro-*,-cppcoreguidelines-owning-memory,-clang-analyzer-cplusplus.Move' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false FormatStyle: '{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, AlignConsecutiveMacros: true }' diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index 97f705877..4906a60d8 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -122,7 +122,7 @@ jobs: if not cpp_files: sys.exit(0) - subprocess.run(["clang-tidy-10", "--fix", "-p=build", *cpp_files, "--"], + subprocess.run(["clang-tidy-10", "--fix", "-p=build", "--extra-args=-std=c++11", *cpp_files, "--"], check=True, text=True, stderr=subprocess.STDOUT) # for cpp_file in cpp_files: # subprocess.run(["clang-tidy-10", "--fix", "-p=build", cpp_file, "--"], From 1f32b4e412862d65c819efac7716625915160fc7 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 12 Jul 2020 07:24:57 -0400 Subject: [PATCH 59/67] Fix command syntax (#949) --- .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 4906a60d8..9cff1c48d 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -122,7 +122,7 @@ jobs: if not cpp_files: sys.exit(0) - subprocess.run(["clang-tidy-10", "--fix", "-p=build", "--extra-args=-std=c++11", *cpp_files, "--"], + subprocess.run(["clang-tidy-10", "--fix", "-p=build", "--extra-arg=-std=c++11", *cpp_files, "--"], check=True, text=True, stderr=subprocess.STDOUT) # for cpp_file in cpp_files: # subprocess.run(["clang-tidy-10", "--fix", "-p=build", cpp_file, "--"], From a707d710b58e5921d7f7131932f48f7e7860e7bd Mon Sep 17 00:00:00 2001 From: enqidu Date: Sun, 12 Jul 2020 19:24:46 +0400 Subject: [PATCH 60/67] update --- data_structures/skip_list.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 6159506a0..f0a17815a 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -26,12 +26,9 @@ using std::endl; * Node structure [Key][Node*, Node*...] */ struct Node { - int key; - // pointer of value - void* value; - // Forward Array points to the neighbour (right) - // nodes of the given one in all levels - vector forward; + int key; ///< key integer + void* value; ///< pointer of value + vector forward; ///< nodes of the given one in all levels // Constructor of the node Node(int key, int level, void* value); }; @@ -54,10 +51,8 @@ Node::Node(int key, int level, void* value) { * SkipList class implementation with basic methods */ class SkipList { - // Maximum level of the skiplist - int level; - // Pointer to the header node - Node *header; + int level; ///< Maximum level of the skiplist + Node *header; ///< Pointer to the header node public: SkipList(); int randomLevel(); From f970ce361cd1f17e289068a1e36c19eb362db1a0 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 12 Jul 2020 17:00:27 -0400 Subject: [PATCH 61/67] tidied up code based on error reports by clang-tidy --- data_structures/skip_list.cpp | 422 +++++++++++++++++----------------- 1 file changed, 208 insertions(+), 214 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 373b93dad..d7982f866 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -1,241 +1,235 @@ /** * @file skip_list.cpp - * @brief Data structure for fast searching and insertion in \f$O(\log n)\f$ time + * @brief Data structure for fast searching and insertion in \f$O(\log n)\f$ + * time * @details - * A skip list is a data structure that is used for storing a sorted list of items with a - * help of hierarchy of linked lists that connect increasingly sparse subsequences of the items - * - * References used: [GeeksForGeek](https://www.geeksforgeeks.org/skip-list/), [OpenGenus](https://iq.opengenus.org/skip-list) for PseudoCode and Code + * A skip list is a data structure that is used for storing a sorted list of + * items with a help of hierarchy of linked lists that connect increasingly + * sparse subsequences of the items + * + * References used: [GeeksForGeek](https://www.geeksforgeeks.org/skip-list/), + * [OpenGenus](https://iq.opengenus.org/skip-list) for PseudoCode and Code * @author [enqidu](https://github.com/enqidu) - * . -*/ + * @author [Krishna Vedala](https://github.com/kvedala) + */ -#include -#include +#include #include -#include +#include +#include +#include +#include -using std::vector; -using std::endl; - -#define MAX_LEVEL 2 ///< Maximum level of skip list -#define PROBABILITY 0.5 ///< Current probability for "coin toss" - +/** \namespace data_structure + * \brief Data-structure algorithms + */ +namespace data_structure { +constexpr int MAX_LEVEL = 2; ///< Maximum level of skip list +constexpr float PROBABILITY = 0.5; ///< Current probability for "coin toss" /** * Node structure [Key][Node*, Node*...] -*/ -struct Node { - int key; ///< key integer - void* value; ///< pointer of value - vector forward; ///< nodes of the given one in all levels - // Constructor of the node - Node(int key, int level, void* value); + */ +struct Node { + int key; ///< key integer + void* value; ///< pointer of value + std::vector> + forward; ///< nodes of the given one in all levels + + /** + * Creates node with provided key, level and value + * @param key is number that is used for comparision + * @param level is the maximum level node's going to added + */ + Node(int key, int level, void* value = nullptr) : key(key) { + // Initialization of forward vector + for (int i = 0; i < (level + 1); i++) { + forward.push_back(nullptr); + } + } }; -/** - * Creates node with provided key, level and value - * @param key is number that is used for comparision - * @param level is the maximum level node's going to added -*/ -Node::Node(int key, int level, void* value) { - this->key = key; - - //Initialization of forward vector - for (int i = 0; i < (level+1); i++){ - forward.push_back(nullptr); - } -} - /** * SkipList class implementation with basic methods -*/ -class SkipList { - int level; ///< Maximum level of the skiplist - Node *header; ///< Pointer to the header node -public: - SkipList(); - int randomLevel(); - void insertElement(int, void*); - void deleteElement(int); - void* searchElement(int); - void displayList(); - ~SkipList(); + */ +class SkipList { + int level; ///< Maximum level of the skiplist + std::shared_ptr header; ///< Pointer to the header node + + public: + /** + * Skip List constructor. Initializes header, start + * Node for searching in the list + */ + SkipList() { + level = 0; + // Header initialization + header = std::shared_ptr(new Node(-1, MAX_LEVEL)); + } + + /** + * Destructor for skiplist class + */ + ~SkipList() { + for (int i = 0; i <= level; i++) { + std::shared_ptr node = header->forward[i]; + std::shared_ptr temp; + while (node != nullptr) { + temp = node; + node = node->forward[i]; + temp.reset(); + } + } + header.reset(); + } + + /** + * Returns random level of the skip list. + * Every higher level is 2 times less likely. + * @return random level for skip list + */ + int randomLevel() { + int lvl = 0; + while (static_cast(std::rand() / RAND_MAX) < PROBABILITY && + lvl < MAX_LEVEL) + lvl++; + return lvl; + } + + /** + * Inserts elements with given key and value; + * It's level is computed by randomLevel() function. + * @param key is number that is used for comparision + * @param value pointer to a value, that can be any type + */ + void insertElement(int key, void* value) { + std::cout << "Inserting" << key << "..."; + std::shared_ptr x = header; + std::array, MAX_LEVEL + 1> update; + update.fill(nullptr); + + for (int i = level; i >= 0; i--) { + while (x->forward[i] != nullptr && x->forward[i]->key < key) + x = x->forward[i]; + update[i] = x; + } + + x = x->forward[0]; + + bool doesnt_exist = (x == nullptr || x->key != key); + if (doesnt_exist) { + int rlevel = randomLevel(); + + if (rlevel > level) { + for (int i = level + 1; i < rlevel + 1; i++) update[i] = header; + + // Update current level + level = rlevel; + } + + std::shared_ptr n = + std::shared_ptr(new Node(key, rlevel, value)); + for (int i = 0; i <= rlevel; i++) { + n->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = n; + } + std::cout << "Inserted" << std::endl; + + } else { + std::cout << "Exists" << std::endl; + } + } + + /** + * Deletes an element by key and prints if has been removed successfully + * @param key is number that is used for comparision. + */ + void deleteElement(int key) { + std::shared_ptr x = header; + + std::array, MAX_LEVEL + 1> update; + update.fill(nullptr); + + for (int i = level; i >= 0; i--) { + while (x->forward[i] != nullptr && x->forward[i]->key < key) + x = x->forward[i]; + update[i] = x; + } + + x = x->forward[0]; + + bool doesnt_exist = (x == nullptr || x->key != key); + + if (!doesnt_exist) { + for (int i = 0; i <= level; i++) { + if (update[i]->forward[i] != x) + break; + update[i]->forward[i] = x->forward[i]; + } + /* Remove empty levels*/ + while (level > 0 && header->forward[level] == nullptr) level--; + std::cout << "Deleted" << std::endl; + } else { + std::cout << "Doesn't exist" << std::endl; + } + } + + /** + * Searching element in skip list structure + * @param key is number that is used for comparision + * @return pointer to the value of the node + */ + void* searchElement(int key) { + std::shared_ptr x = header; + std::cout << "Searching for " << key << std::endl; + + for (int i = level; i >= 0; i--) { + while (x->forward[i] && x->forward[i]->key < key) x = x->forward[i]; + } + + x = x->forward[0]; + if (x && x->key == key) { + std::cout << "Found" << std::endl; + return x->value; + } else { + std::cout << "Not Found" << std::endl; + return nullptr; + } + } + + /* + * Display skip list level + */ + void displayList() { + std::cout << "Displaying list:\n" << std::endl; + for (int i = 0; i <= level; i++) { + std::shared_ptr node = header->forward[i]; + std::cout << "Level " << (i) << ": "; + while (node != nullptr) { + std::cout << node->key << " "; + node = node->forward[i]; + } + std::cout << std::endl; + } + } }; - -/** - * Skeep List constructor. Initializes header, start - * Node for searching in the list -*/ -SkipList::SkipList() { - level = 0; - // Header initialization - header = new Node(-1, MAX_LEVEL, nullptr); -} - -/** - * Destructor for skiplist class -*/ -SkipList::~SkipList(){ - for(int i=0; i <= level; i++) { - Node *node = header->forward[i]; - Node* temp; - while(node != nullptr) { - temp = node; - node = node->forward[i]; - delete temp; - } - } - delete header; -} - - -/** - * Returns random level of the skip list. - * Every higher level is 2 times less likely. - * @return lvl: random level for skip list; -*/ -int SkipList::randomLevel() { - int lvl = 0; - while(static_cast(std::rand())/RAND_MAX < PROBABILITY && lvl < MAX_LEVEL) lvl++; - return lvl; -} - - - -/** - * Inserts elements with given key and value; - * It's level is computed by randomLevel() function. - * @param key is number that is used for comparision - * @param value pointer to a value, that can be any type -*/ -void SkipList::insertElement(int key, void* value) { - std::cout << "Inserting" << key << "..."; - Node *x = header; - Node *update[MAX_LEVEL+1]; - memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); - - - for(int i = level; i >= 0; i--) { - while(x->forward[i] != nullptr && x->forward[i]->key < key) x = x->forward[i]; - update[i] = x; - } - - x = x->forward[0]; - - bool doesnt_exist = (x == nullptr || x->key != key); - if (doesnt_exist) { - int rlevel = randomLevel(); - - if(rlevel > level) { - for(int i=level+1;iforward[i] = update[i]->forward[i]; - update[i]->forward[i] = n; - } - std::cout << "Inserted" << endl; - - } else { - std::cout << "Exists" << endl; - } -} - -/** - * Deletes an element by key and prints if has been removed successfully - * @param key is number that is used for comparision. -*/ -void SkipList::deleteElement(int key) { - Node *x = header; - - Node *update[MAX_LEVEL+1]; - memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); - - for(int i = level; i >= 0; i--) { - while(x->forward[i] != nullptr && x->forward[i]->key < key) x = x->forward[i]; - update[i] = x; - } - - x = x->forward[0]; - - bool doesnt_exist = (x == nullptr || x->key != key); - - if(!doesnt_exist) { - for(int i=0;i<=level;i++) { - if(update[i]->forward[i] != x) break; - update[i]->forward[i] = x->forward[i]; - } - /* Remove empty levels*/ - while(level>0 && header->forward[level] == 0) level--; - std::cout << "Deleted" << endl; - } else { - std::cout << "Doesn't exist" << endl; - } -} - - -/** - * Searching element in skip list structure - * @param key is number that is used for comparision - * @return pointer to the value of the node -*/ -void* SkipList::searchElement(int key) { - Node *x = header; - std::cout << "Searching for " + key << endl; - - for(int i = level; i >= 0; i--) { - while(x->forward[i] && x->forward[i]->key < key) x = x->forward[i]; - } - - x = x->forward[0]; - if(x && x->key == key){ - std::cout << "Found" << endl; - return x->value; - } else { - std::cout << "Not Found" << endl; - return nullptr; - } -} - -/* - * Display skip list level - */ -void SkipList::displayList() { - std::cout << "Displaying list:\n" << endl; - for(int i=0; i <= level; i++) { - Node *node = header->forward[i]; - std::cout << "Level " << (i) << ": "; - while(node != nullptr) { - std::cout << node->key << " "; - node = node->forward[i]; - } - std::cout << endl; - } -} - +} // namespace data_structure /** * Main function: * Creates and inserts random 2^[number of levels] * elements into the skip lists and than displays it - */ -int main() -{ + */ +int main() { std::srand(std::time(nullptr)); - SkipList lst; + data_structure::SkipList lst; - for (int j = 0; j < (1 << (MAX_LEVEL+1)); j++){ - int k = (std::rand()%( 1 << (MAX_LEVEL+2)) + 1); - lst.insertElement(k, &j); + for (int j = 0; j < (1 << (data_structure::MAX_LEVEL + 1)); j++) { + int k = (std::rand() % (1 << (data_structure::MAX_LEVEL + 2)) + 1); + lst.insertElement(k, &j); } lst.displayList(); - -} +} From c15c962f02d284f50b7a62b4af92fe2ef696a7a1 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 12 Jul 2020 17:04:09 -0400 Subject: [PATCH 62/67] since we are using smart pointers, an explicit destructor is not required --- data_structures/skip_list.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index d7982f866..2cb78b8c8 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -67,22 +67,6 @@ class SkipList { header = std::shared_ptr(new Node(-1, MAX_LEVEL)); } - /** - * Destructor for skiplist class - */ - ~SkipList() { - for (int i = 0; i <= level; i++) { - std::shared_ptr node = header->forward[i]; - std::shared_ptr temp; - while (node != nullptr) { - temp = node; - node = node->forward[i]; - temp.reset(); - } - } - header.reset(); - } - /** * Returns random level of the skip list. * Every higher level is 2 times less likely. From 47f5ad9aaf0f497afec0bdcbb0138c344b9364e8 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 12 Jul 2020 17:47:57 -0400 Subject: [PATCH 63/67] fix randomlevel float conversion --- data_structures/skip_list.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 2cb78b8c8..b1b24ea20 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -41,7 +41,7 @@ struct Node { * @param key is number that is used for comparision * @param level is the maximum level node's going to added */ - Node(int key, int level, void* value = nullptr) : key(key) { + Node(int key, int level, void* value = nullptr) : key(key), value(value) { // Initialization of forward vector for (int i = 0; i < (level + 1); i++) { forward.push_back(nullptr); @@ -74,7 +74,7 @@ class SkipList { */ int randomLevel() { int lvl = 0; - while (static_cast(std::rand() / RAND_MAX) < PROBABILITY && + while (static_cast(std::rand()) / RAND_MAX < PROBABILITY && lvl < MAX_LEVEL) lvl++; return lvl; @@ -185,7 +185,7 @@ class SkipList { * Display skip list level */ void displayList() { - std::cout << "Displaying list:\n" << std::endl; + std::cout << "Displaying list:\n"; for (int i = 0; i <= level; i++) { std::shared_ptr node = header->forward[i]; std::cout << "Level " << (i) << ": "; From 8ab9a2ae939b915f0da7d5daacb03eec2aed91c1 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Mon, 13 Jul 2020 07:52:38 -0400 Subject: [PATCH 64/67] [cpp fixes] tidied up code based on error reports by clang-tidy (#950) * tidied up code based on error reports by clang-tidy * added doc for activation function --- machine_learning/adaline_learning.cpp | 107 ++++++++------ machine_learning/kohonen_som_topology.cpp | 130 ++++++++++-------- machine_learning/kohonen_som_trace.cpp | 88 +++++++----- .../ordinary_least_squares_regressor.cpp | 48 ++++--- numerical_methods/newton_raphson_method.cpp | 11 +- numerical_methods/ode_forward_euler.cpp | 31 +++-- 6 files changed, 243 insertions(+), 172 deletions(-) diff --git a/machine_learning/adaline_learning.cpp b/machine_learning/adaline_learning.cpp index a8426ac4e..6da839a9d 100644 --- a/machine_learning/adaline_learning.cpp +++ b/machine_learning/adaline_learning.cpp @@ -26,6 +26,7 @@ * computed using stochastic gradient descent method. */ +#include #include #include #include @@ -35,7 +36,8 @@ #include #include -#define MAX_ITER 500 // INT_MAX ///< Maximum number of iterations to learn +/** Maximum number of iterations to learn */ +constexpr int MAX_ITER = 500; // INT_MAX /** \namespace machine_learning * \brief Machine learning algorithms @@ -50,8 +52,8 @@ class adaline { * \param[in] convergence accuracy (optional, * default=\f$1\times10^{-5}\f$) */ - adaline(int num_features, const double eta = 0.01f, - const double accuracy = 1e-5) + explicit adaline(int num_features, const double eta = 0.01f, + const double accuracy = 1e-5) : eta(eta), accuracy(accuracy) { if (eta <= 0) { std::cerr << "learning rate should be positive and nonzero" @@ -64,7 +66,7 @@ class adaline { 1); // additional weight is for the constant bias term // initialize with random weights in the range [-50, 49] - for (int i = 0; i < weights.size(); i++) weights[i] = 1.f; + for (double &weight : weights) weight = 1.f; // weights[i] = (static_cast(std::rand() % 100) - 50); } @@ -75,8 +77,9 @@ class adaline { out << "<"; for (int i = 0; i < ada.weights.size(); i++) { out << ada.weights[i]; - if (i < ada.weights.size() - 1) + if (i < ada.weights.size() - 1) { out << ", "; + } } out << ">"; return out; @@ -90,28 +93,33 @@ class adaline { * model prediction output */ int predict(const std::vector &x, double *out = nullptr) { - if (!check_size_match(x)) + if (!check_size_match(x)) { return 0; + } double y = weights.back(); // assign bias value // for (int i = 0; i < x.size(); i++) y += x[i] * weights[i]; y = std::inner_product(x.begin(), x.end(), weights.begin(), y); - if (out != nullptr) // if out variable is provided + if (out != nullptr) { // if out variable is provided *out = y; + } return activation(y); // quantizer: apply ADALINE threshold function } /** * Update the weights of the model using supervised learning for one - * feature vector \param[in] x feature vector \param[in] y known output - * value \returns correction factor + * feature vector + * \param[in] x feature vector + * \param[in] y known output value + * \returns correction factor */ double fit(const std::vector &x, const int &y) { - if (!check_size_match(x)) + if (!check_size_match(x)) { return 0; + } /* output of the model with current weights */ int p = predict(x); @@ -129,21 +137,23 @@ class adaline { /** * Update the weights of the model using supervised learning for an - * array of vectors. \param[in] X array of feature vector \param[in] y - * known output value for each feature vector + * array of vectors. + * \param[in] X array of feature vector + * \param[in] y known output value for each feature vector */ - template - void fit(std::vector const (&X)[N], const int *y) { + template + void fit(std::array, N> const &X, + std::array const &Y) { double avg_pred_error = 1.f; - int iter; + int iter = 0; for (iter = 0; (iter < MAX_ITER) && (avg_pred_error > accuracy); iter++) { avg_pred_error = 0.f; // perform fit for each sample for (int i = 0; i < N; i++) { - double err = fit(X[i], y[i]); + double err = fit(X[i], Y[i]); avg_pred_error += std::abs(err); } avg_pred_error /= N; @@ -154,15 +164,25 @@ class adaline { << "\tAvg error: " << avg_pred_error << std::endl; } - if (iter < MAX_ITER) - + if (iter < MAX_ITER) { std::cout << "Converged after " << iter << " iterations." << std::endl; - else + } else { std::cout << "Did not converge after " << iter << " iterations." << std::endl; + } } + /** Defines activation function as Heaviside's step function. + * \f[ + * f(x) = \begin{cases} + * -1 & \forall x \le 0\\ + * 1 & \forall x > 0 + * \end{cases} + * \f] + * @param x input value to apply activation on + * @return activation output + */ int activation(double x) { return x > 0 ? 1 : -1; } private: @@ -206,15 +226,19 @@ void test1(double eta = 0.01) { const int N = 10; // number of sample points - std::vector X[N] = {{0, 1}, {1, -2}, {2, 3}, {3, -1}, - {4, 1}, {6, -5}, {-7, -3}, {-8, 5}, - {-9, 2}, {-10, -15}}; - int y[] = {1, -1, 1, -1, -1, -1, 1, 1, 1, -1}; // corresponding y-values + std::array, N> X = { + std::vector({0, 1}), std::vector({1, -2}), + std::vector({2, 3}), std::vector({3, -1}), + std::vector({4, 1}), std::vector({6, -5}), + std::vector({-7, -3}), std::vector({-8, 5}), + std::vector({-9, 2}), std::vector({-10, -15})}; + std::array y = {1, -1, 1, -1, -1, + -1, 1, 1, 1, -1}; // corresponding y-values std::cout << "------- Test 1 -------" << std::endl; std::cout << "Model before fit: " << ada << std::endl; - ada.fit(X, y); + ada.fit(X, y); std::cout << "Model after fit: " << ada << std::endl; int predict = ada.predict({5, -3}); @@ -240,17 +264,17 @@ void test2(double eta = 0.01) { const int N = 50; // number of sample points - std::vector X[N]; - int Y[N]; // corresponding y-values + std::array, N> X; + std::array Y{}; // corresponding y-values // generate sample points in the interval // [-range2/100 , (range2-1)/100] int range = 500; // sample points full-range int range2 = range >> 1; // sample points half-range for (int i = 0; i < N; i++) { - double x0 = ((std::rand() % range) - range2) / 100.f; - double x1 = ((std::rand() % range) - range2) / 100.f; - X[i] = {x0, x1}; + double x0 = (static_cast(std::rand() % range) - range2) / 100.f; + double x1 = (static_cast(std::rand() % range) - range2) / 100.f; + X[i] = std::vector({x0, x1}); Y[i] = (x0 + 3. * x1) > -1 ? 1 : -1; } @@ -262,8 +286,8 @@ void test2(double eta = 0.01) { int N_test_cases = 5; for (int i = 0; i < N_test_cases; i++) { - double x0 = ((std::rand() % range) - range2) / 100.f; - double x1 = ((std::rand() % range) - range2) / 100.f; + double x0 = (static_cast(std::rand() % range) - range2) / 100.f; + double x1 = (static_cast(std::rand() % range) - range2) / 100.f; int predict = ada.predict({x0, x1}); @@ -291,18 +315,18 @@ void test3(double eta = 0.01) { const int N = 100; // number of sample points - std::vector X[N]; - int Y[N]; // corresponding y-values + std::array, N> X; + std::array Y{}; // corresponding y-values // generate sample points in the interval // [-range2/100 , (range2-1)/100] int range = 200; // sample points full-range int range2 = range >> 1; // sample points half-range for (int i = 0; i < N; i++) { - double x0 = ((std::rand() % range) - range2) / 100.f; - double x1 = ((std::rand() % range) - range2) / 100.f; - double x2 = ((std::rand() % range) - range2) / 100.f; - X[i] = {x0, x1, x2, x0 * x0, x1 * x1, x2 * x2}; + double x0 = (static_cast(std::rand() % range) - range2) / 100.f; + double x1 = (static_cast(std::rand() % range) - range2) / 100.f; + double x2 = (static_cast(std::rand() % range) - range2) / 100.f; + X[i] = std::vector({x0, x1, x2, x0 * x0, x1 * x1, x2 * x2}); Y[i] = ((x0 * x0) + (x1 * x1) + (x2 * x2)) <= 1.f ? 1 : -1; } @@ -314,9 +338,9 @@ void test3(double eta = 0.01) { int N_test_cases = 5; for (int i = 0; i < N_test_cases; i++) { - double x0 = ((std::rand() % range) - range2) / 100.f; - double x1 = ((std::rand() % range) - range2) / 100.f; - double x2 = ((std::rand() % range) - range2) / 100.f; + double x0 = (static_cast(std::rand() % range) - range2) / 100.f; + double x1 = (static_cast(std::rand() % range) - range2) / 100.f; + double x2 = (static_cast(std::rand() % range) - range2) / 100.f; int predict = ada.predict({x0, x1, x2, x0 * x0, x1 * x1, x2 * x2}); @@ -334,8 +358,9 @@ int main(int argc, char **argv) { std::srand(std::time(nullptr)); // initialize random number generator double eta = 0.1; // default value of eta - if (argc == 2) // read eta value from commandline argument if present + if (argc == 2) { // read eta value from commandline argument if present eta = strtof(argv[1], nullptr); + } test1(eta); diff --git a/machine_learning/kohonen_som_topology.cpp b/machine_learning/kohonen_som_topology.cpp index 016fe6d1e..cccc9faa3 100644 --- a/machine_learning/kohonen_som_topology.cpp +++ b/machine_learning/kohonen_som_topology.cpp @@ -25,8 +25,11 @@ */ #define _USE_MATH_DEFINES //< required for MS Visual C++ #include +#include +#include #include #include +#include #include #include #include @@ -68,7 +71,8 @@ int save_2d_data(const char *fname, fp.open(fname); if (!fp.is_open()) { // error with opening file to write - std::cerr << "Error opening file " << fname << "\n"; + std::cerr << "Error opening file " << fname << ": " + << std::strerror(errno) << "\n"; return -1; } @@ -76,12 +80,14 @@ int save_2d_data(const char *fname, for (int i = 0; i < num_points; i++) { // for each feature in the array for (int j = 0; j < num_features; j++) { - fp << X[i][j]; // print the feature value - if (j < num_features - 1) // if not the last feature - fp << ","; // suffix comma + fp << X[i][j]; // print the feature value + if (j < num_features - 1) { // if not the last feature + fp << ","; // suffix comma + } + } + if (i < num_points - 1) { // if not the last row + fp << "\n"; // start a new line } - if (i < num_points - 1) // if not the last row - fp << "\n"; // start a new line } fp.close(); @@ -99,12 +105,12 @@ int save_2d_data(const char *fname, void get_min_2d(const std::vector> &X, double *val, int *x_idx, int *y_idx) { val[0] = INFINITY; // initial min value - int N = X.size(); + size_t N = X.size(); for (int i = 0; i < N; i++) { // traverse each x-index auto result = std::min_element(std::begin(X[i]), std::end(X[i])); double d_min = *result; - int j = std::distance(std::begin(X[i]), result); + std::ptrdiff_t j = std::distance(std::begin(X[i]), result); if (d_min < val[0]) { // if a lower value is found // save the value and its index @@ -119,7 +125,8 @@ void get_min_2d(const std::vector> &X, double *val, * \brief Machine learning algorithms */ namespace machine_learning { -#define MIN_DISTANCE 1e-4 ///< Minimum average distance of image nodes +/** Minimum average distance of image nodes */ +constexpr double MIN_DISTANCE = 1e-4; /** * Create the distance matrix or @@ -136,9 +143,8 @@ int save_u_matrix(const char *fname, const std::vector>> &W) { std::ofstream fp(fname); if (!fp) { // error with fopen - char msg[120]; - std::snprintf(msg, sizeof(msg), "File error (%s): ", fname); - std::perror(msg); + std::cerr << "File error (" << fname << "): " << std::strerror(errno) + << std::endl; return -1; } @@ -153,7 +159,7 @@ int save_u_matrix(const char *fname, int to_x = std::min(W.size(), i + R + 1); int from_y = std::max(0, j - R); int to_y = std::min(W[0].size(), j + R + 1); - int l, m; + int l = 0, m = 0; #ifdef _OPENMP #pragma omp parallel for reduction(+ : distance) #endif @@ -172,8 +178,9 @@ int save_u_matrix(const char *fname, fp << ','; // suffix comma } } - if (i < W.size() - 1) // if not the last row - fp << '\n'; // start a new line + if (i < W.size() - 1) { // if not the last row + fp << '\n'; // start a new line + } } fp.close(); @@ -194,10 +201,11 @@ double update_weights(const std::valarray &X, std::vector>> *W, std::vector> *D, double alpha, int R) { - int x, y; + int x = 0, y = 0; int num_out_x = static_cast(W->size()); // output nodes - in X int num_out_y = static_cast(W[0][0].size()); // output nodes - in Y - int num_features = static_cast(W[0][0][0].size()); // features = in Z + // int num_features = static_cast(W[0][0][0].size()); // features = + // in Z double d_min = 0.f; #ifdef _OPENMP @@ -217,7 +225,7 @@ double update_weights(const std::valarray &X, // step 2: get closest node i.e., node with snallest Euclidian distance // to the current pattern - int d_min_x, d_min_y; + int d_min_x = 0, d_min_y = 0; get_min_2d(*D, &d_min, &d_min_x, &d_min_y); // step 3a: get the neighborhood range @@ -261,10 +269,10 @@ double update_weights(const std::valarray &X, void kohonen_som(const std::vector> &X, std::vector>> *W, double alpha_min) { - int num_samples = X.size(); // number of rows - int num_features = X[0].size(); // number of columns - int num_out = W->size(); // output matrix size - int R = num_out >> 2, iter = 0; + size_t num_samples = X.size(); // number of rows + // size_t num_features = X[0].size(); // number of columns + size_t num_out = W->size(); // output matrix size + size_t R = num_out >> 2, iter = 0; double alpha = 1.f; std::vector> D(num_out); @@ -283,15 +291,17 @@ void kohonen_som(const std::vector> &X, } // every 100th iteration, reduce the neighborhood range - if (iter % 300 == 0 && R > 1) + if (iter % 300 == 0 && R > 1) { R--; + } dmin /= num_samples; // termination condition variable -> % change in minimum distance dmin_ratio = (past_dmin - dmin) / past_dmin; - if (dmin_ratio < 0) + if (dmin_ratio < 0) { dmin_ratio = 1.f; + } past_dmin = dmin; std::cout << "iter: " << iter << "\t alpha: " << alpha << "\t R: " << R @@ -320,14 +330,14 @@ using machine_learning::save_u_matrix; void test_2d_classes(std::vector> *data) { const int N = data->size(); const double R = 0.3; // radius of cluster - int i; + int i = 0; const int num_classes = 4; - const double centres[][2] = { + std::array, num_classes> centres = { // centres of each class cluster - {.5, .5}, // centre of class 1 - {.5, -.5}, // centre of class 2 - {-.5, .5}, // centre of class 3 - {-.5, -.5} // centre of class 4 + std::array({.5, .5}), // centre of class 1 + std::array({.5, -.5}), // centre of class 2 + std::array({-.5, .5}), // centre of class 3 + std::array({-.5, -.5}) // centre of class 4 }; #ifdef _OPENMP @@ -357,15 +367,16 @@ void test_2d_classes(std::vector> *data) { * * `w12.csv`: trained SOM map */ void test1() { - int j, N = 300; + int j = 0, N = 300; int features = 2; int num_out = 30; std::vector> X(N); std::vector>> W(num_out); for (int i = 0; i < std::max(num_out, N); i++) { // loop till max(N, num_out) - if (i < N) // only add new arrays if i < N + if (i < N) { // only add new arrays if i < N X[i] = std::valarray(features); + } if (i < num_out) { // only add new arrays if i < num_out W[i] = std::vector>(num_out); for (int k = 0; k < num_out; k++) { @@ -373,9 +384,10 @@ void test1() { #ifdef _OPENMP #pragma omp for #endif - for (j = 0; j < features; j++) + for (j = 0; j < features; j++) { // preallocate with random initial weights W[i][k][j] = _random(-10, 10); + } } } } @@ -397,16 +409,16 @@ void test1() { * \param[out] data matrix to store data in */ void test_3d_classes1(std::vector> *data) { - const int N = data->size(); + const size_t N = data->size(); const double R = 0.3; // radius of cluster - int i; + int i = 0; const int num_classes = 4; - const double centres[][3] = { + const std::array, num_classes> centres = { // centres of each class cluster - {.5, .5, .5}, // centre of class 1 - {.5, -.5, -.5}, // centre of class 2 - {-.5, .5, .5}, // centre of class 3 - {-.5, -.5 - .5} // centre of class 4 + std::array({.5, .5, .5}), // centre of class 1 + std::array({.5, -.5, -.5}), // centre of class 2 + std::array({-.5, .5, .5}), // centre of class 3 + std::array({-.5, -.5 - .5}) // centre of class 4 }; #ifdef _OPENMP @@ -437,15 +449,16 @@ void test_3d_classes1(std::vector> *data) { * * `w22.csv`: trained SOM map */ void test2() { - int j, N = 300; + int j = 0, N = 300; int features = 3; int num_out = 30; std::vector> X(N); std::vector>> W(num_out); for (int i = 0; i < std::max(num_out, N); i++) { // loop till max(N, num_out) - if (i < N) // only add new arrays if i < N + if (i < N) { // only add new arrays if i < N X[i] = std::valarray(features); + } if (i < num_out) { // only add new arrays if i < num_out W[i] = std::vector>(num_out); for (int k = 0; k < num_out; k++) { @@ -453,9 +466,10 @@ void test2() { #ifdef _OPENMP #pragma omp for #endif - for (j = 0; j < features; j++) + for (j = 0; j < features; j++) { // preallocate with random initial weights W[i][k][j] = _random(-10, 10); + } } } } @@ -477,20 +491,20 @@ void test2() { * \param[out] data matrix to store data in */ void test_3d_classes2(std::vector> *data) { - const int N = data->size(); + const size_t N = data->size(); const double R = 0.2; // radius of cluster - int i; + int i = 0; const int num_classes = 8; - const double centres[][3] = { + const std::array, num_classes> centres = { // centres of each class cluster - {.5, .5, .5}, // centre of class 1 - {.5, .5, -.5}, // centre of class 2 - {.5, -.5, .5}, // centre of class 3 - {.5, -.5, -.5}, // centre of class 4 - {-.5, .5, .5}, // centre of class 5 - {-.5, .5, -.5}, // centre of class 6 - {-.5, -.5, .5}, // centre of class 7 - {-.5, -.5, -.5} // centre of class 8 + std::array({.5, .5, .5}), // centre of class 1 + std::array({.5, .5, -.5}), // centre of class 2 + std::array({.5, -.5, .5}), // centre of class 3 + std::array({.5, -.5, -.5}), // centre of class 4 + std::array({-.5, .5, .5}), // centre of class 5 + std::array({-.5, .5, -.5}), // centre of class 6 + std::array({-.5, -.5, .5}), // centre of class 7 + std::array({-.5, -.5, -.5}) // centre of class 8 }; #ifdef _OPENMP @@ -521,15 +535,16 @@ void test_3d_classes2(std::vector> *data) { * * `w32.csv`: trained SOM map */ void test3() { - int j, N = 500; + int j = 0, N = 500; int features = 3; int num_out = 30; std::vector> X(N); std::vector>> W(num_out); for (int i = 0; i < std::max(num_out, N); i++) { // loop till max(N, num_out) - if (i < N) // only add new arrays if i < N + if (i < N) { // only add new arrays if i < N X[i] = std::valarray(features); + } if (i < num_out) { // only add new arrays if i < num_out W[i] = std::vector>(num_out); for (int k = 0; k < num_out; k++) { @@ -537,9 +552,10 @@ void test3() { #ifdef _OPENMP #pragma omp for #endif - for (j = 0; j < features; j++) + for (j = 0; j < features; j++) { // preallocate with random initial weights W[i][k][j] = _random(-10, 10); + } } } } diff --git a/machine_learning/kohonen_som_trace.cpp b/machine_learning/kohonen_som_trace.cpp index 273a2a57c..63a0c02c6 100644 --- a/machine_learning/kohonen_som_trace.cpp +++ b/machine_learning/kohonen_som_trace.cpp @@ -20,6 +20,7 @@ */ #define _USE_MATH_DEFINES // required for MS Visual C++ #include +#include #include #include #include @@ -71,12 +72,14 @@ int save_nd_data(const char *fname, for (int i = 0; i < num_points; i++) { // for each feature in the array for (int j = 0; j < num_features; j++) { - fp << X[i][j]; // print the feature value - if (j < num_features - 1) // if not the last feature - fp << ","; // suffix comma + fp << X[i][j]; // print the feature value + if (j < num_features - 1) { // if not the last feature + fp << ","; // suffix comma + } + } + if (i < num_points - 1) { // if not the last row + fp << "\n"; // start a new line } - if (i < num_points - 1) // if not the last row - fp << "\n"; // start a new line } fp.close(); @@ -100,9 +103,9 @@ namespace machine_learning { void update_weights(const std::valarray &x, std::vector> *W, std::valarray *D, double alpha, int R) { - int j, k; - int num_out = W->size(); // number of SOM output nodes - int num_features = x.size(); // number of data features + int j = 0, k = 0; + int num_out = W->size(); // number of SOM output nodes + // int num_features = x.size(); // number of data features #ifdef _OPENMP #pragma omp for @@ -117,7 +120,7 @@ void update_weights(const std::valarray &x, // step 2: get closest node i.e., node with snallest Euclidian distance to // the current pattern auto result = std::min_element(std::begin(*D), std::end(*D)); - double d_min = *result; + // double d_min = *result; int d_min_idx = std::distance(std::begin(*D), result); // step 3a: get the neighborhood range @@ -129,9 +132,10 @@ void update_weights(const std::valarray &x, #ifdef _OPENMP #pragma omp for #endif - for (j = from_node; j < to_node; j++) + for (j = from_node; j < to_node; j++) { // update weights of nodes in the neighborhood (*W)[j] += alpha * (x - (*W)[j]); + } } /** @@ -145,16 +149,16 @@ void update_weights(const std::valarray &x, void kohonen_som_tracer(const std::vector> &X, std::vector> *W, double alpha_min) { - int num_samples = X.size(); // number of rows - int num_features = X[0].size(); // number of columns - int num_out = W->size(); // number of rows + int num_samples = X.size(); // number of rows + // int num_features = X[0].size(); // number of columns + int num_out = W->size(); // number of rows int R = num_out >> 2, iter = 0; double alpha = 1.f; std::valarray D(num_out); // Loop alpha from 1 to slpha_min - for (; alpha > alpha_min; alpha -= 0.01, iter++) { + do { // Loop for each sample pattern in the data set for (int sample = 0; sample < num_samples; sample++) { // update weights for the current input pattern sample @@ -162,9 +166,13 @@ void kohonen_som_tracer(const std::vector> &X, } // every 10th iteration, reduce the neighborhood range - if (iter % 10 == 0 && R > 1) + if (iter % 10 == 0 && R > 1) { R--; - } + } + + alpha -= 0.01; + iter++; + } while (alpha > alpha_min); } } // namespace machine_learning @@ -190,7 +198,7 @@ void test_circle(std::vector> *data) { const double R = 0.75, dr = 0.3; double a_t = 0., b_t = 2.f * M_PI; // theta random between 0 and 2*pi double a_r = R - dr, b_r = R + dr; // radius random between R-dr and R+dr - int i; + int i = 0; #ifdef _OPENMP #pragma omp for @@ -223,24 +231,26 @@ void test_circle(std::vector> *data) { * output](https://raw.githubusercontent.com/TheAlgorithms/C-Plus-Plus/docs/images/machine_learning/kohonen/test1.svg) */ void test1() { - int j, N = 500; + int j = 0, N = 500; int features = 2; int num_out = 50; std::vector> X(N); std::vector> W(num_out); for (int i = 0; i < std::max(num_out, N); i++) { // loop till max(N, num_out) - if (i < N) // only add new arrays if i < N + if (i < N) { // only add new arrays if i < N X[i] = std::valarray(features); + } if (i < num_out) { // only add new arrays if i < num_out W[i] = std::valarray(features); #ifdef _OPENMP #pragma omp for #endif - for (j = 0; j < features; j++) + for (j = 0; j < features; j++) { // preallocate with random initial weights W[i][j] = _random(-1, 1); + } } } @@ -267,7 +277,7 @@ void test1() { void test_lamniscate(std::vector> *data) { const int N = data->size(); const double dr = 0.2; - int i; + int i = 0; #ifdef _OPENMP #pragma omp for @@ -303,24 +313,26 @@ void test_lamniscate(std::vector> *data) { * output](https://raw.githubusercontent.com/TheAlgorithms/C-Plus-Plus/docs/images/machine_learning/kohonen/test2.svg) */ void test2() { - int j, N = 500; + int j = 0, N = 500; int features = 2; int num_out = 20; std::vector> X(N); std::vector> W(num_out); for (int i = 0; i < std::max(num_out, N); i++) { // loop till max(N, num_out) - if (i < N) // only add new arrays if i < N + if (i < N) { // only add new arrays if i < N X[i] = std::valarray(features); + } if (i < num_out) { // only add new arrays if i < num_out W[i] = std::valarray(features); #ifdef _OPENMP #pragma omp for #endif - for (j = 0; j < features; j++) + for (j = 0; j < features; j++) { // preallocate with random initial weights W[i][j] = _random(-1, 1); + } } } @@ -347,18 +359,18 @@ void test2() { void test_3d_classes(std::vector> *data) { const int N = data->size(); const double R = 0.1; // radius of cluster - int i; + int i = 0; const int num_classes = 8; - const double centres[][3] = { + const std::array, num_classes> centres = { // centres of each class cluster - {.5, .5, .5}, // centre of class 0 - {.5, .5, -.5}, // centre of class 1 - {.5, -.5, .5}, // centre of class 2 - {.5, -.5, -.5}, // centre of class 3 - {-.5, .5, .5}, // centre of class 4 - {-.5, .5, -.5}, // centre of class 5 - {-.5, -.5, .5}, // centre of class 6 - {-.5, -.5, -.5} // centre of class 7 + std::array({.5, .5, .5}), // centre of class 0 + std::array({.5, .5, -.5}), // centre of class 1 + std::array({.5, -.5, .5}), // centre of class 2 + std::array({.5, -.5, -.5}), // centre of class 3 + std::array({-.5, .5, .5}), // centre of class 4 + std::array({-.5, .5, -.5}), // centre of class 5 + std::array({-.5, -.5, .5}), // centre of class 6 + std::array({-.5, -.5, -.5}) // centre of class 7 }; #ifdef _OPENMP @@ -400,24 +412,26 @@ void test_3d_classes(std::vector> *data) { * output](https://raw.githubusercontent.com/TheAlgorithms/C-Plus-Plus/docs/images/machine_learning/kohonen/test3.svg) */ void test3() { - int j, N = 200; + int j = 0, N = 200; int features = 3; int num_out = 20; std::vector> X(N); std::vector> W(num_out); for (int i = 0; i < std::max(num_out, N); i++) { // loop till max(N, num_out) - if (i < N) // only add new arrays if i < N + if (i < N) { // only add new arrays if i < N X[i] = std::valarray(features); + } if (i < num_out) { // only add new arrays if i < num_out W[i] = std::valarray(features); #ifdef _OPENMP #pragma omp for #endif - for (j = 0; j < features; j++) + for (j = 0; j < features; j++) { // preallocate with random initial weights W[i][j] = _random(-1, 1); + } } } diff --git a/machine_learning/ordinary_least_squares_regressor.cpp b/machine_learning/ordinary_least_squares_regressor.cpp index 896504e20..0c865761b 100644 --- a/machine_learning/ordinary_least_squares_regressor.cpp +++ b/machine_learning/ordinary_least_squares_regressor.cpp @@ -25,9 +25,10 @@ std::ostream &operator<<(std::ostream &out, const char separator = ' '; for (size_t row = 0; row < v.size(); row++) { - for (size_t col = 0; col < v[row].size(); col++) + for (size_t col = 0; col < v[row].size(); col++) { out << std::left << std::setw(width) << std::setfill(separator) << v[row][col]; + } out << std::endl; } @@ -42,9 +43,10 @@ std::ostream &operator<<(std::ostream &out, std::vector const &v) { const int width = 15; const char separator = ' '; - for (size_t row = 0; row < v.size(); row++) + for (size_t row = 0; row < v.size(); row++) { out << std::left << std::setw(width) << std::setfill(separator) << v[row]; + } return out; } @@ -57,9 +59,11 @@ template inline bool is_square(std::vector> const &A) { // Assuming A is square matrix size_t N = A.size(); - for (size_t i = 0; i < N; i++) - if (A[i].size() != N) + for (size_t i = 0; i < N; i++) { + if (A[i].size() != N) { return false; + } + } return true; } @@ -90,8 +94,9 @@ std::vector> operator*(std::vector> const &A, std::vector v(N_B); for (size_t col = 0; col < N_B; col++) { v[col] = static_cast(0); - for (size_t j = 0; j < B.size(); j++) + for (size_t j = 0; j < B.size(); j++) { v[col] += A[row][j] * B[j][col]; + } } result[row] = v; } @@ -154,8 +159,9 @@ std::vector operator*(std::vector const &A, float const scalar) { std::vector result(N_A); - for (size_t row = 0; row < N_A; row++) + for (size_t row = 0; row < N_A; row++) { result[row] = A[row] * static_cast(scalar); + } return result; } @@ -226,8 +232,9 @@ std::vector> get_inverse( for (size_t row = 0; row < N; row++) { // preallocatae a resultant identity matrix inverse[row] = std::vector(N); - for (size_t col = 0; col < N; col++) + for (size_t col = 0; col < N; col++) { inverse[row][col] = (row == col) ? 1.f : 0.f; + } } if (!is_square(A)) { @@ -239,8 +246,9 @@ std::vector> get_inverse( std::vector> temp(N); for (size_t row = 0; row < N; row++) { std::vector v(N); - for (size_t col = 0; col < N; col++) + for (size_t col = 0; col < N; col++) { v[col] = static_cast(A[row][col]); + } temp[row] = v; } @@ -267,13 +275,14 @@ std::vector> get_inverse( } // set diagonal to 1 - float divisor = static_cast(temp[row][row]); + auto divisor = static_cast(temp[row][row]); temp[row] = temp[row] / divisor; inverse[row] = inverse[row] / divisor; // Row transformations for (size_t row2 = 0; row2 < N; row2++) { - if (row2 == row) + if (row2 == row) { continue; + } float factor = temp[row2][row]; temp[row2] = temp[row2] - factor * temp[row]; inverse[row2] = inverse[row2] - factor * inverse[row]; @@ -313,9 +322,10 @@ std::vector fit_OLS_regressor(std::vector> const &X, std::vector const &Y) { // NxF std::vector> X2 = X; - for (size_t i = 0; i < X2.size(); i++) + for (size_t i = 0; i < X2.size(); i++) { // add Y-intercept -> Nx(F+1) X2[i].push_back(1); + } // (F+1)xN std::vector> Xt = get_transpose(X2); // (F+1)x(F+1) @@ -347,8 +357,9 @@ std::vector predict_OLS_regressor(std::vector> const &X, for (size_t rows = 0; rows < X.size(); rows++) { // -> start with constant term result[rows] = beta[X[0].size()]; - for (size_t cols = 0; cols < X[0].size(); cols++) + for (size_t cols = 0; cols < X[0].size(); cols++) { result[rows] += beta[cols] * X[rows][cols]; + } } // Nx1 return result; @@ -375,8 +386,9 @@ void ols_test() { // predicted regression outputs std::vector out1 = predict_OLS_regressor(test_data1, beta1); // compare predicted results are within +-0.01 limit of expected - for (size_t rows = 0; rows < out1.size(); rows++) + for (size_t rows = 0; rows < out1.size(); rows++) { assert(std::abs(out1[rows] - expected1[rows]) < 0.01); + } std::cout << "passed\n"; /* test function = x^3 + x^2 - 100 */ @@ -396,8 +408,9 @@ void ols_test() { // predicted regression outputs std::vector out2 = predict_OLS_regressor(test_data2, beta2); // compare predicted results are within +-0.01 limit of expected - for (size_t rows = 0; rows < out2.size(); rows++) + for (size_t rows = 0; rows < out2.size(); rows++) { assert(std::abs(out2[rows] - expected2[rows]) < 0.01); + } std::cout << "passed\n"; std::cout << std::endl; // ensure test results are displayed on screen @@ -410,7 +423,7 @@ void ols_test() { int main() { ols_test(); - size_t N, F; + size_t N = 0, F = 0; std::cout << "Enter number of features: "; // number of features = columns @@ -429,9 +442,10 @@ int main() { for (size_t rows = 0; rows < N; rows++) { std::vector v(F); std::cout << "Sample# " << rows + 1 << ": "; - for (size_t cols = 0; cols < F; cols++) + for (size_t cols = 0; cols < F; cols++) { // get the F features std::cin >> v[cols]; + } data[rows] = v; // get the corresponding output std::cin >> Y[rows]; @@ -440,7 +454,7 @@ int main() { std::vector beta = fit_OLS_regressor(data, Y); std::cout << std::endl << std::endl << "beta:" << beta << std::endl; - size_t T; + size_t T = 0; std::cout << "Enter number of test samples: "; // number of test sample inputs std::cin >> T; diff --git a/numerical_methods/newton_raphson_method.cpp b/numerical_methods/newton_raphson_method.cpp index 7597f1b8a..17147e0be 100644 --- a/numerical_methods/newton_raphson_method.cpp +++ b/numerical_methods/newton_raphson_method.cpp @@ -17,8 +17,8 @@ #include #include -#define EPSILON 1e-10 ///< system accuracy limit -#define MAX_ITERATIONS INT16_MAX ///< Maximum number of iterations to check +constexpr double EPSILON = 1e-10; ///< system accuracy limit +constexpr int16_t MAX_ITERATIONS = INT16_MAX; ///< Maximum number of iterations /** define \f$f(x)\f$ to find root for. * Currently defined as: @@ -44,8 +44,8 @@ static double eq_der(double i) { int main() { std::srand(std::time(nullptr)); // initialize randomizer - double z, c = std::rand() % 100, m, n; - int i; + double z = NAN, c = std::rand() % 100, m = NAN, n = NAN; + int i = 0; std::cout << "\nInitial approximation: " << c; @@ -57,8 +57,9 @@ int main() { z = c - (m / n); c = z; - if (std::abs(m) < EPSILON) // stoping criteria + if (std::abs(m) < EPSILON) { // stoping criteria break; + } } std::cout << "\n\nRoot: " << z << "\t\tSteps: " << i << std::endl; diff --git a/numerical_methods/ode_forward_euler.cpp b/numerical_methods/ode_forward_euler.cpp index a4455c57a..5e4dda31b 100644 --- a/numerical_methods/ode_forward_euler.cpp +++ b/numerical_methods/ode_forward_euler.cpp @@ -54,8 +54,8 @@ void problem(const double &x, std::valarray *y, std::valarray *dy) { const double omega = 1.F; // some const for the problem - dy[0][0] = y[0][1]; // x dot - dy[0][1] = -omega * omega * y[0][0]; // y dot + (*dy)[0] = (*y)[1]; // x dot // NOLINT + (*dy)[1] = -omega * omega * (*y)[0]; // y dot // NOLINT } /** @@ -83,10 +83,10 @@ void exact_solution(const double &x, std::valarray *y) { * @param[in,out] y take \f$y_n\f$ and compute \f$y_{n+1}\f$ * @param[in,out] dy compute \f$f\left(x_n,y_n\right)\f$ */ -void forward_euler_step(const double dx, const double &x, +void forward_euler_step(const double dx, const double x, std::valarray *y, std::valarray *dy) { problem(x, y, dy); - y[0] += dy[0] * dx; + *y += *dy * dx; } /** @@ -101,7 +101,7 @@ void forward_euler_step(const double dx, const double &x, */ double forward_euler(double dx, double x0, double x_max, std::valarray *y, bool save_to_file = false) { - std::valarray dy = y[0]; + std::valarray dy = *y; std::ofstream fp; if (save_to_file) { @@ -122,9 +122,9 @@ double forward_euler(double dx, double x0, double x_max, // write to file fp << x << ","; for (int i = 0; i < L - 1; i++) { - fp << y[0][i] << ","; + fp << y[0][i] << ","; // NOLINT } - fp << y[0][L - 1] << "\n"; + fp << y[0][L - 1] << "\n"; // NOLINT } forward_euler_step(dx, x, y, &dy); // perform integration @@ -133,8 +133,9 @@ double forward_euler(double dx, double x0, double x_max, /* end of integration */ std::clock_t t2 = std::clock(); - if (fp.is_open()) + if (fp.is_open()) { fp.close(); + } return static_cast(t2 - t1) / CLOCKS_PER_SEC; } @@ -153,7 +154,7 @@ void save_exact_solution(const double &X0, const double &X_MAX, const double &step_size, const std::valarray &Y0) { double x = X0; - std::valarray y = Y0; + std::valarray y(Y0); std::ofstream fp("exact.csv", std::ostream::out); if (!fp.is_open()) { @@ -166,9 +167,9 @@ void save_exact_solution(const double &X0, const double &X_MAX, do { fp << x << ","; for (int i = 0; i < y.size() - 1; i++) { - fp << y[i] << ","; + fp << y[i] << ","; // NOLINT } - fp << y[y.size() - 1] << "\n"; + fp << y[y.size() - 1] << "\n"; // NOLINT exact_solution(x, &y); @@ -186,10 +187,10 @@ void save_exact_solution(const double &X0, const double &X_MAX, * Main Function */ int main(int argc, char *argv[]) { - double X0 = 0.f; /* initial value of x0 */ - double X_MAX = 10.F; /* upper limit of integration */ - std::valarray Y0 = {1.f, 0.f}; /* initial value Y = y(x = x_0) */ - double step_size; + double X0 = 0.f; /* initial value of x0 */ + double X_MAX = 10.F; /* upper limit of integration */ + std::valarray Y0{1.f, 0.f}; /* initial value Y = y(x = x_0) */ + double step_size = NAN; if (argc == 1) { std::cout << "\nEnter the step size: "; From dc4a72c4181ee000cfdfede684c089adbc3a0774 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Mon, 13 Jul 2020 08:07:10 -0400 Subject: [PATCH 65/67] fix doc comment block --- data_structures/skip_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index b1b24ea20..39dda5ce6 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -181,7 +181,7 @@ class SkipList { } } - /* + /** * Display skip list level */ void displayList() { From eefe46688deb4197d14a7d123135037c7888a304 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Mon, 13 Jul 2020 08:07:44 -0400 Subject: [PATCH 66/67] main function must return --- data_structures/skip_list.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 39dda5ce6..cc679a31c 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -216,4 +216,6 @@ int main() { } lst.displayList(); + + return 0; } From 076d156302cc93101eb56958c1cbd9d5829a4251 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 13 Jul 2020 13:34:13 +0000 Subject: [PATCH 67/67] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index bc007bc5f..57a1b1c13 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -33,6 +33,7 @@ * [Queue Using Array2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_array2.cpp) * [Queue Using Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linked_list.cpp) * [Queue Using Linkedlist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linkedlist.cpp) + * [Skip List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/skip_list.cpp) * [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack.h) * [Stack Using Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack_using_array.cpp) * [Stack Using Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack_using_linked_list.cpp)