diff --git a/config.json b/config.json index 65770b9..7b6c229 100644 --- a/config.json +++ b/config.json @@ -886,6 +886,14 @@ "practices": [], "prerequisites": [], "difficulty": 5 + }, + { + "slug": "strain", + "name": "Strain", + "uuid": "daff70f7-504a-4ba5-89a5-1a2860dcd98e", + "practices": [], + "prerequisites": [], + "difficulty": 2 } ] }, 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..2165d6b --- /dev/null +++ b/exercises/practice/strain/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "kmarker1101" + ], + "files": { + "solution": [ + "strain.el" + ], + "test": [ + "strain-test.el" + ], + "example": [ + ".meta/example.el" + ] + }, + "blurb": "Implement the `keep` and `discard` operation on collections.", + "source": "Conversation with James Edward Gray II", + "source_url": "http://graysoftinc.com/" +} diff --git a/exercises/practice/strain/.meta/example.el b/exercises/practice/strain/.meta/example.el new file mode 100644 index 0000000..7f7f0a4 --- /dev/null +++ b/exercises/practice/strain/.meta/example.el @@ -0,0 +1,24 @@ +;;; strain.el --- Strain (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(defun keep (predicate list) + "Return a list of elements in COLLECTION for which PREDICATE returns true." + (let (result) + (dolist (element list (nreverse result)) + (when (funcall predicate element) + (push element result))))) + +(defun discard (predicate list) + "Return a list of elements in COLLECTION for which PREDICATE returns false." + (let (result) + (dolist (element list (nreverse result)) + (unless (funcall predicate element) + (push element result))))) + + +(provide 'strain) +;;; strain.el ends here diff --git a/exercises/practice/strain/.meta/tests.toml b/exercises/practice/strain/.meta/tests.toml new file mode 100644 index 0000000..3a617b4 --- /dev/null +++ b/exercises/practice/strain/.meta/tests.toml @@ -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" diff --git a/exercises/practice/strain/strain-test.el b/exercises/practice/strain/strain-test.el new file mode 100644 index 0000000..b73d08e --- /dev/null +++ b/exercises/practice/strain/strain-test.el @@ -0,0 +1,86 @@ +;;; strain-test.el --- Strain (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(load-file "strain.el") +(declare-function keep "strain.el" (predicate list)) +(declare-function discard "strain.el" (predicate list)) + + +(defun starts-with (string prefix) + (string-prefix-p prefix string)) + + +(defun contains (list element) + (member element list)) + + +(ert-deftest keep-on-empty-list-returns-empty-list () + (should (equal (keep (lambda (x) t) '()) '()))) + + +(ert-deftest keeps-everything () + (should (equal (keep (lambda (x) t) '(1 3 5)) '(1 3 5)))) + + +(ert-deftest keeps-nothing () + (should (equal (keep (lambda (x) nil) '(1 3 5)) '()))) + + +(ert-deftest keeps-first-and-last () + (should (equal (keep (lambda (x) (= 1 (% x 2))) '(1 2 3)) '(1 3)))) + + +(ert-deftest keeps-neither-first-nor-last () + (should (equal (keep (lambda (x) (= 0 (% x 2))) '(1 2 3)) '(2)))) + + +(ert-deftest keeps-strings () + (should (equal (keep (lambda (x) (starts-with x "z")) + '("apple" "zebra" "banana" "zombies" "cherimoya" "zealot")) + '("zebra" "zombies" "zealot")))) + + +(ert-deftest keeps-lists () + (should (equal (keep (lambda (x) (contains x 5)) + '((1 2 3) (5 5 5) (5 1 2) (2 1 2) (1 5 2) (2 2 1) (1 2 5))) + '((5 5 5) (5 1 2) (1 5 2) (1 2 5))))) + + +(ert-deftest discard-on-empty-list-returns-empty-list () + (should (equal (discard (lambda (x) t) '()) '()))) + + +(ert-deftest discards-everything () + (should (equal (discard (lambda (x) t) '(1 3 5)) '()))) + + +(ert-deftest discards-nothing () + (should (equal (discard (lambda (x) nil) '(1 3 5)) '(1 3 5)))) + + +(ert-deftest discards-first-and-last () + (should (equal (discard (lambda (x) (= (mod x 2) 1)) '(1 2 3)) '(2)))) + + +(ert-deftest discards-neither-first-nor-last () + (should (equal (discard (lambda (x) (= (mod x 2) 0)) '(1 2 3)) '(1 3)))) + + +(ert-deftest discards-strings () + (should (equal (discard (lambda (x) (starts-with x "z")) + '("apple" "zebra" "banana" "zombies" "cherimoya" "zealot")) + '("apple" "banana" "cherimoya")))) + + +(ert-deftest discards-lists () + (should (equal (discard (lambda (x) (contains x 5)) + '((1 2 3) (5 5 5) (5 1 2) (2 1 2) (1 5 2) (2 2 1) (1 2 5))) + '((1 2 3) (2 1 2) (2 2 1))))) + + +(provide 'strain-test) +;;; strain-test.el ends here diff --git a/exercises/practice/strain/strain.el b/exercises/practice/strain/strain.el new file mode 100644 index 0000000..457ccbb --- /dev/null +++ b/exercises/practice/strain/strain.el @@ -0,0 +1,17 @@ +;;; strain.el --- Strain (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(defun keep (predicate list) + (error "Delete this S-Expression and write your own implementation")) + +(defun discard (predicate list) + (error "Delete this S-Expression and write your own implementation")) + + +(provide 'strain) +;;; strain.el ends here +