diff --git a/cv4/list-ops/.docs/instructions.md b/cv4/list-ops/.docs/instructions.md deleted file mode 100644 index ccfc2f8..0000000 --- a/cv4/list-ops/.docs/instructions.md +++ /dev/null @@ -1,19 +0,0 @@ -# Instructions - -Implement basic list operations. - -In functional languages list operations like `length`, `map`, and `reduce` are very common. -Implement a series of basic list operations, without using existing functions. - -The precise number and names of the operations to be implemented will be track dependent to avoid conflicts with existing names, but the general operations you will implement include: - -- `append` (*given two lists, add all items in the second list to the end of the first list*); -- `concatenate` (*given a series of lists, combine all items in all lists into one flattened list*); -- `filter` (*given a predicate and a list, return the list of all items for which `predicate(item)` is True*); -- `length` (*given a list, return the total number of items within it*); -- `map` (*given a function and a list, return the list of the results of applying `function(item)` on all items*); -- `foldl` (*given a function, a list, and initial accumulator, fold (reduce) each item into the accumulator from the left*); -- `foldr` (*given a function, a list, and an initial accumulator, fold (reduce) each item into the accumulator from the right*); -- `reverse` (*given a list, return a list with all the original items, but in reversed order*). - -Note, the ordering in which arguments are passed to the fold functions (`foldl`, `foldr`) is significant. diff --git a/cv4/list-ops/.meta/config.json b/cv4/list-ops/.meta/config.json deleted file mode 100644 index dd36a7a..0000000 --- a/cv4/list-ops/.meta/config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "authors": [ - "wolf99" - ], - "contributors": [ - "patricksjackson", - "rootbeersoup", - "ryanplusplus", - "xihh87" - ], - "files": { - "solution": [ - "list_ops.c", - "list_ops.h" - ], - "test": [ - "test_list_ops.c" - ], - "example": [ - ".meta/example.c", - ".meta/example.h" - ] - }, - "blurb": "Implement basic list operations." -} diff --git a/cv4/list-ops/.meta/example.c b/cv4/list-ops/.meta/example.c deleted file mode 100644 index f2b9e79..0000000 --- a/cv4/list-ops/.meta/example.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "list_ops.h" -#include - -list_t *new_list(size_t length, list_element_t elements[]) -{ - list_t *list = malloc(sizeof(*list) + sizeof(list_element_t) * length); - - if (!list) - return NULL; - - list->length = length; - memcpy(list->elements, elements, sizeof(list_element_t) * length); - - return list; -} - -list_t *append_list(list_t *list1, list_t *list2) -{ - if (!list1 || !list2) - return NULL; - - size_t length = list1->length + list2->length; - list_t *list = malloc(sizeof(*list) + sizeof(list_element_t) * (length)); - - if (!list) - return NULL; - - list->length = length; - if (length) { - memcpy(list->elements, list1->elements, - sizeof(list_element_t) * list1->length); - memcpy(&(list->elements[list1->length]), list2->elements, - sizeof(list_element_t) * list2->length); - } - - return list; -} - -list_t *filter_list(list_t *list, bool (*filter)(list_element_t)) -{ - if (!list || !filter) - return NULL; - - list_t *filtered = - malloc(sizeof(*list) + sizeof(list_element_t) * list->length); - - if (!filtered) - return NULL; - - size_t j = 0; - for (size_t i = 0; i < list->length && j < list->length; ++i) { - if (filter(list->elements[i])) - filtered->elements[j++] = list->elements[i]; - } - filtered->length = j; - - return filtered; -} - -size_t length_list(list_t *list) -{ - if (!list) - return 0; - return list->length; -} - -list_t *map_list(list_t *list, list_element_t (*map)(list_element_t)) -{ - if (!list || !map) - return NULL; - - list_t *mapped = - malloc(sizeof(*list) + sizeof(list_element_t) * list->length); - - if (!mapped) - return NULL; - - mapped->length = list->length; - for (size_t i = 0; i < mapped->length; ++i) - mapped->elements[i] = map(list->elements[i]); - - return mapped; -} - -list_element_t foldl_list(list_t *list, list_element_t initial, - list_element_t (*foldl)(list_element_t, - list_element_t)) -{ - if (!list || !foldl) - return 0; - - for (size_t i = 0; i < list->length; ++i) - initial = foldl(list->elements[i], initial); - - return initial; -} - -list_element_t foldr_list(list_t *list, list_element_t initial, - list_element_t (*foldr)(list_element_t, - list_element_t)) -{ - if (!list || !foldr) - return 0; - - for (size_t i = list->length; i > 0; --i) - initial = foldr(list->elements[i - 1], initial); - - return initial; -} - -list_t *reverse_list(list_t *list) -{ - if (!list) - return NULL; - - list_t *reversed = - malloc(sizeof(*list) + sizeof(list_element_t) * list->length); - - if (!reversed) - return NULL; - - reversed->length = list->length; - for (size_t i = 0, j = reversed->length - 1; i < reversed->length; - i++, j--) { - reversed->elements[i] = list->elements[j]; - } - - return reversed; -} - -void delete_list(list_t *list) -{ - free(list); -} diff --git a/cv4/list-ops/.meta/example.h b/cv4/list-ops/.meta/example.h deleted file mode 100644 index 14a56d8..0000000 --- a/cv4/list-ops/.meta/example.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef LIST_OPS_H -#define LIST_OPS_H - -#include -#include - -typedef int list_element_t; - -typedef struct { - size_t length; - list_element_t elements[]; -} list_t; - -// constructs a new list -list_t *new_list(size_t length, list_element_t elements[]); - -// append entries to a list and return the new list -list_t *append_list(list_t *list1, list_t *list2); - -// filter list returning only values that satisfy the filter function -list_t *filter_list(list_t *list, bool (*filter)(list_element_t)); - -// returns the length of the list -size_t length_list(list_t *list); - -// return a list of elements whose values equal the list value transformed by -// the mapping function -list_t *map_list(list_t *list, list_element_t (*map)(list_element_t)); - -// folds (reduces) the given list from the left with a function -list_element_t foldl_list(list_t *list, list_element_t initial, - list_element_t (*foldl)(list_element_t, - list_element_t)); - -// folds (reduces) the given list from the right with a function -list_element_t foldr_list(list_t *list, list_element_t initial, - list_element_t (*foldr)(list_element_t, - list_element_t)); - -// reverse the elements of the list -list_t *reverse_list(list_t *list); - -// destroy the entire list -// list will be a dangling pointer after calling this method on it -void delete_list(list_t *list); - -#endif diff --git a/cv4/list-ops/.meta/tests.toml b/cv4/list-ops/.meta/tests.toml deleted file mode 100644 index b182853..0000000 --- a/cv4/list-ops/.meta/tests.toml +++ /dev/null @@ -1,105 +0,0 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. - -[485b9452-bf94-40f7-a3db-c3cf4850066a] -description = "empty lists" - -[2c894696-b609-4569-b149-8672134d340a] -description = "list to empty list" - -[e842efed-3bf6-4295-b371-4d67a4fdf19c] -description = "empty list to list" - -[71dcf5eb-73ae-4a0e-b744-a52ee387922f] -description = "non-empty lists" - -[28444355-201b-4af2-a2f6-5550227bde21] -description = "empty list" -include = false - -[331451c1-9573-42a1-9869-2d06e3b389a9] -description = "list of lists" -include = false -comment = "C does not easily allow a single implementation for multiple types (Liskov substitution)" - -[d6ecd72c-197f-40c3-89a4-aa1f45827e09] -description = "list of nested lists" -include = false -comment = "C does not easily allow a single implementation for multiple types (Liskov substitution)" - -[0524fba8-3e0f-4531-ad2b-f7a43da86a16] -description = "empty list" - -[88494bd5-f520-4edb-8631-88e415b62d24] -description = "non-empty list" - -[1cf0b92d-8d96-41d5-9c21-7b3c37cb6aad] -description = "empty list" - -[d7b8d2d9-2d16-44c4-9a19-6e5f237cb71e] -description = "non-empty list" - -[c0bc8962-30e2-4bec-9ae4-668b8ecd75aa] -description = "empty list" - -[11e71a95-e78b-4909-b8e4-60cdcaec0e91] -description = "non-empty list" - -[613b20b7-1873-4070-a3a6-70ae5f50d7cc] -description = "empty list" -include = false - -[e56df3eb-9405-416a-b13a-aabb4c3b5194] -description = "direction independent function applied to non-empty list" -include = false -coment = "reimplemented" - -[d2cf5644-aee1-4dfc-9b88-06896676fe27] -description = "direction dependent function applied to non-empty list" - -[36549237-f765-4a4c-bfd9-5d3a8f7b07d2] -description = "empty list" - -[7a626a3c-03ec-42bc-9840-53f280e13067] -description = "direction independent function applied to non-empty list" - -[d7fcad99-e88e-40e1-a539-4c519681f390] -description = "direction dependent function applied to non-empty list" -include = false -comment = "Prefer integer division test case (d2cf5644-aee1-4dfc-9b88-06896676fe27)" - -[aeb576b9-118e-4a57-a451-db49fac20fdc] -description = "empty list" -include = false -coment = "reimplemented" - -[c4b64e58-313e-4c47-9c68-7764964efb8e] -description = "direction independent function applied to non-empty list" -include = false -coment = "reimplemented" - -[be396a53-c074-4db3-8dd6-f7ed003cce7c] -description = "direction dependent function applied to non-empty list" - -[17214edb-20ba-42fc-bda8-000a5ab525b0] -description = "empty list" - -[e1c64db7-9253-4a3d-a7c4-5273b9e2a1bd] -description = "direction independent function applied to non-empty list" - -[8066003b-f2ff-437e-9103-66e6df474844] -description = "direction dependent function applied to non-empty list" -include = false -comment = "Prefer integer division test case (be396a53-c074-4db3-8dd6-f7ed003cce7c)" - -[94231515-050e-4841-943d-d4488ab4ee30] -description = "empty list" - -[fcc03d1e-42e0-4712-b689-d54ad761f360] -description = "non-empty list" - -[40872990-b5b8-4cb8-9085-d91fc0d05d26] -description = "list of lists is not flattened" -include = false -comment = "C does not easily allow a single implementation for multiple types (Liskov substitution)" diff --git a/cv4/list-ops/.zip b/cv4/list-ops/.zip deleted file mode 100644 index a6a1489..0000000 Binary files a/cv4/list-ops/.zip and /dev/null differ diff --git a/cv4/list_ops.c b/cv4/list_ops.c index a488be1..4bf4a64 100644 --- a/cv4/list_ops.c +++ b/cv4/list_ops.c @@ -39,11 +39,30 @@ list_t *append_list(list_t *list1, list_t *list2) { } // filter list returning only values that satisfy the filter function -list_t *filter_list(list_t *list, bool (*filter)(list_element_t)){ - return NULL; +list_t *filter_list(list_t *list, bool (*filter)(list_element_t)) { + if (list == NULL) return NULL; + + size_t filteredLength = 0; + for (size_t i = 0; i < list->length; ++i) { + if (filter(list->elements[i])) { + ++filteredLength; + } + } + list_t *filtered = malloc(sizeof(list_t) + filteredLength * sizeof(list_element_t)); + if (filtered != NULL) { + filtered->length = filteredLength; + size_t j = 0; + for (size_t i = 0; i < list->length; ++i) { + if (filter(list->elements[i])) { + filtered->elements[j++] = list->elements[i]; + } + } + } + return filtered; } + // returns the length of the list size_t length_list(list_t *list) { return (list != NULL) ? list->length : 0; @@ -64,28 +83,47 @@ list_t *map_list(list_t *list, list_element_t (*map)(list_element_t)) { } // folds (reduces) the given list from the left with a function -list_element_t foldl_list(list_t *list, list_element_t initial, list_element_t (*foldl)(list_element_t, list_element_t)){ - list_element_t accumulator = initial; - - return res; - +list_element_t foldl_list(list_t *list, list_element_t initial, + list_element_t (*foldl)(list_element_t, list_element_t)) { + list_element_t accumulator = initial; + if (list != NULL) { + for (size_t i = 0; i < list->length; ++i) { + accumulator = foldl(list->elements[i], accumulator); + } + } + return accumulator; } // folds (reduces) the given list from the right with a function -list_element_t foldr_list(list_t *list, list_element_t initial,list_element_t (*foldr)(list_element_t, list_element_t)){ - list_element_t res=0; - return res; - +list_element_t foldr_list(list_t *list, list_element_t initial, + list_element_t (*foldr)(list_element_t, list_element_t)) { + list_element_t accumulator = initial; + if (list != NULL) { + for (size_t i = list->length; i > 0; --i) { + accumulator = foldr(list->elements[i - 1], accumulator); + } + } + return accumulator; } // reverse the elements of the list -list_t *reverse_list(list_t *list){ - return NULL; - +list_t *reverse_list(list_t *list) { + if (list == NULL) return NULL; + + list_t *reversedList = new_list(list->length, list->elements); + if (reversedList != NULL) { + for (size_t i = 0; i < list->length / 2; ++i) { + list_element_t temp = reversedList->elements[i]; + reversedList->elements[i] = reversedList->elements[list->length - i - 1]; + reversedList->elements[list->length - i - 1] = temp; + } + } + return reversedList; } + // destroy the entire list // list will be a dangling pointer after calling this method on it -void delete_list(list_t *list){ - -} \ No newline at end of file +void delete_list(list_t *list) { + free(list); +}