Skip to content

Commit a3f55f3

Browse files
authored
Add strain (#589)
* Add `strain` * Reapply formatting * Swap stub and example
1 parent cb5b74e commit a3f55f3

File tree

8 files changed

+282
-0
lines changed

8 files changed

+282
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,14 @@
301301
"prerequisites": [],
302302
"difficulty": 2
303303
},
304+
{
305+
"slug": "strain",
306+
"name": "Strain",
307+
"uuid": "3c03a3f1-972e-44d0-a558-43480d862021",
308+
"practices": [],
309+
"prerequisites": [],
310+
"difficulty": 2
311+
},
304312
{
305313
"slug": "sum-of-multiples",
306314
"name": "Sum of Multiples",
Lines changed: 29 additions & 0 deletions
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.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"BNAndras"
4+
],
5+
"files": {
6+
"solution": [
7+
"lib/strain.dart"
8+
],
9+
"test": [
10+
"test/strain_test.dart"
11+
],
12+
"example": [
13+
".meta/lib/example.dart"
14+
]
15+
},
16+
"blurb": "Implement the `keep` and `discard` operation on collections.",
17+
"source": "Conversation with James Edward Gray II",
18+
"source_url": "http://graysoftinc.com/"
19+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Strain {
2+
List<T> keep<T>(List<T> list, bool Function(T) predicate) {
3+
final result = <T>[];
4+
5+
for (final item in list) {
6+
if (predicate(item)) {
7+
result.add(item);
8+
}
9+
}
10+
11+
return result;
12+
}
13+
14+
List<T> discard<T>(List<T> list, bool Function(T) predicate) {
15+
return keep(list, (item) => !predicate(item));
16+
}
17+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
[26af8c32-ba6a-4eb3-aa0a-ebd8f136e003]
13+
description = "keep on empty list returns empty list"
14+
15+
[f535cb4d-e99b-472a-bd52-9fa0ffccf454]
16+
description = "keeps everything"
17+
18+
[950b8e8e-f628-42a8-85e2-9b30f09cde38]
19+
description = "keeps nothing"
20+
21+
[92694259-6e76-470c-af87-156bdf75018a]
22+
description = "keeps first and last"
23+
24+
[938f7867-bfc7-449e-a21b-7b00cbb56994]
25+
description = "keeps neither first nor last"
26+
27+
[8908e351-4437-4d2b-a0f7-770811e48816]
28+
description = "keeps strings"
29+
30+
[2728036b-102a-4f1e-a3ef-eac6160d876a]
31+
description = "keeps lists"
32+
33+
[ef16beb9-8d84-451a-996a-14e80607fce6]
34+
description = "discard on empty list returns empty list"
35+
36+
[2f42f9bc-8e06-4afe-a222-051b5d8cd12a]
37+
description = "discards everything"
38+
39+
[ca990fdd-08c2-4f95-aa50-e0f5e1d6802b]
40+
description = "discards nothing"
41+
42+
[71595dae-d283-48ca-a52b-45fa96819d2f]
43+
description = "discards first and last"
44+
45+
[ae141f79-f86d-4567-b407-919eaca0f3dd]
46+
description = "discards neither first nor last"
47+
48+
[daf25b36-a59f-4f29-bcfe-302eb4e43609]
49+
description = "discards strings"
50+
51+
[a38d03f9-95ad-4459-80d1-48e937e4acaf]
52+
description = "discards lists"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Strain {
2+
// your code here...
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: 'strain'
2+
environment:
3+
sdk: '>=3.2.0 <4.0.0'
4+
dev_dependencies:
5+
test: '<2.0.0'
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import 'package:strain/strain.dart';
2+
import 'package:test/test.dart';
3+
4+
void main() {
5+
final strain = Strain();
6+
7+
group('Strain', () {
8+
group('Keep', () {
9+
test('keep on empty list returns empty list', () {
10+
final values = [];
11+
final fn = (x) => true;
12+
final result = strain.keep(values, fn);
13+
final expected = [];
14+
expect(result, equals(expected));
15+
}, skip: false);
16+
17+
test('keeps everything', () {
18+
final values = [1, 3, 5];
19+
final fn = (x) => true;
20+
final result = strain.keep(values, fn);
21+
final expected = [1, 3, 5];
22+
expect(result, equals(expected));
23+
}, skip: false);
24+
25+
test('keeps nothing', () {
26+
final values = [1, 3, 5];
27+
final fn = (x) => false;
28+
final result = strain.keep(values, fn);
29+
final expected = [];
30+
expect(result, equals(expected));
31+
}, skip: false);
32+
33+
test('keeps first and last', () {
34+
final values = [1, 2, 3];
35+
final fn = (x) => x % 2 == 1;
36+
final result = strain.keep(values, fn);
37+
final expected = [1, 3];
38+
expect(result, equals(expected));
39+
}, skip: false);
40+
41+
test('keeps neither first nor last', () {
42+
final values = [1, 2, 3];
43+
final fn = (x) => x % 2 == 0;
44+
final result = strain.keep(values, fn);
45+
final expected = [2];
46+
expect(result, equals(expected));
47+
}, skip: false);
48+
49+
test('keeps strings', () {
50+
final values = ["apple", "zebra", "banana", "zombies", "cherimoya", "zealot"];
51+
final fn = (String x) => x.startsWith('z');
52+
final result = strain.keep(values, fn);
53+
final expected = ["zebra", "zombies", "zealot"];
54+
expect(result, equals(expected));
55+
}, skip: false);
56+
57+
test('keeps lists', () {
58+
final values = [
59+
[1, 2, 3],
60+
[5, 5, 5],
61+
[5, 1, 2],
62+
[2, 1, 2],
63+
[1, 5, 2],
64+
[2, 2, 1],
65+
[1, 2, 5]
66+
];
67+
final fn = (List<int> x) => x.contains(5);
68+
final result = strain.keep(values, fn);
69+
final expected = [
70+
[5, 5, 5],
71+
[5, 1, 2],
72+
[1, 5, 2],
73+
[1, 2, 5]
74+
];
75+
expect(result, equals(expected));
76+
}, skip: false);
77+
});
78+
79+
group('Discard', () {
80+
test('discard on empty list returns empty list', () {
81+
final values = [];
82+
final fn = (x) => true;
83+
final result = strain.discard(values, fn);
84+
final expected = [];
85+
expect(result, equals(expected));
86+
}, skip: false);
87+
88+
test('discards everything', () {
89+
final values = [1, 3, 5];
90+
final fn = (x) => true;
91+
final result = strain.discard(values, fn);
92+
final expected = [];
93+
expect(result, equals(expected));
94+
}, skip: false);
95+
96+
test('discards nothing', () {
97+
final values = [1, 3, 5];
98+
final fn = (x) => false;
99+
final result = strain.discard(values, fn);
100+
final expected = [1, 3, 5];
101+
expect(result, equals(expected));
102+
}, skip: false);
103+
104+
test('discards first and last', () {
105+
final values = [1, 2, 3];
106+
final fn = (x) => x % 2 == 1;
107+
final result = strain.discard(values, fn);
108+
final expected = [2];
109+
expect(result, equals(expected));
110+
}, skip: false);
111+
112+
test('discards neither first nor last', () {
113+
final values = [1, 2, 3];
114+
final fn = (x) => x % 2 == 0;
115+
final result = strain.discard(values, fn);
116+
final expected = [1, 3];
117+
expect(result, equals(expected));
118+
}, skip: false);
119+
120+
test('discards strings', () {
121+
final values = ["apple", "zebra", "banana", "zombies", "cherimoya", "zealot"];
122+
final fn = (String x) => x.startsWith('z');
123+
final result = strain.discard(values, fn);
124+
final expected = ["apple", "banana", "cherimoya"];
125+
expect(result, equals(expected));
126+
}, skip: false);
127+
128+
test('discards lists', () {
129+
final values = [
130+
[1, 2, 3],
131+
[5, 5, 5],
132+
[5, 1, 2],
133+
[2, 1, 2],
134+
[1, 5, 2],
135+
[2, 2, 1],
136+
[1, 2, 5]
137+
];
138+
final fn = (List<int> x) => x.contains(5);
139+
final result = strain.discard(values, fn);
140+
final expected = [
141+
[1, 2, 3],
142+
[2, 1, 2],
143+
[2, 2, 1]
144+
];
145+
expect(result, equals(expected));
146+
}, skip: false);
147+
});
148+
});
149+
}

0 commit comments

Comments
 (0)