Skip to content

Commit 99a2e8a

Browse files
committed
add strain
1 parent d5f36cd commit 99a2e8a

9 files changed

Lines changed: 287 additions & 0 deletions

File tree

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@
178178
"prerequisites": [],
179179
"difficulty": 2
180180
},
181+
{
182+
"slug": "strain",
183+
"name": "Strain",
184+
"uuid": "9fd2db0a-e806-451c-9bea-3d895dccd6f6",
185+
"practices": [],
186+
"prerequisites": [],
187+
"difficulty": 2
188+
},
181189
{
182190
"slug": "sum-of-multiples",
183191
"name": "Sum of Multiples",

exercises/practice/strain/.busted

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
return {
2+
default = {
3+
ROOT = { '.' }
4+
}
5+
}
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+
"strain.moon"
8+
],
9+
"test": [
10+
"strain_spec.moon"
11+
],
12+
"example": [
13+
".meta/example.moon"
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: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
keep: (list, predicate) ->
3+
[item for item in *list when predicate(item)]
4+
5+
discard: (list, predicate) ->
6+
[item for item in *list when not predicate(item)]
7+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
format_predicate = (pred) ->
2+
p = pred\gsub "fn%(x%) %-> ", "(x) -> "
3+
p = p\gsub "contains%(x, 5%)", "contains x, 5"
4+
p = p\gsub "starts_with%(x, 'z'%)", "starts_with x, 'z'"
5+
p
6+
7+
format_list = (list) ->
8+
if #list == 0
9+
return "{}"
10+
elseif type(list[1]) == 'string'
11+
return "{" .. table.concat([quote(elem) for elem in *list], ', ') .. "}"
12+
else
13+
return "{" .. table.concat(list, ', ') .. "}"
14+
15+
format_value = (val, level) ->
16+
if #val == 0
17+
'{}'
18+
elseif type(val[1]) == 'table'
19+
rows = [indent format_list(row), level + 1 for row in *val]
20+
table.insert rows, 1, '{'
21+
table.insert rows, indent('}', level)
22+
table.concat rows, '\n'
23+
else
24+
format_list(val)
25+
26+
{
27+
module_name: 'Strain'
28+
29+
test_helpers: [[
30+
local starts_with, contains
31+
32+
starts_with = (str, prefix) ->
33+
str\sub(1, #prefix) == prefix
34+
35+
contains = (list, element) ->
36+
for item in *list
37+
if item == element
38+
return true
39+
false
40+
]]
41+
42+
generate_test: (case, level) ->
43+
44+
45+
lines = {
46+
"result = Strain.#{case.property} #{format_value(case.input.list, level)}, #{format_predicate case.input.predicate}"
47+
"expected = #{format_value(case.expected, level)}"
48+
"assert.are.same expected, result"
49+
}
50+
51+
table.concat [indent line, level for line in *lines], '\n'
52+
}
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: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
keep: (list, predicate) ->
3+
error 'Implement me'
4+
5+
discard: (list, predicate) ->
6+
error 'Implement me'
7+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
Strain = require 'strain'
2+
3+
describe 'strain', ->
4+
local starts_with, contains
5+
6+
starts_with = (str, prefix) ->
7+
str\sub(1, #prefix) == prefix
8+
9+
contains = (list, element) ->
10+
for item in *list
11+
if item == element
12+
return true
13+
false
14+
15+
it 'keep on empty list returns empty list', ->
16+
result = Strain.keep {}, (x) -> true
17+
expected = {}
18+
assert.are.same expected, result
19+
20+
pending 'keeps everything', ->
21+
result = Strain.keep {1, 3, 5}, (x) -> true
22+
expected = {1, 3, 5}
23+
assert.are.same expected, result
24+
25+
pending 'keeps nothing', ->
26+
result = Strain.keep {1, 3, 5}, (x) -> false
27+
expected = {}
28+
assert.are.same expected, result
29+
30+
pending 'keeps first and last', ->
31+
result = Strain.keep {1, 2, 3}, (x) -> x % 2 == 1
32+
expected = {1, 3}
33+
assert.are.same expected, result
34+
35+
pending 'keeps neither first nor last', ->
36+
result = Strain.keep {1, 2, 3}, (x) -> x % 2 == 0
37+
expected = {2}
38+
assert.are.same expected, result
39+
40+
pending 'keeps strings', ->
41+
result = Strain.keep {'apple', 'zebra', 'banana', 'zombies', 'cherimoya', 'zealot'}, (x) -> starts_with x, 'z'
42+
expected = {'zebra', 'zombies', 'zealot'}
43+
assert.are.same expected, result
44+
45+
pending 'keeps lists', ->
46+
result = Strain.keep {
47+
{1, 2, 3}
48+
{5, 5, 5}
49+
{5, 1, 2}
50+
{2, 1, 2}
51+
{1, 5, 2}
52+
{2, 2, 1}
53+
{1, 2, 5}
54+
}, (x) -> contains x, 5
55+
expected = {
56+
{5, 5, 5}
57+
{5, 1, 2}
58+
{1, 5, 2}
59+
{1, 2, 5}
60+
}
61+
assert.are.same expected, result
62+
63+
pending 'discard on empty list returns empty list', ->
64+
result = Strain.discard {}, (x) -> true
65+
expected = {}
66+
assert.are.same expected, result
67+
68+
pending 'discards everything', ->
69+
result = Strain.discard {1, 3, 5}, (x) -> true
70+
expected = {}
71+
assert.are.same expected, result
72+
73+
pending 'discards nothing', ->
74+
result = Strain.discard {1, 3, 5}, (x) -> false
75+
expected = {1, 3, 5}
76+
assert.are.same expected, result
77+
78+
pending 'discards first and last', ->
79+
result = Strain.discard {1, 2, 3}, (x) -> x % 2 == 1
80+
expected = {2}
81+
assert.are.same expected, result
82+
83+
pending 'discards neither first nor last', ->
84+
result = Strain.discard {1, 2, 3}, (x) -> x % 2 == 0
85+
expected = {1, 3}
86+
assert.are.same expected, result
87+
88+
pending 'discards strings', ->
89+
result = Strain.discard {'apple', 'zebra', 'banana', 'zombies', 'cherimoya', 'zealot'}, (x) -> starts_with x, 'z'
90+
expected = {'apple', 'banana', 'cherimoya'}
91+
assert.are.same expected, result
92+
93+
pending 'discards lists', ->
94+
result = Strain.discard {
95+
{1, 2, 3}
96+
{5, 5, 5}
97+
{5, 1, 2}
98+
{2, 1, 2}
99+
{1, 5, 2}
100+
{2, 2, 1}
101+
{1, 2, 5}
102+
}, (x) -> contains x, 5
103+
expected = {
104+
{1, 2, 3}
105+
{2, 1, 2}
106+
{2, 2, 1}
107+
}
108+
assert.are.same expected, result

0 commit comments

Comments
 (0)