Initialization
This commit is contained in:
parent
98369fd5cf
commit
9927d7645b
@ -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.
|
@ -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."
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
#include "list_ops.h"
|
||||
#include <string.h>
|
||||
|
||||
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);
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
#ifndef LIST_OPS_H
|
||||
#define LIST_OPS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
@ -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)"
|
Binary file not shown.
@ -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){
|
||||
|
||||
void delete_list(list_t *list) {
|
||||
free(list);
|
||||
}
|
Loading…
Reference in New Issue
Block a user