Skip to content

Commit 7521a5e

Browse files
feat: Add strain exercise (#175)
1 parent f91afda commit 7521a5e

File tree

7 files changed

+281
-0
lines changed

7 files changed

+281
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,14 @@
473473
"prerequisites": [],
474474
"difficulty": 3
475475
},
476+
{
477+
"slug": "strain",
478+
"name": "Strain",
479+
"uuid": "2da79b0f-d182-46c7-a4e4-f0246a0fad65",
480+
"practices": [],
481+
"prerequisites": [],
482+
"difficulty": 3
483+
},
476484
{
477485
"slug": "connect",
478486
"name": "Connect",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Instructions
2+
3+
Implement the `keep` and `discard` operation on collections.
4+
Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false.
5+
6+
For example, given the collection of numbers:
7+
8+
- 1, 2, 3, 4, 5
9+
10+
And the predicate:
11+
12+
- is the number even?
13+
14+
Then your keep operation should produce:
15+
16+
- 2, 4
17+
18+
While your discard operation should produce:
19+
20+
- 1, 3, 5
21+
22+
Note that the union of keep and discard is all the elements.
23+
24+
The functions may be called `keep` and `discard`, or they may need different names in order to not clash with existing functions or concepts in your language.
25+
26+
## Restrictions
27+
28+
Keep your hands off that filter/reject/whatchamacallit functionality provided by your standard library!
29+
Solve this one yourself using other basic tools instead.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"strain.v"
8+
],
9+
"test": [
10+
"run_test.v"
11+
],
12+
"example": [
13+
".meta/example.v"
14+
]
15+
},
16+
"blurb": "Implement the `keep` and `discard` operation on collections. Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false.",
17+
"source": "Conversation with James Edward Gray II",
18+
"source_url": "http://graysoftinc.com/"
19+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module main
2+
3+
pub fn keep[T](array []T, predicate fn (e T) bool) []T {
4+
mut result := []T{cap: array.len}
5+
6+
for element in array {
7+
if predicate(element) {
8+
result << element
9+
}
10+
}
11+
12+
return result
13+
}
14+
15+
pub fn discard[T](array []T, predicate fn (e T) bool) []T {
16+
mut result := []T{cap: array.len}
17+
18+
for element in array {
19+
if !predicate(element) {
20+
result << element
21+
}
22+
}
23+
24+
return result
25+
}
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# This is an auto-generated file. Regular comments will be removed when this
2+
# file is regenerated. Regenerating will not touch any manually added keys,
3+
# so comments can be added in a "comment" key.
4+
5+
[26af8c32-ba6a-4eb3-aa0a-ebd8f136e003]
6+
description = "keep on empty list returns empty list"
7+
8+
[f535cb4d-e99b-472a-bd52-9fa0ffccf454]
9+
description = "keeps everything"
10+
11+
[950b8e8e-f628-42a8-85e2-9b30f09cde38]
12+
description = "keeps nothing"
13+
14+
[92694259-6e76-470c-af87-156bdf75018a]
15+
description = "keeps first and last"
16+
17+
[938f7867-bfc7-449e-a21b-7b00cbb56994]
18+
description = "keeps neither first nor last"
19+
20+
[8908e351-4437-4d2b-a0f7-770811e48816]
21+
description = "keeps strings"
22+
23+
[2728036b-102a-4f1e-a3ef-eac6160d876a]
24+
description = "keeps lists"
25+
26+
[ef16beb9-8d84-451a-996a-14e80607fce6]
27+
description = "discard on empty list returns empty list"
28+
29+
[2f42f9bc-8e06-4afe-a222-051b5d8cd12a]
30+
description = "discards everything"
31+
32+
[ca990fdd-08c2-4f95-aa50-e0f5e1d6802b]
33+
description = "discards nothing"
34+
35+
[71595dae-d283-48ca-a52b-45fa96819d2f]
36+
description = "discards first and last"
37+
38+
[ae141f79-f86d-4567-b407-919eaca0f3dd]
39+
description = "discards neither first nor last"
40+
41+
[daf25b36-a59f-4f29-bcfe-302eb4e43609]
42+
description = "discards strings"
43+
44+
[a38d03f9-95ad-4459-80d1-48e937e4acaf]
45+
description = "discards lists"

exercises/practice/strain/run_test.v

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
module main
2+
3+
const empty = []int{cap: 0}
4+
5+
fn test_keep_on_empty_list_returns_empty_list() {
6+
predicate := fn (x int) bool {
7+
return true
8+
}
9+
assert keep(empty, predicate) == empty
10+
}
11+
12+
fn test_keeps_everything() {
13+
array := [1, 3, 5]
14+
predicate := fn (x int) bool {
15+
return true
16+
}
17+
expect := [1, 3, 5]
18+
assert keep(array, predicate) == expect
19+
}
20+
21+
fn test_keeps_nothing() {
22+
array := [1, 3, 5]
23+
predicate := fn (x int) bool {
24+
return false
25+
}
26+
assert keep(array, predicate) == empty
27+
}
28+
29+
fn test_keeps_first_and_last() {
30+
array := [1, 2, 3]
31+
predicate := fn (x int) bool {
32+
return x % 2 == 1
33+
}
34+
expect := [1, 3]
35+
assert keep(array, predicate) == expect
36+
}
37+
38+
fn test_keeps_neither_first_nor_last() {
39+
array := [1, 2, 3]
40+
predicate := fn (x int) bool {
41+
return x % 2 == 0
42+
}
43+
expect := [2]
44+
assert keep(array, predicate) == expect
45+
}
46+
47+
fn test_keeps_strings() {
48+
array := ['apple', 'zebra', 'banana', 'zombies', 'cherimoya', 'zealot']
49+
predicate := fn (x string) bool {
50+
return x.starts_with('z')
51+
}
52+
expect := ['zebra', 'zombies', 'zealot']
53+
assert keep(array, predicate) == expect
54+
}
55+
56+
fn test_keeps_lists() {
57+
array := [
58+
[1, 2, 3],
59+
[5, 5, 5],
60+
[5, 1, 2],
61+
[2, 1, 2],
62+
[1, 5, 2],
63+
[2, 2, 1],
64+
[1, 2, 5],
65+
]
66+
predicate := fn (x []int) bool {
67+
return x.contains(5)
68+
}
69+
expect := [
70+
[5, 5, 5],
71+
[5, 1, 2],
72+
[1, 5, 2],
73+
[1, 2, 5],
74+
]
75+
assert keep(array, predicate) == expect
76+
}
77+
78+
fn test_discard_on_empty_list_returns_empty_list() {
79+
predicate := fn (x int) bool {
80+
return true
81+
}
82+
assert discard(empty, predicate) == empty
83+
}
84+
85+
fn test_discards_everything() {
86+
array := [1, 3, 5]
87+
predicate := fn (x int) bool {
88+
return true
89+
}
90+
assert discard(array, predicate) == empty
91+
}
92+
93+
fn test_discards_nothing() {
94+
array := [1, 3, 5]
95+
predicate := fn (x int) bool {
96+
return false
97+
}
98+
expect := [1, 3, 5]
99+
assert discard(array, predicate) == expect
100+
}
101+
102+
fn test_discards_first_and_last() {
103+
array := [1, 2, 3]
104+
predicate := fn (x int) bool {
105+
return x % 2 == 1
106+
}
107+
expect := [2]
108+
assert discard(array, predicate) == expect
109+
}
110+
111+
fn test_discards_neither_first_nor_last() {
112+
array := [1, 2, 3]
113+
predicate := fn (x int) bool {
114+
return x % 2 == 0
115+
}
116+
expect := [1, 3]
117+
assert discard(array, predicate) == expect
118+
}
119+
120+
fn test_discards_strings() {
121+
array := ['apple', 'zebra', 'banana', 'zombies', 'cherimoya', 'zealot']
122+
predicate := fn (x string) bool {
123+
return x.starts_with('z')
124+
}
125+
expect := ['apple', 'banana', 'cherimoya']
126+
assert discard(array, predicate) == expect
127+
}
128+
129+
fn test_discards_lists() {
130+
array := [
131+
[1, 2, 3],
132+
[5, 5, 5],
133+
[5, 1, 2],
134+
[2, 1, 2],
135+
[1, 5, 2],
136+
[2, 2, 1],
137+
[1, 2, 5],
138+
]
139+
predicate := fn (x []int) bool {
140+
return x.contains(5)
141+
}
142+
expect := [
143+
[1, 2, 3],
144+
[2, 1, 2],
145+
[2, 2, 1],
146+
]
147+
assert discard(array, predicate) == expect
148+
}

exercises/practice/strain/strain.v

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module main
2+
3+
pub fn keep[T](array []T, predicate fn (e T) bool) []T {
4+
}
5+
6+
pub fn discard[T](array []T, predicate fn (e T) bool) []T {
7+
}

0 commit comments

Comments
 (0)