Skip to content
Snippets Groups Projects
Commit 790c598e authored by Mactavish's avatar Mactavish
Browse files

add new exercise

parent a373facb
No related branches found
No related tags found
No related merge requests found
# Higher Order Functions
Here is a small exercise that helps you understand function pointers and void pointers in C.
## Instructions
Implement some higher order functions for arrays.
You will implement the following functions:
* `map`: map a given array with a transform function to a new array.
* `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.
## Tips
TBD
## Testing
The included makefile can be used to create and run the tests using the following commands:
```bash
# run unit tests
make test
# check memory leaks
make memcheck
# clean all compilation files
make clean
```
#include "higher_order_func.h"
#include <stdlib.h>
#include <string.h>
void *map(void *array, size_t n, size_t size, void (*fn)(void *elem)) {
// TODO: implement me!
}
void *filter(void *array, size_t n, size_t size, size_t *new_size,
bool (*pred)(void *elem)) {
// TODO: implement me!
}
void *reduce(void *array, size_t n, size_t size, void *initial_value,
void *(*reducer)(void *acc, void *elem)) {
// TODO: implement me!
}
#ifndef HIGHER_ORDER_FUNC_H
#define HIGHER_ORDER_FUNC_H
#include <stddef.h>
#include <stdbool.h>
void* map(void* array, size_t n, size_t size, void (*fn)(void* elem));
void* filter(void* array, size_t n, size_t size, size_t* new_size, bool (*pred)(void* elem));
void* reduce(void* array, size_t n, size_t size, void* initial_value, void* (*reducer)(void* acc, void * elem));
#endif
### If you wish to use extra libraries (math.h for instance),
### add their flags here (-lm in our case) in the "LIBS" variable.
LIBS = -lm
###
CFLAGS = -std=c99
CFLAGS += -g
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -pedantic
CFLAGS += -Wmissing-declarations
CFLAGS += -DUNITY_SUPPORT_64 -DUNITY_OUTPUT_COLOR
ASANFLAGS = -fsanitize=address
ASANFLAGS += -fno-common
ASANFLAGS += -fno-omit-frame-pointer
.PHONY: test
test: tests.out
@./tests.out
.PHONY: memcheck
memcheck: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(ASANFLAGS) $(CFLAGS) ../unity/unity.c ./*.c -o memcheck.out $(LIBS)
@./memcheck.out
@echo "Memory check passed"
.PHONY: clean
clean:
rm -rf *.o *.out *.out.dSYM
tests.out: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(CFLAGS) ../unity/unity.c ./*.c -o tests.out $(LIBS)
#include "../unity/unity.h"
#include "higher_order_func.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#define INT_ARRAY_SIZE 100
static int int_arr[INT_ARRAY_SIZE];
static int int_arr_copy[INT_ARRAY_SIZE];
void setUp(void) {
for (int i = 0; i < INT_ARRAY_SIZE; i++) {
int_arr[i] = i;
int_arr_copy[i] = i;
}
}
void tearDown(void) {}
static void id(void *element) { *(int *)element = *(int *)element; }
static bool tautology(void *element) {
int *element_ptr = (int *)element;
return *element_ptr >= 0;
}
static bool always_false(void *element) { return *(int *)element < 0; }
static void double_int(void *element) { *((int *)element) *= 2; }
static void plus_2(void *element) { *((int *)element) += 2; }
static void *sum_int(void *acc, void *element) {
int *acc_ptr = (int *)acc;
int *element_ptr = (int *)element;
*acc_ptr += *element_ptr;
return acc_ptr;
}
static void *product_int(void *acc, void *element) {
int *acc_ptr = (int *)acc;
if (*acc_ptr == 0) {
return acc_ptr;
}
int *element_ptr = (int *)element;
*acc_ptr *= *element_ptr;
return acc_ptr;
}
static bool is_prime(void *element) {
int *element_ptr = (int *)element;
if (*element_ptr < 2) {
return false;
}
for (int i = 2; i < *element_ptr; i++) {
if (*element_ptr % i == 0) {
return false;
}
}
return true;
}
static bool is_even(void *element) {
int *element_ptr = (int *)element;
return *element_ptr % 2 == 0;
}
static void test_map_empty_array(void) {
int *result = map(int_arr, 0, sizeof(int), NULL);
TEST_ASSERT_NULL(result);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
}
static void test_filter_empty_array(void) {
size_t new_size;
int *result = filter(int_arr, 0, sizeof(int), &new_size, NULL);
TEST_ASSERT_NULL(result);
TEST_ASSERT_EQUAL_INT(new_size, 0);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
}
static void test_reduce_empty_array(void) {
int inital_value = 0;
int *result = reduce(int_arr, 0, sizeof(int), &inital_value, NULL);
TEST_ASSERT_EQUAL_INT(*result, inital_value);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
}
static void test_map_id_array(void) {
int *result = map(int_arr, INT_ARRAY_SIZE, sizeof(int), id);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, result, INT_ARRAY_SIZE);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
free(result);
}
static void test_filter_totology_array(void) {
size_t new_size;
int *result =
filter(int_arr, INT_ARRAY_SIZE, sizeof(int), &new_size, tautology);
TEST_ASSERT_EQUAL_INT(new_size, INT_ARRAY_SIZE);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, result, INT_ARRAY_SIZE);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
free(result);
}
static void test_map_double_array(void) {
int *result = map(int_arr, INT_ARRAY_SIZE, sizeof(int), double_int);
for (int i = 0; i < INT_ARRAY_SIZE; i++) {
TEST_ASSERT_EQUAL_INT(int_arr[i] * 2, result[i]);
}
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
free(result);
}
static void test_map_plus_2_array(void) {
int *result = map(int_arr, INT_ARRAY_SIZE, sizeof(int), plus_2);
for (int i = 0; i < INT_ARRAY_SIZE; i++) {
TEST_ASSERT_EQUAL_INT(int_arr[i] + 2, result[i]);
}
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
free(result);
}
static void test_reduce_sum_array(void) {
int inital_value = 0;
int *result =
reduce(int_arr, INT_ARRAY_SIZE, sizeof(int), &inital_value, sum_int);
int expected = 0;
for (int i = 0; i < INT_ARRAY_SIZE; i++) {
expected += int_arr[i];
}
TEST_ASSERT_EQUAL_INT(expected, *result);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
}
static void test_product_sum_array(void) {
int inital_value = 1;
int *result =
reduce(int_arr, INT_ARRAY_SIZE, sizeof(int), &inital_value, product_int);
int expected = 1;
for (int i = 1; i < INT_ARRAY_SIZE; i++) {
expected *= int_arr[i];
}
TEST_ASSERT_EQUAL_INT(expected, *result);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
}
static void test_filter_is_prime_array(void) {
size_t new_size;
int *result =
filter(int_arr, INT_ARRAY_SIZE, sizeof(int), &new_size, is_prime);
int expected[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
TEST_ASSERT_EQUAL_INT(new_size, sizeof(expected) / sizeof(int));
TEST_ASSERT_EQUAL_INT_ARRAY(expected, result, sizeof(expected) / sizeof(int));
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
free(result);
}
static void test_filter_always_false_array(void) {
size_t new_size;
int *result =
filter(int_arr, INT_ARRAY_SIZE, sizeof(int), &new_size, always_false);
TEST_ASSERT_EQUAL_INT(new_size, 0);
TEST_ASSERT_NULL(result);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
}
static void test_filter_is_even_array(void) {
size_t new_size;
int *result =
filter(int_arr, INT_ARRAY_SIZE, sizeof(int), &new_size, is_even);
int expected[50];
for (int i = 0; i < 50; i++) {
expected[i] = i * 2;
}
TEST_ASSERT_EQUAL_INT(new_size, 50);
TEST_ASSERT_EQUAL_INT_ARRAY(expected, result, sizeof(expected) / sizeof(int));
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
free(result);
}
static void test_is_even_and_sum(void) {
size_t new_size;
int *result =
filter(int_arr, INT_ARRAY_SIZE, sizeof(int), &new_size, is_even);
int inital_value = 0;
int *sum = reduce(result, new_size, sizeof(int), &inital_value, sum_int);
int expected = 0;
for (int i = 0; i < INT_ARRAY_SIZE; i++) {
if (int_arr[i] % 2 == 0) {
expected += int_arr[i];
}
}
TEST_ASSERT_EQUAL_INT(new_size, 50);
TEST_ASSERT_EQUAL_INT(expected, *sum);
TEST_ASSERT_EQUAL_INT_ARRAY(int_arr, int_arr_copy, INT_ARRAY_SIZE);
free(result);
}
int main(void) {
UnityBegin("test_higher_order_func.c");
RUN_TEST(test_map_empty_array);
RUN_TEST(test_filter_empty_array);
RUN_TEST(test_reduce_empty_array);
RUN_TEST(test_map_id_array);
RUN_TEST(test_filter_totology_array);
RUN_TEST(test_map_double_array);
RUN_TEST(test_reduce_sum_array);
RUN_TEST(test_filter_is_prime_array);
RUN_TEST(test_filter_always_false_array);
RUN_TEST(test_filter_is_even_array);
RUN_TEST(test_map_plus_2_array);
RUN_TEST(test_product_sum_array);
RUN_TEST(test_is_even_and_sum);
return UnityEnd();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment