Skip to content

Commit a3e100a

Browse files
author
oxe-i
committed
add sublist exercise
1 parent 63db0db commit a3e100a

File tree

12 files changed

+3813
-0
lines changed

12 files changed

+3813
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@
340340
"prerequisites": [],
341341
"difficulty": 3
342342
},
343+
{
344+
"slug": "sublist",
345+
"name": "Sublist",
346+
"uuid": "9876f5db-d23c-49c0-bf99-c24f4efe5622",
347+
"practices": [],
348+
"prerequisites": [],
349+
"difficulty": 3
350+
},
343351
{
344352
"slug": "acronym",
345353
"name": "Acronym",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Instructions
2+
3+
Given any two lists `A` and `B`, determine if:
4+
5+
- List `A` is equal to list `B`; or
6+
- List `A` contains list `B` (`A` is a superlist of `B`); or
7+
- List `A` is contained by list `B` (`A` is a sublist of `B`); or
8+
- None of the above is true, thus lists `A` and `B` are unequal
9+
10+
Specifically, list `A` is equal to list `B` if both lists have the same values in the same order.
11+
List `A` is a superlist of `B` if `A` contains a contiguous sub-sequence of values equal to `B`.
12+
List `A` is a sublist of `B` if `B` contains a contiguous sub-sequence of values equal to `A`.
13+
14+
Examples:
15+
16+
- If `A = []` and `B = []` (both lists are empty), then `A` and `B` are equal
17+
- If `A = [1, 2, 3]` and `B = []`, then `A` is a superlist of `B`
18+
- If `A = []` and `B = [1, 2, 3]`, then `A` is a sublist of `B`
19+
- If `A = [1, 2, 3]` and `B = [1, 2, 3, 4, 5]`, then `A` is a sublist of `B`
20+
- If `A = [3, 4, 5]` and `B = [1, 2, 3, 4, 5]`, then `A` is a sublist of `B`
21+
- If `A = [3, 4]` and `B = [1, 2, 3, 4, 5]`, then `A` is a sublist of `B`
22+
- If `A = [1, 2, 3]` and `B = [1, 2, 3]`, then `A` and `B` are equal
23+
- If `A = [1, 2, 3, 4, 5]` and `B = [2, 3, 4]`, then `A` is a superlist of `B`
24+
- If `A = [1, 2, 4]` and `B = [1, 2, 3, 4, 5]`, then `A` and `B` are unequal
25+
- If `A = [1, 2, 3]` and `B = [1, 3, 2]`, then `A` and `B` are unequal
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"authors": [
3+
"oxe-i"
4+
],
5+
"files": {
6+
"solution": [
7+
"sublist.asm"
8+
],
9+
"test": [
10+
"sublist_test.c"
11+
],
12+
"example": [
13+
".meta/example.asm"
14+
]
15+
},
16+
"blurb": "Write a function to determine if a list is a sublist of another list."
17+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
UNEQUAL equ 0
2+
EQUAL equ 1
3+
SUBLIST equ 2
4+
SUPERLIST equ 3
5+
6+
section .text
7+
global sublist
8+
9+
sublist:
10+
; rdi - array of int64_t (first list)
11+
; rsi - size of first array as uint64_t
12+
; rdx - array of int64_t (second list)
13+
; rcx - size of second array as uint64_t
14+
; return is an enum in eax
15+
16+
xchg rsi, rdx ; for using cmpsq
17+
18+
cmp rdx, rcx
19+
je .check_equality ; if lengths are the same, lists must be equal or unequal
20+
jg .check_superlist ; if first list is larger, it must be a superlist or unequal
21+
; otherwise, second list is larger and first must be sublist or unequal
22+
23+
.check_sublist:
24+
cmp rdx, 0
25+
je .sublist ; empty list is sublist of any list
26+
; except of other empty list, which is equal (but this is covered in .check_equality)
27+
28+
.sublist_loop:
29+
cmp rcx, rdx
30+
jl .unequal ; if at any point of the loop, the first list is greater, then the lists are unequal
31+
32+
mov r8, qword [rdi]
33+
cmp r8, qword [rsi]
34+
jne .check_next_sublist ; if elements are different, no sublist starts here
35+
; otherwise we check if a sublist starts here
36+
37+
; saves variables to use cmpsq
38+
mov r8, rdi
39+
mov r9, rsi
40+
mov r10, rcx
41+
42+
mov rcx, rdx ; repe uses rcx as counter, it must be instantiated with the lesser length
43+
44+
repe cmpsq
45+
je .sublist ; if the comparison exhausts the first list returning equal, then it's a sublist
46+
; otherwise, the variables are restored to check next element
47+
48+
mov rdi, r8
49+
mov rsi, r9
50+
mov rcx, r10
51+
52+
.check_next_sublist:
53+
; moves to next element of the second list to check if a sublist starts there
54+
dec rcx
55+
add rsi, 8
56+
57+
jmp .sublist_loop
58+
59+
.sublist:
60+
mov rax, SUBLIST
61+
ret
62+
63+
.check_superlist:
64+
cmp rcx, 0
65+
je .superlist ; any list is superlist of an empty list
66+
; except another empty list, which is equal (but this is covered in .check_equality)
67+
68+
.superlist_loop:
69+
cmp rdx, rcx
70+
jl .unequal ; if at any point of the loop, the first list's size is lesser, then the lists are unequal
71+
72+
mov r8, qword [rdi]
73+
cmp r8, qword [rsi]
74+
jne .check_next_superlist ; if elements are different, no superlist starts here
75+
; otherwise we check if a superlist starts here
76+
77+
; saves variables to use cmpsq
78+
mov r8, rdi
79+
mov r9, rsi
80+
mov r10, rcx
81+
82+
; repe uses rcx as counter, it must be instantiated with the lesser length
83+
; but in this case rcx is already the lesser length
84+
85+
repe cmpsq
86+
je .superlist ; if the comparison exhausts the second list returning equal, then the first is a superlist
87+
; otherwise, the variables are restored to check next element
88+
89+
mov rdi, r8
90+
mov rsi, r9
91+
mov rcx, r10
92+
93+
.check_next_superlist:
94+
; moves to next element of the first list to check if a superlist starts there
95+
dec rdx
96+
add rdi, 8
97+
98+
jmp .superlist_loop
99+
100+
.superlist:
101+
mov rax, SUPERLIST
102+
ret
103+
104+
.check_equality:
105+
; sizes are equal, there's no need to change rcx for repe
106+
repe cmpsq
107+
jne .unequal
108+
109+
mov rax, EQUAL
110+
ret
111+
112+
.unequal:
113+
mov rax, UNEQUAL
114+
ret
115+
116+
%ifidn __OUTPUT_FORMAT__,elf64
117+
section .note.GNU-stack noalloc noexec nowrite progbits
118+
%endif
119+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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+
[97319c93-ebc5-47ab-a022-02a1980e1d29]
13+
description = "empty lists"
14+
15+
[de27dbd4-df52-46fe-a336-30be58457382]
16+
description = "empty list within non empty list"
17+
18+
[5487cfd1-bc7d-429f-ac6f-1177b857d4fb]
19+
description = "non empty list contains empty list"
20+
21+
[1f390b47-f6b2-4a93-bc23-858ba5dda9a6]
22+
description = "list equals itself"
23+
24+
[7ed2bfb2-922b-4363-ae75-f3a05e8274f5]
25+
description = "different lists"
26+
27+
[3b8a2568-6144-4f06-b0a1-9d266b365341]
28+
description = "false start"
29+
30+
[dc39ed58-6311-4814-be30-05a64bc8d9b1]
31+
description = "consecutive"
32+
33+
[d1270dab-a1ce-41aa-b29d-b3257241ac26]
34+
description = "sublist at start"
35+
36+
[81f3d3f7-4f25-4ada-bcdc-897c403de1b6]
37+
description = "sublist in middle"
38+
39+
[43bcae1e-a9cf-470e-923e-0946e04d8fdd]
40+
description = "sublist at end"
41+
42+
[76cf99ed-0ff0-4b00-94af-4dfb43fe5caa]
43+
description = "at start of superlist"
44+
45+
[b83989ec-8bdf-4655-95aa-9f38f3e357fd]
46+
description = "in middle of superlist"
47+
48+
[26f9f7c3-6cf6-4610-984a-662f71f8689b]
49+
description = "at end of superlist"
50+
51+
[0a6db763-3588-416a-8f47-76b1cedde31e]
52+
description = "first list missing element from second list"
53+
54+
[83ffe6d8-a445-4a3c-8795-1e51a95e65c3]
55+
description = "second list missing element from first list"
56+
57+
[7bc76cb8-5003-49ca-bc47-cdfbe6c2bb89]
58+
description = "first list missing additional digits from second list"
59+
60+
[0d7ee7c1-0347-45c8-9ef5-b88db152b30b]
61+
description = "order matters to a list"
62+
63+
[5f47ce86-944e-40f9-9f31-6368aad70aa6]
64+
description = "same digits but different numbers"

exercises/practice/sublist/Makefile

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
AS = nasm
2+
3+
CFLAGS = -g -Wall -Wextra -pedantic -Werror
4+
LDFLAGS =
5+
ASFLAGS = -g -F dwarf -Werror
6+
7+
ifeq ($(shell uname -s),Darwin)
8+
ifeq ($(shell sysctl -n hw.optional.arm64 2>/dev/null),1)
9+
ALL_CFLAGS = -target x86_64-apple-darwin
10+
endif
11+
ALL_LDFLAGS = -Wl,-pie
12+
ALL_ASFLAGS = -f macho64 --prefix _
13+
else
14+
ALL_LDFLAGS = -pie -Wl,--fatal-warnings
15+
ALL_ASFLAGS = -f elf64
16+
endif
17+
18+
ALL_CFLAGS += -std=c99 -fPIE -m64 $(CFLAGS)
19+
ALL_LDFLAGS += $(LDFLAGS)
20+
ALL_ASFLAGS += $(ASFLAGS)
21+
22+
C_OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
23+
AS_OBJS = $(patsubst %.asm,%.o,$(wildcard *.asm))
24+
ALL_OBJS = $(filter-out example.o,$(C_OBJS) $(AS_OBJS) vendor/unity.o)
25+
26+
CC_CMD = $(CC) $(ALL_CFLAGS) -c -o $@ $<
27+
28+
all: tests
29+
@./$<
30+
31+
tests: $(ALL_OBJS)
32+
@$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $(ALL_OBJS)
33+
34+
%.o: %.asm
35+
@$(AS) $(ALL_ASFLAGS) -o $@ $<
36+
37+
%.o: %.c
38+
@$(CC_CMD)
39+
40+
vendor/unity.o: vendor/unity.c vendor/unity.h vendor/unity_internals.h
41+
@$(CC_CMD)
42+
43+
clean:
44+
@rm -f *.o vendor/*.o tests
45+
46+
.PHONY: all clean
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
UNEQUAL equ 0
2+
EQUAL equ 1
3+
SUBLIST equ 2
4+
SUPERLIST equ 3
5+
6+
section .text
7+
global sublist
8+
9+
sublist:
10+
; Provide your implementation here
11+
ret
12+
13+
%ifidn __OUTPUT_FORMAT__,elf64
14+
section .note.GNU-stack noalloc nowrite progbits
15+
%endif
16+
17+

0 commit comments

Comments
 (0)