diff --git a/config.json b/config.json index 1b650d8..05b58dd 100644 --- a/config.json +++ b/config.json @@ -473,6 +473,14 @@ "prerequisites": [], "difficulty": 3 }, + { + "slug": "strain", + "name": "Strain", + "uuid": "2da79b0f-d182-46c7-a4e4-f0246a0fad65", + "practices": [], + "prerequisites": [], + "difficulty": 3 + }, { "slug": "connect", "name": "Connect", diff --git a/exercises/practice/strain/.docs/instructions.md b/exercises/practice/strain/.docs/instructions.md new file mode 100644 index 0000000..3469ae6 --- /dev/null +++ b/exercises/practice/strain/.docs/instructions.md @@ -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. diff --git a/exercises/practice/strain/.meta/config.json b/exercises/practice/strain/.meta/config.json new file mode 100644 index 0000000..4cfd7f1 --- /dev/null +++ b/exercises/practice/strain/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "strain.v" + ], + "test": [ + "run_test.v" + ], + "example": [ + ".meta/example.v" + ] + }, + "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/" +} diff --git a/exercises/practice/strain/.meta/example.v b/exercises/practice/strain/.meta/example.v new file mode 100644 index 0000000..ecfdfba --- /dev/null +++ b/exercises/practice/strain/.meta/example.v @@ -0,0 +1,25 @@ +module main + +pub fn keep[T](array []T, predicate fn (e T) bool) []T { + mut result := []T{cap: array.len} + + for element in array { + if predicate(element) { + result << element + } + } + + return result +} + +pub fn discard[T](array []T, predicate fn (e T) bool) []T { + mut result := []T{cap: array.len} + + for element in array { + if !predicate(element) { + result << element + } + } + + return result +} diff --git a/exercises/practice/strain/.meta/tests.toml b/exercises/practice/strain/.meta/tests.toml new file mode 100644 index 0000000..94208fb --- /dev/null +++ b/exercises/practice/strain/.meta/tests.toml @@ -0,0 +1,45 @@ +# This is an auto-generated file. Regular comments will be removed when this +# file is regenerated. Regenerating will not touch any manually added keys, +# so comments can be added in 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" diff --git a/exercises/practice/strain/run_test.v b/exercises/practice/strain/run_test.v new file mode 100644 index 0000000..362accc --- /dev/null +++ b/exercises/practice/strain/run_test.v @@ -0,0 +1,148 @@ +module main + +const empty = []int{cap: 0} + +fn test_keep_on_empty_list_returns_empty_list() { + predicate := fn (x int) bool { + return true + } + assert keep(empty, predicate) == empty +} + +fn test_keeps_everything() { + array := [1, 3, 5] + predicate := fn (x int) bool { + return true + } + expect := [1, 3, 5] + assert keep(array, predicate) == expect +} + +fn test_keeps_nothing() { + array := [1, 3, 5] + predicate := fn (x int) bool { + return false + } + assert keep(array, predicate) == empty +} + +fn test_keeps_first_and_last() { + array := [1, 2, 3] + predicate := fn (x int) bool { + return x % 2 == 1 + } + expect := [1, 3] + assert keep(array, predicate) == expect +} + +fn test_keeps_neither_first_nor_last() { + array := [1, 2, 3] + predicate := fn (x int) bool { + return x % 2 == 0 + } + expect := [2] + assert keep(array, predicate) == expect +} + +fn test_keeps_strings() { + array := ['apple', 'zebra', 'banana', 'zombies', 'cherimoya', 'zealot'] + predicate := fn (x string) bool { + return x.starts_with('z') + } + expect := ['zebra', 'zombies', 'zealot'] + assert keep(array, predicate) == expect +} + +fn test_keeps_lists() { + array := [ + [1, 2, 3], + [5, 5, 5], + [5, 1, 2], + [2, 1, 2], + [1, 5, 2], + [2, 2, 1], + [1, 2, 5], + ] + predicate := fn (x []int) bool { + return x.contains(5) + } + expect := [ + [5, 5, 5], + [5, 1, 2], + [1, 5, 2], + [1, 2, 5], + ] + assert keep(array, predicate) == expect +} + +fn test_discard_on_empty_list_returns_empty_list() { + predicate := fn (x int) bool { + return true + } + assert discard(empty, predicate) == empty +} + +fn test_discards_everything() { + array := [1, 3, 5] + predicate := fn (x int) bool { + return true + } + assert discard(array, predicate) == empty +} + +fn test_discards_nothing() { + array := [1, 3, 5] + predicate := fn (x int) bool { + return false + } + expect := [1, 3, 5] + assert discard(array, predicate) == expect +} + +fn test_discards_first_and_last() { + array := [1, 2, 3] + predicate := fn (x int) bool { + return x % 2 == 1 + } + expect := [2] + assert discard(array, predicate) == expect +} + +fn test_discards_neither_first_nor_last() { + array := [1, 2, 3] + predicate := fn (x int) bool { + return x % 2 == 0 + } + expect := [1, 3] + assert discard(array, predicate) == expect +} + +fn test_discards_strings() { + array := ['apple', 'zebra', 'banana', 'zombies', 'cherimoya', 'zealot'] + predicate := fn (x string) bool { + return x.starts_with('z') + } + expect := ['apple', 'banana', 'cherimoya'] + assert discard(array, predicate) == expect +} + +fn test_discards_lists() { + array := [ + [1, 2, 3], + [5, 5, 5], + [5, 1, 2], + [2, 1, 2], + [1, 5, 2], + [2, 2, 1], + [1, 2, 5], + ] + predicate := fn (x []int) bool { + return x.contains(5) + } + expect := [ + [1, 2, 3], + [2, 1, 2], + [2, 2, 1], + ] + assert discard(array, predicate) == expect +} diff --git a/exercises/practice/strain/strain.v b/exercises/practice/strain/strain.v new file mode 100644 index 0000000..bbb35ca --- /dev/null +++ b/exercises/practice/strain/strain.v @@ -0,0 +1,7 @@ +module main + +pub fn keep[T](array []T, predicate fn (e T) bool) []T { +} + +pub fn discard[T](array []T, predicate fn (e T) bool) []T { +}