From 4d00d78d504a8709520760222907879f6a905665 Mon Sep 17 00:00:00 2001 From: Ian Whitney Date: Wed, 20 Apr 2016 14:24:10 -0500 Subject: [PATCH] Shrink & clean up custom_set.json Discussed here: https://github.com/exercism/discussions/issues/10 I'm trying to improve custom_set in two ways: 1. Reducing the test suite, to remove redundancy or uninteresting implementations. 2. Changing test order to improve flow Reducing the test suite ---- The previous test suite contained 74 tests, which is a lot. I haven't checked all the exercises, but it's the biggest test suite that I've come across. If all of those tests provided value (exposing corner cases, improving implementations, etc.) then that's fine. But I found there to be a lot of duplicate tests. With the subset/union/etc tests, a student's implementation is usually done by the 2nd or 3rd test, so the remaining tests didn't provide any additional value. So I have removed the tests that seemed redundant. The tests also expected methods like `size`, `delete` or `is_empty`. I have removed those because - They aren't vital to the behavior of a Set - They are usually implemented as an alias - They aren't used by the set operations (diff/subset/etc) Changing test order ---- The previous test suite started with `equal`. I found that this requires students to implement two things: - Creating a new element - Comparing two collections of elements I have chosen to start the tests with `contains`, since that only requires one set. And, helpfully, when the student implements `add` and `equal`, they can leverage their already-existing `contains` function. --- custom-set.json | 397 +++++++++--------------------------------------- 1 file changed, 74 insertions(+), 323 deletions(-) diff --git a/custom-set.json b/custom-set.json index 834403ccc3..c8e4df560e 100644 --- a/custom-set.json +++ b/custom-set.json @@ -1,90 +1,39 @@ { "#": [ - "This problem is not too difficult but is long, with most languages", - "requiring a number of set operations. Most languages test sets of", - "ints, which are represented here. If you want to tests sets of", - "strings for example instead, just derive strings from the ints.", - "", - "Some languages test that integer-valued floats are considered distinct", - "from ints or test other types. To simplify the JSON for test data", - "conversion programs these tests with non-int values are collected in", - "a separate section. (Well, I confess, I was finding it awkward to", - "deal with this data in Go so I pulled it out. I'd done the work to", - "collect these test cases though and I didn't want to throw them away", - "so I put them in that separate section. If someone writing a test", - "data conversion program can use this data and wants to organize it", - "differently, go for it. We'll deal with it.)", - "", - "Most languages rely on a solver-implemented 'equal' function for", - "testing other functions. Equal tests should come before other", - "tests that rely on it.", - "", - "Languages vary some in terminology, for example in element/member,", - "add/put, size/length/cardinality.", - "", - "Languages often require some functions for getting data in or out", - "of sets, such as 'to-list' or 'string' methods. These are generally", - "language specific and so are not represented here.", - "", - "Some languages with mutable types test functions that modify sets,", - "often by assigning variables in a sequence of operations.", - "This also is not represented here." + "These tests cover the core components of a set data structure: checking", + "presence, adding, comparing and basic set operations. Other features", + "such as deleting elements, checking size, sorting are not tested, but", + "you can add them if they are interesting in your language", + "", + "Tests about mixed-type sets are not included because the ability", + "to implement that will vary by language. If your language supports it", + "and you want to implement mixed-type sets, feel free." ], - "equal": { - "description": ["Test two sets for equality."], + "contains": { + "description": ["Sets can report if they contain an element"], "cases": [ { - "description": "order doesn't matter", - "set1": [1, 3], - "set2": [3, 1], - "expected": true - }, - { - "description": "dupicates don't matter", - "set1": [1, 1], - "set2": [1], - "expected": true - }, - { - "description": "empty sets are equal", - "set1": [], - "set2": [], - "expected": true - }, - { - "description": "set with single element is equal to itself", - "set1": [1], - "set2": [1], - "expected": true - }, - { - "description": "different sets are not equal", - "set1": [1, 2, 3], - "set2": [3, 4, 5], - "expected": false - }, - { - "description": "empty set is not equal to non-empty set", - "set1": [], - "set2": [1, 2, 3], + "description": "nothing is contained in an empty set", + "set": [], + "element": 1, "expected": false }, { - "description": "non-empty set is not equal to empty set", - "set1": [1, 2, 3], - "set2": [], - "expected": false + "description": "when the element is in the set", + "set": [1, 2, 3], + "element": 1, + "expected": true }, { - "description": "having most in common is not good enough", - "set1": [1, 2, 3, 4], - "set2": [2, 3, 4, 5], + "description": "when the element is not in the set", + "set": [1, 2, 3, 2], + "element": 4, "expected": false } ] }, "add": { - "description": ["Add an element to a set."], + "description": ["Unique elements can be added to a set"], "cases": [ { "description": "add to empty set", @@ -99,160 +48,91 @@ "expected": [1, 2, 3, 4] }, { - "description": "add existing element", + "description": "adding an existing element does not change the set", "set": [1, 2, 3], "element": 3, "expected": [1, 2, 3] } ] }, - "delete": { - "description": ["Delete an element from a set."], - "cases": [ - { - "description": "delete an element", - "set": [3, 2, 1], - "element": 2, - "expected": [1, 3] - }, - { - "description": "delete an element not in set", - "set": [3, 2, 1], - "element": 4, - "expected": [1, 2, 3] - } - ] - }, - "is-empty": { - "description": ["Test if is a set is empty."], + "equal": { + "description": ["Sets with the same elements are equal"], "cases": [ { - "description": "empty", - "set": [], + "description": "empty sets are equal", + "set1": [], + "set2": [], "expected": true }, { - "description": "single element", - "set": [1], - "expected": false - }, - { - "description": "a few elements", - "set": [1, 2, 3, 2], + "description": "empty set is not equal to non-empty set", + "set1": [], + "set2": [1, 2, 3], "expected": false - } - ] - }, - "size": { - "description": ["Return the cardinality of a set."], - "cases": [ - { - "description": "empty set", - "set": [], - "expected": 0 - }, - { - "description": "non-empty set", - "set": [1, 2, 3], - "expected": 3 }, { - "description": "duplicate element", - "set": [1, 2, 3, 2], - "expected": 3 - } - ] - }, - "element": { - "description": ["Test if a value is an element of a set."], - "cases": [ - { - "description": "nothing is an element of the empty set", - "set": [], - "element": 1, + "description": "non-empty set is not equal to empty set", + "set1": [1, 2, 3], + "set2": [], "expected": false }, { - "description": "1 is in the set", - "set": [1, 2, 3, 2], - "element": 1, - "expected": true - }, - { - "description": "2 is in the set", - "set": [1, 2, 3, 2], - "element": 2, - "expected": true - }, - { - "description": "3 is in the set", - "set": [1, 2, 3, 2], - "element": 3, + "description": "sets with the same elements are equal", + "set1": [1,2], + "set2": [2,1], "expected": true }, { - "description": "4 not in the set", - "set": [1, 2, 3, 2], - "element": 4, + "description": "sets with different elements are not equal", + "set1": [1,2,3], + "set2": [1,2,4], "expected": false } ] }, "subset": { - "description": ["Test if set1 is a subset of set2."], + "description": ["A set is a subset if all of its elements are contained in the other set"], "cases": [ { - "description": "empty set is subset of itself", + "description": "empty set is a subset of another empty set", "set1": [], "set2": [], "expected": true }, { - "description": "empty set is subset of non-empty set", + "description": "empty set is a subset of non-empty set", "set1": [], "set2": [1], "expected": true }, { - "description": "non-empty set is not subset of empty set", + "description": "non-empty set is not a subset of empty set", "set1": [1], "set2": [], "expected": false }, { - "description": "non-empty set is subset of itself", + "description": "set is a subset of set with exact same elements", "set1": [1, 2, 3], "set2": [1, 2, 3], "expected": true }, { - "description": "proper subset", + "description": "set is a subset of larger set with same elements", "set1": [1, 2, 3], "set2": [4, 1, 2, 3], "expected": true }, { - "description": "same number of elements", + "description": "set is not a subset of set that does not contain its elements", "set1": [1, 2, 3], "set2": [4, 1, 3], "expected": false - }, - { - "description": "superset", - "set1": [1, 2, 3, 4, 5], - "set2": [2, 3, 4], - "expected": false - }, - { - "description": "fewer elements but not a subset", - "set1": [1, 2, 3, 11], - "set2": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - "expected": false } ] }, "disjoint": { - "description": ["Test if two sets are disjoint."], + "description": ["Sets are disjoint if they share no elements"], "cases": [ { "description": "the empty set is disjoint with itself", @@ -261,25 +141,25 @@ "expected": true }, { - "description": "empty set disjoint with non-empty set", + "description": "empty set is disjoint with non-empty set", "set1": [], "set2": [1], "expected": true }, { - "description": "non-empty set disjoint with empty set", + "description": "non-empty set is disjoint with empty set", "set1": [1], "set2": [], "expected": true }, { - "description": "one element in common", + "description": "sets are not disjoint if they share an element", "set1": [1, 2], "set2": [2, 3], "expected": false }, { - "description": "no elements in common", + "description": "sets are dijoint if they share no elements", "set1": [1, 2], "set2": [3, 4], "expected": true @@ -287,254 +167,125 @@ ] }, "intersection": { - "description": ["Intersect two sets."], + "description": ["Intersect returns a set of all shared elements"], "cases": [ { - "description": "intersect empty sets", + "description": "intersection of two empty sets is an empty set", "set1": [], "set2": [], "expected": [] }, { - "description": "intersect empty set with non-empty set", + "description": "intersection of an empty set and non-empty set is an empty set", "set1": [], "set2": [3, 2, 5], "expected": [] }, { - "description": "intersect non-empty set with empty set", + "description": "intersection of a non-empty set and an empty set is an empty set", "set1": [1, 2, 3, 4], "set2": [], "expected": [] }, { - "description": "intersect one element with itself", - "set1": [3], - "set2": [3], - "expected": [3] - }, - { - "description": "one element in common, extra elements in both sets", + "description": "intersection of two sets with no shared elements is an empty set", "set1": [1, 2, 3], - "set2": [3, 5, 4], - "expected": [3] + "set2": [4, 5, 6], + "expected": [] }, { - "description": "two elements in common, extras in both sets", + "description": "intersetion of two sets with shared elements is a set of the shared elements", "set1": [1, 2, 3, 4], "set2": [3, 2, 5], "expected": [2, 3] - }, - { - "description": "intersect with subset", - "set1": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - "set2": [5, 6, 7, 8, 9, 10], - "expected": [5, 6, 7, 8, 9, 10] - }, - { - "description": "nothing in common", - "set1": [1, 2, 3], - "set2": [4, 5, 6], - "expected": [] } ] }, "union": { - "description": ["Produce the union of two sets."], + "description": ["Union returns a set of all elements in either set"], "cases": [ { - "description": "union of empty sets", + "description": "union of empty sets is an empty set", "set1": [], "set2": [], "expected": [] }, { - "description": "union of empty set with set of one element", + "description": "union of an empty set and non-empty set is the non-empty set", "set1": [], "set2": [2], "expected": [2] }, { - "description": "union of empty set with non-empty set", - "set1": [], - "set2": [3, 2, 5], - "expected": [2, 3, 5] - }, - { - "description": "union of non-empty set with empty set", + "description": "union of a non-empty set and empty set is the non-empty set", "set1": [1, 3], "set2": [], "expected": [1, 3] }, { - "description": "union of a set with itself", - "set1": [1, 3], - "set2": [3, 1], - "expected": [1, 3] - }, - { - "description": "union with one element", - "set1": [1, 3], - "set2": [2], - "expected": [1, 2, 3] - }, - { - "description": "one element in common, one different", + "description": "union of non-empty sets contains all unique elements", "set1": [1, 3], "set2": [2, 3], "expected": [3, 2, 1] - }, - { - "description": "two elements in common", - "set1": [1, 2, 3, 4], - "set2": [3, 2, 5], - "expected": [1, 2, 3, 4, 5] } ] }, "difference": { - "description": ["Produce the set difference (set1 - set2)", - "or more specifically, (set1 ∖ set2)"], + "description": ["Difference (or Complement) of a set is a set of all elements that are only in the first set"], "cases": [ { - "description": "difference of two empty sets", + "description": "difference of two empty sets is an empty set", "set1": [], "set2": [], "expected": [] }, { - "description": "difference of empty set and non-empty set", + "description": "difference of empty set and non-empty set is an empty set", "set1": [], "set2": [3, 2, 5], "expected": [] }, { - "description": "difference of non-empty set and empty set", + "description": "difference of a non-empty set and an empty set is the non-empty set", "set1": [1, 2, 3, 4], "set2": [], "expected": [1, 2, 3, 4] }, { - "description": "no elements in common", - "set1": [1, 2, 3], - "set2": [4], - "expected": [1, 2, 3] - }, - { - "description": "one element in common, one extra", + "description": "difference of two non-empty sets is a set of elements that are only in the first set", "set1": [3, 2, 1], "set2": [2, 4], "expected": [1, 3] - }, - { - "description": "two elements in common, one extra", - "set1": [1, 2, 3, 4], - "set2": [3, 2, 5], - "expected": [1, 4] } ] }, "symmetric-difference": { - "description": [ - "Produce the symmetric difference of two sets. The symmetric", - "difference consists of elements in one or the other but not both." - ], + "description": ["Symmetric difference is a set of all elements that only appear in one set or the other, but not in both"], "cases": [ { - "description": "two empty sets", + "description": "symmetric difference of two empty sets is an empty set", "set1": [], "set2": [], "expected": [] }, { - "description": "empty set and non-empty set", + "description": "symmetric difference of an empty set and a non-empty set is the non-empty set", "set1": [], "set2": [3, 2, 5], "expected": [3, 2, 5] }, { - "description": "non-empty set and empty set", + "description": "symmetric difference of a non-empty set and an empty set is the non-empty set", "set1": [1, 2, 3, 4], "set2": [], "expected": [1, 2, 3, 4] }, { - "description": "no elements in common", - "set1": [1, 2, 3], - "set2": [4], - "expected": [1, 2, 3, 4] - }, - { - "description": "one element in common", + "description": "symmetric difference of two non-empty sets is a set of elements that only appear in one set or the other", "set1": [3, 2, 1], "set2": [2, 4], "expected": [1, 3, 4] } ] - }, - "mixed types": { - "description": ["Exercise various operations with mixed data types"], - "cases": [ - { - "operation": "add", - "set": [1, 2, 3], - "element": 3.0, - "expected": [1, 2, 3, 3.0] - }, - { - "operation": "delete mismatched type", - "set": [3, 2, 1], - "element": 2.0, - "expected": [1, 2, 3] - }, - { - "operation": "delete float", - "set": [3, 2.0, 1], - "element": 2.0, - "expected": [1, 3] - }, - { - "operation": "element", - "set": [1, 2, 3], - "element": 2.0, - "expected": false - }, - { - "operation": "subset", - "set1": [1, 2, 3.0], - "set2": [1, 2, 3, 4], - "expected": false - }, - { - "operation": "disjoint", - "set1": [1.0, 2.0], - "det2": [2, 3], - "expected": true - }, - { - "operation": "intersection", - "set1": [1, 2, 3], - "set2": [1.0, 2.0, 3], - "expected": [3] - }, - { - "operation": "union", - "set1": [1, 3], - "set2": [2, 3.0], - "expected": [3.0, 3, 2, 1] - }, - { - "operation": "difference", - "set1": [1, 2.0, 3], - "set2": [2, 4], - "expected": [1, 2.0, 3] - }, - { - "operation": "intersection", - "set1": ["a", "b", "c"], - "set2": ["a", "c", "d"], - "expected": ["a", "c"] - } - ] } }