From 8b23c4146ed5b6060cee38142010441c422e039b Mon Sep 17 00:00:00 2001 From: Mactavish <maczhanchao@yahoo.com> Date: Thu, 4 May 2023 15:56:06 +0200 Subject: [PATCH] update README for higher-order functions --- exercises/higher-oder-func/README.md | 74 +++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/exercises/higher-oder-func/README.md b/exercises/higher-oder-func/README.md index ea7405e..369d0f3 100644 --- a/exercises/higher-oder-func/README.md +++ b/exercises/higher-oder-func/README.md @@ -12,9 +12,81 @@ You will implement the following functions: * `filter`: filter a given array with a predicate function to a new array. * `reduce`: "reduce" the array with a given initial accumulator and a reducer function to a final value. +### Map + +`map` takes a pointer to the target array, the length of the target array, the size of each element in the array and a pointer to a transformer function as parameters. + +It should return a pointer to a newly allocated array, in which every element will be transformed using the transformer function. + +For example: + +```c +int double_it(void *elem) { + *((int *)elem) *= 2; +} + +int arr[] = {1, 2, 3, 4, 5}; +int *new_arr = map(arr, 5, sizeof int, double_it); + +// the new_arr will be {2, 4, 6, 8, 9} and the old array arr is not affected +``` + +### Filter + +`filter` takes a pointer to the target array, the length of the target array, the size of each element in the array, a pointer to a `size_t` variable that stores the size of the filtered array and a pointer to a predicate function as parameters. + +It should return a pointer to a newly allocated array which contains only those elements that fulfill the requirements posed by the predicate function. + +For example: + +```c +bool is_even(void *elem) { + return *((int *)elem) % 2 == 0; +} + +int arr[] = {1, 2, 3, 4, 5}; +size_t new_size = 0; +int *new_arr = filter(arr, 5, sizeof int, &new_size, is_even); + +// the new_arr will be {2, 4} and the old array arr is not affected, new_size will be 2 +``` + +The parameter `new_size` is necessary, otherwise there is no way of knowing the size of the filtered array since we can only deduct the size of an array only from a pointer. + +### Reduce + +`reduce` takes a pointer to the target array, the length of the target array, the size of each element in the array, a pointer to the initial accumulator variable and a pointer to a reducer function as parameters. + +It should return a pointer to that initial accumulator. + +The purpose of `reduce` is to apply a given function to a sequence of elements from left to right and reduces it to a single value using a so called accumulator. + +For example: + +```c +void* sum_int(void *acc, void *elem) { + int *acc_ptr = (int *)acc; + int *elem_ptr = (int *)elem; + *acc_ptr += *elem_ptr; + return acc_ptr; +} + +int arr[] = {1, 2, 3, 4, 5}; +int acc = 0; +int *result = reduce(arr, 5, sizeof int, &acc, sum_int); + +// acc will be 1+2+3+4+5 = 15 and result actually points to acc +``` + ## Tips -TBD +We want the `map`, `filter` and `reduce` functions to be as generic as they can, so as you can see, the return values and the parameters of the given functions are all using `void *` pointers. + +For `map` and `filter`, you will have to use `malloc` or `calloc` to allocate a new array. If the given `length` is 0, then just return a `NULL`. + +In order to use the transformer/predicate/reducer function, you will have to calculate the offset of the element with the give `size`. Because you don't have information of the `type` of the array elements, so you have to calculate the offset of the elements manually. + +Because we only have `void *` pointer to the elements, we can cast it into `char *` and then calculate the offset per bytes. ## Testing -- GitLab