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

add new exercise

parent a373facb
Branches
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