# Week 2 - Dynamic Arrays ## Team Team name: FreeFlexers Date:03/03/2022 Members | Role | Name | |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------| | **Facilitator** keeps track of time, assigns tasks and makes sure all the group members are heard and that decisions are agreed upon. | Alex Stan | | **Spokesperson** communicates group’s questions and problems to the teacher and talks to other teams; presents the group’s findings. | Kuda | | **Reflector** observes and assesses the interactions and performance among team members. Provides positive feedback and intervenes with suggestions to improve groups’ processes. | Luigi | | **Recorder** guides consensus building in the group by recording answers to questions. Collects important information and data. | Adriaan | ## Activities Make sure to have the activities signed off regularly to ensure progress is tracked. Set up a project in CLion to write the small programs needed in some of the activities. ### Activity 1: Random access ````c #include <stdio.h> #define COUNT (50) void fill_fibonacci(unsigned long long * storage, int count) { storage[0] = 0; storage[0 + 1] = 1; for (int i = 2; i < count; i++) { storage[i] = storage[i - 1] + storage[i - 2]; } } int main() { unsigned long long array[COUNT]; fill_fibonacci(array, COUNT); for (int i = 1; i < COUNT; i++) { printf("f(%d) = %llu\n", i, array[i]); } } ```` findings: *(someArray) is the same as someArray[0] *(someArray + 1) is the same as someArray[1] ### Activity 2: Array definition This is how you include code listings in your markdown document: ```C typedef struct array { size_t capacity; size_t count; float *data; } array_t; ``` Capacity- used to store size of array Count- used to keep us on track and know which location we are at in the array data- pointer to the chunk of memory of the array location max values of size_t = 2^64 - 1. maxvalues of float = 2^32 ### Activity 3: Correct initialization ```C array_t* array_init(array_t *pArray, size_t capacity) { // version 3 if (pArray != NULL) { if (capacity != 0){ pArray->data = malloc(sizeof(float[capacity])); pArray->count = 0; pArray->capacity = pArray->data != NULL ? capacity : 0; } else{ pArray->data = NULL; pArray->count = 0; pArray->capacity = 0; } } return pArray; } ``` Version 3 seems to be the correct one. Version 1 and 2 are incorrect because there is no explicit declaration for the malloc function. A void* is needed for it to work. Syntax: void *malloc(size_t size). Malloc is a function that is used to allocate memory at run time. It accepts an argument size and it is of type size_t. Size_t is defined as unsigned int in stdlib.h so it has to be included. ### Activity 4: Cleaning up ```c int main(void) { array_t *array = (array_t *) malloc(sizeof(array_t)); array_init(array, 10); // .... do some work ... // finally, clean up array_destroy(array); free(array); } ``` The program 2 is the correct one because it uses malloc to allocate memory dinamically then it uses free function to deallocate the memory. ### Activity 5: Resizing an array ```c void array_reserve(struct array *p_array, size_t min_capacity) { size_t capacity = p_array->capacity; while (capacity < min_capacity) { capacity = (capacity + 1) *1.5; } if (capacity == p_array->capacity) return; float * ptr = (float*)realloc(p_array->data,capacity); if (ptr != NULL) { p_array->data = ptr; p_array->capacity = capacity; } } ``` ### Activity 6: Appending values ```c void array_append(struct array * arr, float value){ array_reserve(arr, arr->count + 1); arr->data[arr->count] = value; arr->count++; } ``` ### Activity 7: Inserting values ```c void array_insert(struct array * arr, int index, float value){ array_reserve(arr, arr->count + 1); for(int i=arr->count;i> index;i--){ arr[i]=arr[i - 1]; } arr->data[index]=value; } ``` ### Activity 8: Removing by index ```c void array_remove(struct array * arr, int index){ for(int i=index;i < arr->count;i++){ arr[i]=arr[i+1]; } ``` Record your answer here ### Activity 9: Finding a value ```c int array_find(const struct array * arr, float value){ for(int i=0;i<= sizeof(arr);i++){ if(arr->data[i]==value){ return i; }else return -1; } } ``` Record your answer here ### Activity 10: Constant time complexity an algorithm has CTC If it takes the same time regardless of the number of inputs. O(1) ### Activity 11: Worst-case time complexity | Operation | Worst-case time complexity | | --------------- | -------------------------- | | Insert | O(N) | | Remove | O(N) | | Find | O(N) | | Lookup / access | O(1) | Record your answer here ### Activity 12: Complexity of *append* Amortized time is the way to express the time complexity when an algorithm has the very bad time complexity only once in a while besides the time complexity that happens most of time. With Ammortized time, bad compleexity takes once in a while whilst the worst case time complexity means the maximum amount of time required for inputs of a given size. Worst case time complexity of append: O(N) Amortized complexity: O(1) ### Activity 13: Storing grades in a dynamically growing array #include <stdio.h> #include <stdlib.h> typedef struct array { size_t capacity; size_t count; float *data; } array_t; void input_grades(array_t * grades); float average(const array_t * grades); int num_passed(const array_t * grades); void array_destroy(array_t *grades); array_t* array_init(array_t *grades, int size ){ if (grades != NULL) { if (size != 0){ grades->data = (int*) calloc(size, size * 4); grades->count = size; grades->capacity = grades->data != NULL ? size * 4 : 0; } else{ grades->data = NULL; grades->count = 0; grades->capacity = 0; } } return grades; } void input_grades(array_t * grades){ grades->data[0] = 1; grades->data[1] = 20; grades->data[2] = 30; grades->data[3] = 10; } float average(const array_t * grades){ int sum = 0; for (int i = 0; i < grades->count; ++i) { sum += grades->data[i]; } float average = sum / grades->count; return average; } int num_passed(const array_t * grades){ int count = 0; for (int i = 0; i < grades->count; i++){ if(grades->data[i] >= 5.5){ count++; } } return count; } void array_destroy(array_t *grades){ if (grades != NULL){ free(grades->data); array_init(grades, 0); } } int main() { array_t grades; array_init(&grades, 4); input_grades(&grades); float avg = average(&grades); int passed = num_passed(&grades); printf("Average grade: %.2f\n", avg); printf("%d out of %lu students passed\n", passed, grades.count); array_destroy(&grades); } ## Looking back ### What we've learnt Formulate at least one lesson learned. ### What were the surprises Fill in... ### What problems we've encountered Fill in... ### What was or still is unclear Fill in... ### How did the group perform? How was the collaboration? What were the reasons for hick-ups? What worked well? What can be improved next time? > Written with [StackEdit](https://stackedit.io/).