From f0e0903cd9c5b3e9cdb3fd2d1d88205ec409d1e4 Mon Sep 17 00:00:00 2001 From: "Begerad, Stefan" Date: Thu, 19 Jan 2023 13:18:35 +0100 Subject: [PATCH] feat: add listprimes --- listprimes/includes/linkedlist.h | 18 ++++++++++ listprimes/includes/listprimes.h | 13 ++++++++ listprimes/linkedlist.c | 50 ++++++++++++++++++++++++++++ listprimes/listprimes.c | 57 ++++++++++++++++++++++++++++++++ listprimes/main.c | 56 +++++++++++++++++++++++++++++++ listprimes/makefile | 20 +++++++++++ listprimes/readme.md | 22 ++++++++++++ 7 files changed, 236 insertions(+) create mode 100644 listprimes/includes/linkedlist.h create mode 100644 listprimes/includes/listprimes.h create mode 100644 listprimes/linkedlist.c create mode 100644 listprimes/listprimes.c create mode 100644 listprimes/main.c create mode 100644 listprimes/makefile create mode 100644 listprimes/readme.md diff --git a/listprimes/includes/linkedlist.h b/listprimes/includes/linkedlist.h new file mode 100644 index 0000000..fc9222c --- /dev/null +++ b/listprimes/includes/linkedlist.h @@ -0,0 +1,18 @@ +/* Contains code to create and manipulate a linked list of `int`s */ + +typedef struct elem { + int val; + struct elem* next; +} elem; + +elem* create(int val, elem* prev_elem); + // Add a new elem number to the linked list + +void display(elem* first_elem); + // Print out the current list of elems + +void release(elem* first_elem); + // Release the memory used by the linked list + +int check_membership(int val, elem* first_elem); + // Check linked list for presence of `val` diff --git a/listprimes/includes/listprimes.h b/listprimes/includes/listprimes.h new file mode 100644 index 0000000..29f736a --- /dev/null +++ b/listprimes/includes/listprimes.h @@ -0,0 +1,13 @@ +/* Contains code to create a linked list of prime numbers. */ + +elem* first_n_primes(int n); + // Return a pointer to the first element in a linked list of the first n + // primes + +elem* primes_lte_n(int n); + // Return a pointer to the first element in a linked list of all primes + // less than or equal to `n` + +int is_prime(int x, elem* first_prime); + // Check if x is prime, given a linked list of prime numbers (assumed + // valid) diff --git a/listprimes/linkedlist.c b/listprimes/linkedlist.c new file mode 100644 index 0000000..223c55c --- /dev/null +++ b/listprimes/linkedlist.c @@ -0,0 +1,50 @@ +/* Contains code to create and manipulate a linked list of `int`s */ + +#include +#include +#include "linkedlist.h" + +elem* create(int val, elem* prev_elem) { + // Add a new elem number to the linked list + elem* new_elem = malloc(sizeof(elem)); + new_elem->val = val; + new_elem->next = NULL; + if (prev_elem != NULL) prev_elem->next = new_elem; + return new_elem; +} + +void display(elem* first_elem) { + // Print out the current list of elems + elem* cur_elem = first_elem; + int i = 1; + while (cur_elem != NULL) { + printf("(%i) %i\n", i, cur_elem->val); + cur_elem = cur_elem->next; + i++; + } +} + +void release(elem* first_elem) { + // Release the memory used by the linked list + elem *cur_elem = first_elem, *next_elem; + while (cur_elem != NULL) { + next_elem = cur_elem->next; // Store pointer to next elem + free(cur_elem); // release memory for the current elem + cur_elem = next_elem; // next iteration, free the next elem + } +} + +int check_membership(int val, elem* first_elem) { + // Check linked list for presence of `val` + int found_val = 0; + elem* cur_elem = first_elem; + while (cur_elem != NULL) { + if (val == cur_elem->val) { + found_val = 1; + break; + } else { + cur_elem = cur_elem->next; + } + } + return found_val; +} diff --git a/listprimes/listprimes.c b/listprimes/listprimes.c new file mode 100644 index 0000000..3ba1fa9 --- /dev/null +++ b/listprimes/listprimes.c @@ -0,0 +1,57 @@ +/* Contains code to create a linked list of prime numbers. */ + +#include +#include +#include "linkedlist.h" +#include "listprimes.h" + +elem* first_n_primes(int n) { + // Return a pointer to the first element in a linked list of the first n + // primes + + elem *first_prime = create(2, NULL), *cur_prime = first_prime; + int cur_val = 3, list_len = 1; + + // Iterate until list of primes is desired length + while (list_len < n) { + if (is_prime(cur_val, first_prime)) { // cur_val is prime + cur_prime = create(cur_val, cur_prime); // add to linked list + list_len ++; + // printf("(%i) %i\n", list_len, cur_val); + } + cur_val += 2; + } + return first_prime; +} + +elem* primes_lte_n(int n) { + // Return a pointer to the first element in a linked list of all primes + // less than or equal to `n` + elem *first_prime = create(2, NULL), *cur_prime = first_prime; + int cur_val = 3, list_len = 1; + + // Iterate until all primes less than n have been considered + while (cur_val <= n) { + if (is_prime(cur_val, first_prime)) { // cur_val is prime + cur_prime = create(cur_val, cur_prime); // add to linked list + list_len ++; + // printf("(%i) %i\n", list_len, cur_val); + } + cur_val += 2; + } + return first_prime; +} + +int is_prime(int x, elem* first_prime) { + // Check if x is prime, given a linked list of prime numbers (assumed + // valid) + elem* cur_prime = first_prime; + double sqrtx = sqrt((double)x); + // Iterate through each element of the linked list + while (cur_prime != NULL) { + if (x % cur_prime->val == 0) return 0; + else if (cur_prime->val > sqrtx) return 1; + else cur_prime = cur_prime->next; + } + return 1; +} diff --git a/listprimes/main.c b/listprimes/main.c new file mode 100644 index 0000000..c8ccfdc --- /dev/null +++ b/listprimes/main.c @@ -0,0 +1,56 @@ +/* Compile and run using: +gcc listprimes.c linkedlist.c main.c -o list-primes && list-primes 0 100 + +*/ + +#include +#include +#include "linkedlist.h" +#include "listprimes.h" + +typedef enum {FIRST_N_PRIMES, PRIMES_LTE_N} mode_type; +const int DEFAULT_MODE = FIRST_N_PRIMES; // by default, list first n primes +const int DEFAULT_N = 20; // by default, list first 20 primes + +int main(int argc, char** argv) { + // Read arguments / use defaults + mode_type mode; + int n; + switch (argc) { + case 1: // no args provided, use defaults + mode = DEFAULT_MODE; + n = DEFAULT_N; + break; + case 2: // 1 arg, use default mode and custom n + mode = DEFAULT_MODE; + n = atoi(argv[1]); + break; + case 3: // custom args, check validity + mode = (mode_type) atoi(argv[1]); + n = atoi(argv[2]); + break; + default: // error + fprintf(stderr, "Error: Please enter valid arguments\n"); + return 1; + } + + // Create appropriate list of primes + elem* prime_list; + switch (mode) { + case FIRST_N_PRIMES: + prime_list = first_n_primes(n); + break; + case PRIMES_LTE_N: + prime_list = primes_lte_n(n); + break; + default: + fprintf(stderr, "Error: Invalid mode type\n"); + return 2; + } + + // Display list of primes and release memory + display(prime_list); + release(prime_list); + + return 0; +} diff --git a/listprimes/makefile b/listprimes/makefile new file mode 100644 index 0000000..06b3c91 --- /dev/null +++ b/listprimes/makefile @@ -0,0 +1,20 @@ +#target: dependency_1 dependency_2 dependency_3 ... +# command +# +RM = /bin/rm -f +OBJ = main.o listprimes.o linkedlist.o +# +list-primes: $(OBJ) + gcc $(OBJ) -o list-primes -lm +# +linkedlist.o: linkedlist.c includes/linkedlist.h + gcc -I ./includes -c linkedlist.c -o linkedlist.o +# +listprimes.o: listprimes.c includes/linkedlist.h includes/listprimes.h + gcc -I ./includes -c listprimes.c -o listprimes.o +# +main.o: main.c includes/linkedlist.h includes/listprimes.h + gcc -I ./includes -c main.c -o main.o +# +clean: + $(RM) $(OBJ) list-primes *~ diff --git a/listprimes/readme.md b/listprimes/readme.md new file mode 100644 index 0000000..3560537 --- /dev/null +++ b/listprimes/readme.md @@ -0,0 +1,22 @@ +[source](https://gist.github.com/jakelevi1996/ce46a808fe3b5ef06ece63aea0bd2fed) + +* build + +``` +/usr/bin/gcc main.c listprimes.c linkedlist.c -o list-primes -lm +``` + +* build in two steps (object files, executable file) + +``` +gcc -c main.c -I ./includes +gcc -c listprimes.c -I ./includes +gcc -c linkedlist.c -I ./includes +gcc main.o listprimes.o linkedlist.o -o list-primes -lm +``` + +* run + +``` +./list-primes +```