diff --git a/CMakeLists.txt b/CMakeLists.txt index df2fcecd..967dd044 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ set(CMAKE_C_STANDARD_REQUIRED YES) if(MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) - add_compile_options(/Za) + # add_compile_options(/Za) endif(MSVC) find_library(MATH_LIBRARY m) diff --git a/misc/cantor_set.c b/misc/cantor_set.c index a5d3e6b7..300d6203 100644 --- a/misc/cantor_set.c +++ b/misc/cantor_set.c @@ -1,54 +1,61 @@ +/** + * @file + * @brief Program to generate [Cantor ternary + * set](https://en.wikipedia.org/wiki/Cantor_set) + */ #include #include #include -struct contour +/** structure to define Cantor set */ +typedef struct _cantor_set { - double start; - double end; - struct contour *next; -}; -typedef struct contour Contour; -Contour *head; + double start; /**< start of interval */ + double end; /**< end of interval */ + struct _cantor_set *next; /**< pointer to next set */ +} CantorSet; -void startList(double start_num, double end_num) +/** Iterative constructor of all sets in the current level. This function + * dynamically allocates memory when creating new sets. These are freed by the + * function ::free_memory. + * @param head pointer to interval set instance to update + */ +void propagate(CantorSet *head) { + // if input is NULL, ignore the process if (head == NULL) - { - head = (Contour *)malloc(sizeof(Contour)); - head->start = start_num; - head->end = end_num; - head->next = NULL; - } -} - -void propagate(Contour *head) -{ - Contour *temp = head; - - if (temp != NULL) - { - Contour *newNode = (Contour *)malloc(sizeof(Contour)); - double diff = (((temp->end) - (temp->start)) / 3); - - newNode->end = temp->end; - temp->end = ((temp->start) + diff); - newNode->start = (newNode->end) - diff; - - newNode->next = temp->next; - - temp->next = newNode; - - propagate(temp->next->next); - } - else return; + + CantorSet *temp = head; // local pointer to track propagation + + // create new node for the new set + CantorSet *newNode = (CantorSet *)malloc(sizeof(CantorSet)); + + // get 1/3rd of interval + double diff = (((temp->end) - (temp->start)) / 3); + + // update interval ranges + newNode->end = temp->end; + temp->end = ((temp->start) + diff); + newNode->start = (newNode->end) - diff; + + // update pointer to next set in this level + newNode->next = temp->next; + + // point to next set + temp->next = newNode; + + // create next set + propagate(temp->next->next); } -void print(Contour *head) +/** Print sets in the current range to `stdout` + * @param head pointer to first set in the current level + */ +void print(CantorSet *head) { - Contour *temp = head; - while (temp != NULL) + CantorSet *temp = head; + while (temp != NULL) // print while a valid set is found { printf("\t"); printf("[%lf] -- ", temp->start); @@ -59,10 +66,23 @@ void print(Contour *head) printf("\n"); } +/** Clear memory allocated by ::propagate function. + * @param head pointer to first allocated instance. + */ +void free_memory(CantorSet *head) +{ + if (!head) + return; + + if (head->next) + free_memory(head->next); + + free(head); +} + +/** Main function */ int main(int argc, char const *argv[]) { - head = NULL; - int start_num, end_num, levels; if (argc < 2) @@ -77,17 +97,27 @@ int main(int argc, char const *argv[]) levels = atoi(argv[3]); } - startList(start_num, end_num); + if (start_num < 0 || end_num < 0 || levels < 0) + { + fprintf(stderr, "All numbers must be positive\n"); + return -1; + } + CantorSet head = {.start = start_num, .end = end_num, .next = NULL}; + + // loop to propagate each level from top to bottom for (int i = 0; i < levels; i++) { printf("Level %d\t", i); - print(head); - propagate(head); + print(&head); + propagate(&head); printf("\n"); } printf("Level %d\t", levels); - print(head); + print(&head); + + // delete all memory allocated + free_memory(head.next); return 0; } diff --git a/project_euler/problem_1/sol1.c b/project_euler/problem_1/sol1.c index 3ffc03fa..b24891fe 100644 --- a/project_euler/problem_1/sol1.c +++ b/project_euler/problem_1/sol1.c @@ -1,7 +1,7 @@ /** * \file * \brief [Problem 1](https://projecteuler.net/problem=1) solution - * + * \details * An Efficient code to print all the sum of all numbers that are multiples of 3 * & 5 below N. */ diff --git a/project_euler/problem_401/sol1.c b/project_euler/problem_401/sol1.c index 7576f7db..bd1044bc 100644 --- a/project_euler/problem_401/sol1.c +++ b/project_euler/problem_401/sol1.c @@ -129,7 +129,7 @@ int main(int argc, char **argv) if (argc == 2) N = strtoll(argv[1], NULL, 10); - else if (N > 2) + else if (argc > 2) { fprintf(stderr, "Wrong number of input arguments!\n"); printf("Usage:\t ./sol1.c [N=1000]"); diff --git a/searching/binary_search.c b/searching/binary_search.c index 78a4cf88..b1fab1f7 100644 --- a/searching/binary_search.c +++ b/searching/binary_search.c @@ -1,9 +1,24 @@ +/** + * @file + * @brief Program to perform [binary + * search](https://en.wikipedia.org/wiki/Binary_search_algorithm) of a target + * value in a given *sorted* array. + * @authors [James McDermott](https://github.com/theycallmemac) - recursive + * algorithm + * @authors [Krishna Vedala](https://github.com/kvedala) - iterative algorithm + */ +#include #include -// Recursive Function- It returns location of x assumiung array arr[l..r] is -// present, otherwise -1 - -int binarysearch(int arr[], int l, int r, int x) +/** Recursive implementation + * \param[in] arr array to search + * \param l left index of search range + * \param r right index of search range + * \param x target value to search for + * \returns location of x assuming array arr[l..r] is present + * \returns -1 otherwise + */ +int binarysearch1(const int *arr, int l, int r, int x) { if (r >= l) { @@ -15,28 +30,80 @@ int binarysearch(int arr[], int l, int r, int x) // If element is smaller than middle if (arr[mid] > x) - return binarysearch(arr, l, mid - 1, x); + return binarysearch1(arr, l, mid - 1, x); // Else element is in right subarray - return binarysearch(arr, mid + 1, r, x); + return binarysearch1(arr, mid + 1, r, x); } // When element is not present in array return -1; } -int main(void) +/** Iterative implementation + * \param[in] arr array to search + * \param l left index of search range + * \param r right index of search range + * \param x target value to search for + * \returns location of x assuming array arr[l..r] is present + * \returns -1 otherwise + */ +int binarysearch2(const int *arr, int l, int r, int x) +{ + int mid = l + (r - l) / 2; + + while (arr[mid] != x) + { + if (r <= l || r < 0) + return -1; + + if (arr[mid] > x) + // If element is smaller than middle + r = mid - 1; + else + // Else element is in right subarray + l = mid + 1; + + mid = l + (r - l) / 2; + } + + // When element is not present in array + return mid; +} + +/** Test implementations */ +void test() { // give function an array to work with int arr[] = {2, 3, 4, 10, 40}; // get size of array int n = sizeof(arr) / sizeof(arr[0]); + + printf("Test 1.... "); // set value to look for int x = 10; // set result to what is returned from binarysearch - int result = binarysearch(arr, 0, n - 1, x); - // print out result - (result == -1) ? printf("Element is not in the array\n") - : printf("Element is present at index %d\n", result); + int result = binarysearch1(arr, 0, n - 1, x); + assert(result == 3); + printf("passed recursive... "); + result = binarysearch2(arr, 0, n - 1, x); + assert(result == 3); + printf("passed iterative...\n"); + + printf("Test 2.... "); + x = 5; + // set result to what is returned from binarysearch + result = binarysearch1(arr, 0, n - 1, x); + assert(result == -1); + printf("passed recursive... "); + result = binarysearch2(arr, 0, n - 1, x); + assert(result == -1); + printf("passed iterative...\n"); +} + +/** Main function */ +int main(void) +{ + test(); return 0; }