Skip to content

Commit

Permalink
Add strain exercise (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
keiravillekode authored Dec 23, 2023
1 parent 9793794 commit 113a723
Show file tree
Hide file tree
Showing 8 changed files with 407 additions and 2 deletions.
17 changes: 15 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@
"floats"
]
},
{
"slug": "strain",
"name": "Strain",
"uuid": "e929f6cf-04f8-41dd-b333-69be7b06d857",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"lists"
]
},
{
"slug": "pangram",
"name": "Pangram",
Expand Down Expand Up @@ -231,8 +242,10 @@
"uuid": "c8b94fa9-d758-4dca-b7fc-7a130061e064",
"practices": [],
"prerequisites": [],
"difficulty": 1,
"topics": []
"difficulty": 4,
"topics": [
"lists"
]
},
{
"slug": "nth-prime",
Expand Down
29 changes: 29 additions & 0 deletions exercises/practice/strain/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Instructions

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.

For example, given the collection of numbers:

- 1, 2, 3, 4, 5

And the predicate:

- is the number even?

Then your keep operation should produce:

- 2, 4

While your discard operation should produce:

- 1, 3, 5

Note that the union of keep and discard is all the elements.

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.

## Restrictions

Keep your hands off that filter/reject/whatchamacallit functionality provided by your standard library!
Solve this one yourself using other basic tools instead.
19 changes: 19 additions & 0 deletions exercises/practice/strain/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"keiravillekode"
],
"files": {
"solution": [
"strain.sml"
],
"test": [
"test.sml"
],
"example": [
".meta/example.sml"
]
},
"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.",
"source": "Conversation with James Edward Gray II",
"source_url": "http://graysoftinc.com/"
}
17 changes: 17 additions & 0 deletions exercises/practice/strain/.meta/example.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
fun keep f nil = nil
| keep f (first :: rest) =
let
val suffix = keep f rest
in
if f first then first :: suffix
else suffix
end

fun discard f nil = nil
| discard f (first :: rest) =
let
val suffix = discard f rest
in
if f first then suffix
else first :: suffix
end
52 changes: 52 additions & 0 deletions exercises/practice/strain/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[26af8c32-ba6a-4eb3-aa0a-ebd8f136e003]
description = "keep on empty list returns empty list"

[f535cb4d-e99b-472a-bd52-9fa0ffccf454]
description = "keeps everything"

[950b8e8e-f628-42a8-85e2-9b30f09cde38]
description = "keeps nothing"

[92694259-6e76-470c-af87-156bdf75018a]
description = "keeps first and last"

[938f7867-bfc7-449e-a21b-7b00cbb56994]
description = "keeps neither first nor last"

[8908e351-4437-4d2b-a0f7-770811e48816]
description = "keeps strings"

[2728036b-102a-4f1e-a3ef-eac6160d876a]
description = "keeps lists"

[ef16beb9-8d84-451a-996a-14e80607fce6]
description = "discard on empty list returns empty list"

[2f42f9bc-8e06-4afe-a222-051b5d8cd12a]
description = "discards everything"

[ca990fdd-08c2-4f95-aa50-e0f5e1d6802b]
description = "discards nothing"

[71595dae-d283-48ca-a52b-45fa96819d2f]
description = "discards first and last"

[ae141f79-f86d-4567-b407-919eaca0f3dd]
description = "discards neither first nor last"

[daf25b36-a59f-4f29-bcfe-302eb4e43609]
description = "discards strings"

[a38d03f9-95ad-4459-80d1-48e937e4acaf]
description = "discards lists"
5 changes: 5 additions & 0 deletions exercises/practice/strain/strain.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fun keep f l =
raise Fail "'keep' is not implemented"

fun discard f l =
raise Fail "'discard' is not implemented"
110 changes: 110 additions & 0 deletions exercises/practice/strain/test.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
(* version 1.0.0 *)

use "testlib.sml";
use "strain.sml";

infixr |>
fun x |> f = f x

val testsuite =
describe "strain" [
test "keep on empty list returns empty list"
(fn _ => let
val l = []
in
keep (fn x => true) l |> Expect.equalTo []
end),

test "keeps everything"
(fn _ => let
val l = [1, 3, 5]
in
keep (fn x => true) l |> Expect.equalTo [1, 3, 5]
end),

test "keeps nothing"
(fn _ => let
val l = [1, 3, 5]
in
keep (fn x => false) l |> Expect.equalTo []
end),

test "keeps first and last"
(fn _ => let
val l = [1, 2, 3]
in
keep (fn x => x mod 2 = 1) l |> Expect.equalTo [1, 3]
end),

test "keeps neither first nor last"
(fn _ => let
val l = [1, 2, 3]
in
keep (fn x => x mod 2 = 0) l |> Expect.equalTo [2]
end),

test "keeps strings"
(fn _ => let
val l = ["apple", "zebra", "banana", "zombies", "cherimoya", "zealot"]
in
keep (String.isPrefix "z") l |> Expect.equalTo ["zebra", "zombies", "zealot"]
end),

test "keeps lists"
(fn _ => let
val l = [[1, 2, 3], [5, 5, 5], [5, 1, 2], [2, 1, 2], [1, 5, 2], [2, 2, 1], [1, 2, 5]]
in
keep (List.exists (fn x => x = 5)) l |> Expect.equalTo [[5, 5, 5], [5, 1, 2], [1, 5, 2], [1, 2, 5]]
end),

test "discard on empty list returns empty list"
(fn _ => let
val l = []
in
discard (fn x => true) l |> Expect.equalTo []
end),

test "discards everything"
(fn _ => let
val l = [1, 3, 5]
in
discard (fn x => true) l |> Expect.equalTo []
end),

test "discards nothing"
(fn _ => let
val l = [1, 3, 5]
in
discard (fn x => false) l |> Expect.equalTo [1, 3, 5]
end),

test "discards first and last"
(fn _ => let
val l = [1, 2, 3]
in
discard (fn x => x mod 2 = 1) l |> Expect.equalTo [2]
end),

test "discards neither first nor last"
(fn _ => let
val l = [1, 2, 3]
in
discard (fn x => x mod 2 = 0) l |> Expect.equalTo [1, 3]
end),

test "discards strings"
(fn _ => let
val l = ["apple", "zebra", "banana", "zombies", "cherimoya", "zealot"]
in
discard (String.isPrefix "z") l |> Expect.equalTo ["apple", "banana", "cherimoya"]
end),

test "discards lists"
(fn _ => let
val l = [[1, 2, 3], [5, 5, 5], [5, 1, 2], [2, 1, 2], [1, 5, 2], [2, 2, 1], [1, 2, 5]]
in
discard (List.exists (fn x => x = 5)) l |> Expect.equalTo [[1, 2, 3], [2, 1, 2], [2, 2, 1]]
end)
]

val _ = Test.run testsuite
Loading

0 comments on commit 113a723

Please sign in to comment.