Skip to content

Commit 8677ee1

Browse files
Add list-ops (#159)
1 parent 8732919 commit 8677ee1

File tree

12 files changed

+4009
-0
lines changed

12 files changed

+4009
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,14 @@
485485
"prerequisites": [],
486486
"difficulty": 6
487487
},
488+
{
489+
"slug": "list-ops",
490+
"name": "List Ops",
491+
"uuid": "95253183-0efe-4f9a-b138-610570e06c08",
492+
"practices": [],
493+
"prerequisites": [],
494+
"difficulty": 6
495+
},
488496
{
489497
"slug": "matching-brackets",
490498
"name": "Matching Brackets",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Instructions
2+
3+
Implement basic list operations.
4+
5+
In functional languages list operations like `length`, `map`, and `reduce` are very common.
6+
Implement a series of basic list operations, without using existing functions.
7+
8+
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:
9+
10+
- `append` (_given two lists, add all items in the second list to the end of the first list_);
11+
- `concatenate` (_given a series of lists, combine all items in all lists into one flattened list_);
12+
- `filter` (_given a predicate and a list, return the list of all items for which `predicate(item)` is True_);
13+
- `length` (_given a list, return the total number of items within it_);
14+
- `map` (_given a function and a list, return the list of the results of applying `function(item)` on all items_);
15+
- `foldl` (_given a function, a list, and initial accumulator, fold (reduce) each item into the accumulator from the left_);
16+
- `foldr` (_given a function, a list, and an initial accumulator, fold (reduce) each item into the accumulator from the right_);
17+
- `reverse` (_given a list, return a list with all the original items, but in reversed order_).
18+
19+
Note, the ordering in which arguments are passed to the fold functions (`foldl`, `foldr`) is significant.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"list_ops.s"
8+
],
9+
"test": [
10+
"list_ops_test.c"
11+
],
12+
"example": [
13+
".meta/example.s"
14+
]
15+
},
16+
"blurb": "Implement basic list operations."
17+
}
+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
.text
2+
.globl append
3+
.globl filter
4+
.globl map
5+
.globl foldl
6+
.globl foldr
7+
.globl reverse
8+
9+
10+
/* extern size_t append(int64_t *buffer, const int64_t *list1, size_t list1_count, const int64_t *list2, size_t list2_count); */
11+
append:
12+
mov x9, x0
13+
cbz x2, .append_check_list2_count
14+
15+
lsl x2, x2, #3
16+
add x2, x1, x2
17+
18+
.append_copy_list1:
19+
ldr x10, [x1], #8
20+
str x10, [x0], #8
21+
cmp x1, x2
22+
bne .append_copy_list1
23+
24+
.append_check_list2_count:
25+
cbz x4, .append_return
26+
27+
lsl x4, x4, #3
28+
add x4, x3, x4
29+
30+
.append_copy_list2:
31+
ldr x10, [x3], #8
32+
str x10, [x0], #8
33+
cmp x3, x4
34+
bne .append_copy_list2
35+
36+
.append_return:
37+
sub x0, x0, x9
38+
lsr x0, x0, #3
39+
ret
40+
41+
42+
/* extern size_t filter(int64_t *buffer, const int64_t *list, size_t list_count, bool (*function)(int64_t)); */
43+
filter:
44+
stp x19, x20, [sp, #-64]!
45+
stp x21, x22, [sp, #16]
46+
stp x23, x24, [sp, #32]
47+
stp x25, x26, [sp, #48]
48+
49+
mov x19, x0 /* buffer */
50+
mov x20, x1 /* list */
51+
mov x21, x2 /* list_count */
52+
mov x22, x3 /* function */
53+
mov x23, x0 /* destination */
54+
mov x24, x1 /* source */
55+
mov x25, lr /* return address */
56+
57+
.filter_loop:
58+
cbz x21, .filter_return
59+
60+
ldr x26, [x24], #8
61+
mov x0, x26
62+
add x21, x21, #-1
63+
blr x22
64+
cbz x0, .filter_loop
65+
66+
str x26, [x23], #8
67+
b .filter_loop
68+
69+
.filter_return:
70+
sub x0, x23, x19
71+
lsr x0, x0, #3
72+
mov lr, x25
73+
ldp x25, x26, [sp, #48]
74+
ldp x23, x24, [sp, #32]
75+
ldp x21, x22, [sp, #16]
76+
ldp x19, x20, [sp], #64
77+
ret
78+
79+
80+
/* extern size_t map(int64_t *buffer, const int64_t *list, size_t list_count, int64_t (*function)(int64_t)); */
81+
map:
82+
stp x19, x20, [sp, #-64]!
83+
stp x21, x22, [sp, #16]
84+
stp x23, x24, [sp, #32]
85+
stp x25, x26, [sp, #48]
86+
87+
mov x19, x0 /* buffer */
88+
mov x20, x1 /* list */
89+
mov x21, x2 /* list_count */
90+
mov x22, x3 /* function */
91+
mov x23, x0 /* destination */
92+
mov x24, x1 /* source */
93+
mov x25, lr /* return address */
94+
95+
.map_loop:
96+
cbz x21, .map_return
97+
98+
ldr x0, [x24], #8
99+
add x21, x21, #-1
100+
blr x22
101+
str x0, [x23], #8
102+
b .map_loop
103+
104+
.map_return:
105+
sub x0, x23, x19
106+
lsr x0, x0, #3
107+
mov lr, x25
108+
ldp x25, x26, [sp, #48]
109+
ldp x23, x24, [sp, #32]
110+
ldp x21, x22, [sp, #16]
111+
ldp x19, x20, [sp], #64
112+
ret
113+
114+
115+
/* extern int64_t foldl(const int64_t *list, size_t list_count, int64_t initial, int64_t (*function)(int64_t, int64_t)); */
116+
foldl:
117+
stp x19, x20, [sp, #-32]!
118+
stp x21, x22, [sp, #16]
119+
120+
mov x19, x0 /* list */
121+
mov x20, x1 /* list_count */
122+
mov x21, x3 /* function */
123+
mov x22, lr /* return address */
124+
mov x0, x2 /* initial */
125+
126+
.foldl_loop:
127+
cbz x20, .foldl_return
128+
129+
ldr x1, [x19], #8
130+
add x20, x20, #-1
131+
blr x21
132+
b .foldl_loop
133+
134+
.foldl_return:
135+
mov lr, x22
136+
ldp x21, x22, [sp, #16]
137+
ldp x19, x20, [sp], #32
138+
ret
139+
140+
141+
/* extern int64_t foldr(const int64_t *list, size_t list_count, int64_t initial, int64_t (*function)(int64_t, int64_t)); */
142+
foldr:
143+
stp x19, x20, [sp, #-32]!
144+
stp x21, x22, [sp, #16]
145+
146+
mov x20, x1 /* list_count */
147+
lsl x1, x1, #3
148+
add x19, x0, x1 /* list end */
149+
mov x21, x3 /* function */
150+
mov x22, lr /* return address */
151+
mov x0, x2 /* initial */
152+
cbz x20, .foldr_return
153+
154+
.foldr_loop:
155+
ldr x1, [x19, #-8]!
156+
add x20, x20, #-1
157+
blr x21
158+
cbnz x20, .foldr_loop
159+
160+
.foldr_return:
161+
mov lr, x22
162+
ldp x21, x22, [sp, #16]
163+
ldp x19, x20, [sp], #32
164+
ret
165+
166+
167+
/* extern size_t reverse(int64_t *buffer, const int64_t *list, size_t list_count); */
168+
reverse:
169+
mov x15, x2
170+
cbz x2, .reverse_return
171+
172+
lsl x9, x2, #3
173+
add x9, x1, x9 /* end of list */
174+
175+
.reverse_loop:
176+
ldr x10, [x9, #-8]!
177+
str x10, [x0], #8
178+
add x2, x2, #-1
179+
cbnz x2, .reverse_loop
180+
181+
.reverse_return:
182+
mov x0, x15
183+
ret
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[485b9452-bf94-40f7-a3db-c3cf4850066a]
13+
description = "append entries to a list and return the new list -> empty lists"
14+
15+
[2c894696-b609-4569-b149-8672134d340a]
16+
description = "append entries to a list and return the new list -> list to empty list"
17+
18+
[e842efed-3bf6-4295-b371-4d67a4fdf19c]
19+
description = "append entries to a list and return the new list -> empty list to list"
20+
21+
[71dcf5eb-73ae-4a0e-b744-a52ee387922f]
22+
description = "append entries to a list and return the new list -> non-empty lists"
23+
24+
[28444355-201b-4af2-a2f6-5550227bde21]
25+
description = "concatenate a list of lists -> empty list"
26+
include = false
27+
28+
[331451c1-9573-42a1-9869-2d06e3b389a9]
29+
description = "concatenate a list of lists -> list of lists"
30+
include = false
31+
32+
[d6ecd72c-197f-40c3-89a4-aa1f45827e09]
33+
description = "concatenate a list of lists -> list of nested lists"
34+
include = false
35+
36+
[0524fba8-3e0f-4531-ad2b-f7a43da86a16]
37+
description = "filter list returning only values that satisfy the filter function -> empty list"
38+
39+
[88494bd5-f520-4edb-8631-88e415b62d24]
40+
description = "filter list returning only values that satisfy the filter function -> non-empty list"
41+
42+
[1cf0b92d-8d96-41d5-9c21-7b3c37cb6aad]
43+
description = "returns the length of a list -> empty list"
44+
include = false
45+
46+
[d7b8d2d9-2d16-44c4-9a19-6e5f237cb71e]
47+
description = "returns the length of a list -> non-empty list"
48+
include = false
49+
50+
[c0bc8962-30e2-4bec-9ae4-668b8ecd75aa]
51+
description = "return a list of elements whose values equal the list value transformed by the mapping function -> empty list"
52+
53+
[11e71a95-e78b-4909-b8e4-60cdcaec0e91]
54+
description = "return a list of elements whose values equal the list value transformed by the mapping function -> non-empty list"
55+
56+
[613b20b7-1873-4070-a3a6-70ae5f50d7cc]
57+
description = "folds (reduces) the given list from the left with a function -> empty list"
58+
include = false
59+
60+
[e56df3eb-9405-416a-b13a-aabb4c3b5194]
61+
description = "folds (reduces) the given list from the left with a function -> direction independent function applied to non-empty list"
62+
include = false
63+
64+
[d2cf5644-aee1-4dfc-9b88-06896676fe27]
65+
description = "folds (reduces) the given list from the left with a function -> direction dependent function applied to non-empty list"
66+
include = false
67+
68+
[36549237-f765-4a4c-bfd9-5d3a8f7b07d2]
69+
description = "folds (reduces) the given list from the left with a function -> empty list"
70+
reimplements = "613b20b7-1873-4070-a3a6-70ae5f50d7cc"
71+
72+
[7a626a3c-03ec-42bc-9840-53f280e13067]
73+
description = "folds (reduces) the given list from the left with a function -> direction independent function applied to non-empty list"
74+
reimplements = "e56df3eb-9405-416a-b13a-aabb4c3b5194"
75+
76+
[d7fcad99-e88e-40e1-a539-4c519681f390]
77+
description = "folds (reduces) the given list from the left with a function -> direction dependent function applied to non-empty list"
78+
reimplements = "d2cf5644-aee1-4dfc-9b88-06896676fe27"
79+
80+
[aeb576b9-118e-4a57-a451-db49fac20fdc]
81+
description = "folds (reduces) the given list from the right with a function -> empty list"
82+
include = false
83+
84+
[c4b64e58-313e-4c47-9c68-7764964efb8e]
85+
description = "folds (reduces) the given list from the right with a function -> direction independent function applied to non-empty list"
86+
include = false
87+
88+
[be396a53-c074-4db3-8dd6-f7ed003cce7c]
89+
description = "folds (reduces) the given list from the right with a function -> direction dependent function applied to non-empty list"
90+
include = false
91+
92+
[17214edb-20ba-42fc-bda8-000a5ab525b0]
93+
description = "folds (reduces) the given list from the right with a function -> empty list"
94+
reimplements = "aeb576b9-118e-4a57-a451-db49fac20fdc"
95+
96+
[e1c64db7-9253-4a3d-a7c4-5273b9e2a1bd]
97+
description = "folds (reduces) the given list from the right with a function -> direction independent function applied to non-empty list"
98+
reimplements = "c4b64e58-313e-4c47-9c68-7764964efb8e"
99+
100+
[8066003b-f2ff-437e-9103-66e6df474844]
101+
description = "folds (reduces) the given list from the right with a function -> direction dependent function applied to non-empty list"
102+
reimplements = "be396a53-c074-4db3-8dd6-f7ed003cce7c"
103+
104+
[94231515-050e-4841-943d-d4488ab4ee30]
105+
description = "reverse the elements of the list -> empty list"
106+
107+
[fcc03d1e-42e0-4712-b689-d54ad761f360]
108+
description = "reverse the elements of the list -> non-empty list"
109+
110+
[40872990-b5b8-4cb8-9085-d91fc0d05d26]
111+
description = "reverse the elements of the list -> list of lists is not flattened"
112+
include = false

exercises/practice/list-ops/Makefile

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
PLATFORM = $(shell uname -m)
2+
3+
ifneq ($(PLATFORM),aarch64)
4+
ifeq ($(origin AS),default)
5+
AS = aarch64-linux-gnu-as
6+
endif
7+
ifeq ($(origin CC),default)
8+
CC = aarch64-linux-gnu-gcc
9+
endif
10+
endif
11+
12+
CFLAGS ?= -g -Wall -Wextra -pedantic -Werror -std=c99 -fPIE
13+
LDFLAGS ?= -pie -Wl,--fatal-warnings
14+
15+
C_OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
16+
AS_OBJS = $(patsubst %.s,%.o,$(wildcard *.s))
17+
ALL_OBJS = $(filter-out example.o,$(C_OBJS) $(AS_OBJS) vendor/unity.o)
18+
19+
CC_CMD = $(CC) $(ALL_CFLAGS) -c -o $@ $<
20+
21+
ifeq ($(PLATFORM),aarch64)
22+
MAYBE_QEMU ?=
23+
else
24+
MAYBE_QEMU ?= qemu-aarch64 -L /usr/aarch64-linux-gnu
25+
endif
26+
27+
all: tests
28+
@$(MAYBE_QEMU) ./$<
29+
30+
tests: $(ALL_OBJS)
31+
@$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ALL_OBJS)
32+
33+
%.o: %.s
34+
@$(AS) -o $@ $<
35+
36+
%.o: %.c
37+
@$(CC_CMD)
38+
39+
vendor/unity.o: vendor/unity.c vendor/unity.h vendor/unity_internals.h
40+
@$(CC_CMD)
41+
42+
clean:
43+
@rm -f *.o vendor/*.o tests
44+
45+
.PHONY: all clean

0 commit comments

Comments
 (0)