Skip to content

Commit

Permalink
custom-set: implement exercise (#1140)
Browse files Browse the repository at this point in the history
* custom-set: add README

* custom-set: update config.json

* custom-set: write test cases

* custom-set: add solution template

* custom-set: add example solution

* custom-set: use operator overloads

* update to canonical-data v1.1.0

* fixes re: review by @N-Parsons
  • Loading branch information
cmccandless authored and Nathan Parsons committed Jan 19, 2018
1 parent ad3be2a commit 09de6ff
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 0 deletions.
10 changes: 10 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,16 @@
"object_oriented_programming"
]
},
{
"uuid": "bb07c236-062c-2980-483a-a221e4724445dcd6f32",
"slug": "custom-set",
"core": false,
"unlocked_by": null,
"difficulty": 5,
"topics": [
"sets"
]
},
{
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
"slug": "accumulate",
Expand Down
20 changes: 20 additions & 0 deletions exercises/custom-set/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Custom-Set

Create a custom set type.

Sometimes it is necessary to define a custom data structure of some
type, like a set. In this exercise you will define your own set. How it
works internally doesn't matter, as long as it behaves like a set of
unique elements.

## Submitting Exercises

Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.

For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/python/bob/bob.py`.

For more detailed information about running tests, code style and linting,
please see the [help page](http://exercism.io/languages/python).

## Submitting Incomplete Solutions
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
30 changes: 30 additions & 0 deletions exercises/custom-set/custom_set.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class CustomSet(object):
def __init__(self, elements=[]):
pass

def isempty(self):
pass

def __contains__(self, element):
pass

def issubset(self, other):
pass

def isdisjoint(self, other):
pass

def __eq__(self, other):
pass

def add(self, element):
pass

def intersection(self, other):
pass

def difference(self, other):
pass

def union(self, other):
pass
212 changes: 212 additions & 0 deletions exercises/custom-set/custom_set_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import unittest

from custom_set import CustomSet


# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0

class CustomSetTest(unittest.TestCase):
def test_sets_with_no_elements_are_empty(self):
sut = CustomSet()
self.assertIs(sut.isempty(), True)

def test_sets_with_elements_are_not_empty(self):
sut = CustomSet([1])
self.assertIs(sut.isempty(), False)

def test_empty_set_contains_nothing(self):
sut = CustomSet()
self.assertNotIn(1, sut)

def test_set_contains_when_element_in_set(self):
sut = CustomSet([1])
self.assertIn(1, sut)

def test_set_does_not_contains_when_element_not_in_set(self):
sut = CustomSet([1, 2, 3])
self.assertNotIn(4, sut)

def test_empty_set_is_subset_of_another_empty_set(self):
set1 = CustomSet()
set2 = CustomSet()
self.assertIs(set1.issubset(set2), True)

def test_empty_set_is_subset_of_non_empty_set(self):
set1 = CustomSet()
set2 = CustomSet([1])
self.assertIs(set1.issubset(set2), True)

def test_non_empty_set_is_not_subet_of_empty_set(self):
set1 = CustomSet([1])
set2 = CustomSet()
self.assertIs(set1.issubset(set2), False)

def test_set_is_subset_of_set_with_exact_same_elements(self):
set1 = CustomSet([1, 2, 3])
set2 = CustomSet([1, 2, 3])
self.assertIs(set1.issubset(set2), True)

def test_set_is_subset_of_larger_set_with_same_elements(self):
set1 = CustomSet([1, 2, 3])
set2 = CustomSet([4, 1, 2, 3])
self.assertIs(set1.issubset(set2), True)

def test_set_not_subset_of_set_that_does_not_contain_its_elements(self):
set1 = CustomSet([1, 2, 3])
set2 = CustomSet([4, 1, 3])
self.assertIs(set1.issubset(set2), False)

def test_empty_set_disjoint_with_itself(self):
set1 = CustomSet()
set2 = CustomSet()
self.assertIs(set1.isdisjoint(set2), True)

def test_empty_set_disjoint_with_non_empty_set(self):
set1 = CustomSet()
set2 = CustomSet([1])
self.assertIs(set1.isdisjoint(set2), True)

def test_non_empty_set_disjoint_with_empty_set(self):
set1 = CustomSet([1])
set2 = CustomSet()
self.assertIs(set1.isdisjoint(set2), True)

def test_sets_not_disjoint_if_element_is_shared(self):
set1 = CustomSet([1, 2])
set2 = CustomSet([2, 3])
self.assertIs(set1.isdisjoint(set2), False)

def test_sets_disjoint_if_not_elements_are_shared(self):
set1 = CustomSet([1, 2])
set2 = CustomSet([3, 4])
self.assertIs(set1.isdisjoint(set2), True)

def test_empty_sets_are_equal(self):
set1 = CustomSet()
set2 = CustomSet()
self.assertEqual(set1, set2)

def test_empty_set_not_equal_to_non_empty_set(self):
set1 = CustomSet()
set2 = CustomSet([1, 2, 3])
self.assertNotEqual(set1, set2)

def test_non_empty_set_not_equal_to_empty_set(self):
set1 = CustomSet([1, 2, 3])
set2 = CustomSet()
self.assertNotEqual(set1, set2)

def test_sets_with_same_exact_same_elements_are_equal(self):
set1 = CustomSet([1, 2])
set2 = CustomSet([2, 1])
self.assertEqual(set1, set2)

def test_sets_with_different_elements_are_not_equal(self):
set1 = CustomSet([1, 2, 3])
set2 = CustomSet([1, 2, 4])
self.assertNotEqual(set1, set2)

def test_set_is_not_equal_to_larger_set_with_same_elements(self):
set1 = CustomSet([1, 2, 3])
set2 = CustomSet([1, 2, 3, 4])
self.assertNotEqual(set1, set2)

def test_add_to_empty_set(self):
sut = CustomSet()
sut.add(1)
expected = CustomSet([1])
self.assertEqual(sut, expected)

def test_add_to_non_empty_set(self):
sut = CustomSet([1, 2, 4])
sut.add(3)
expected = CustomSet([1, 2, 3, 4])
self.assertEqual(sut, expected)

def test_adding_existing_element_does_not_change_set(self):
sut = CustomSet([1, 2, 3])
sut.add(3)
expected = CustomSet([1, 2, 3])
self.assertEqual(sut, expected)

def test_intersection_of_two_empty_sets_is_empty_set(self):
set1 = CustomSet()
set2 = CustomSet()
expected = CustomSet()
self.assertEqual(set1.intersection(set2), expected)

def test_intersection_of_empty_set_and_non_empty_set_is_empty_set(self):
set1 = CustomSet()
set2 = CustomSet([3, 2, 5])
expected = CustomSet()
self.assertEqual(set1.intersection(set2), expected)

def test_intersection_of_non_empty_set_and_empty_set_is_empty_set(self):
set1 = CustomSet([1, 2, 3, 4])
set2 = CustomSet()
expected = CustomSet()
self.assertEqual(set1.intersection(set2), expected)

def test_intersection_of_sets_with_no_shared_elements_is_empty_set(self):
set1 = CustomSet([1, 2, 3])
set2 = CustomSet([4, 5, 6])
expected = CustomSet()
self.assertEqual(set1.intersection(set2), expected)

def test_intersection_contains_shared_elements_only(self):
set1 = CustomSet([1, 2, 3, 4])
set2 = CustomSet([3, 2, 5])
expected = CustomSet([2, 3])
self.assertEqual(set1.intersection(set2), expected)

def test_difference_of_two_empty_sets_is_empty_set(self):
set1 = CustomSet()
set2 = CustomSet()
expected = CustomSet()
self.assertEqual(set1 - set2, expected)

def test_difference_of_empty_set_and_non_empty_set_is_empty_set(self):
set1 = CustomSet()
set2 = CustomSet([3, 2, 5])
expected = CustomSet()
self.assertEqual(set1 - set2, expected)

def test_difference_of_non_empty_set_and_empty_set_is_non_empty_set(self):
set1 = CustomSet([1, 2, 3, 4])
set2 = CustomSet()
expected = CustomSet([1, 2, 3, 4])
self.assertEqual(set1 - set2, expected)

def test_difference_of_non_empty_sets_elements_in_first_set_only(self):
set1 = CustomSet([3, 2, 1])
set2 = CustomSet([2, 4])
expected = CustomSet([1, 3])
self.assertEqual(set1 - set2, expected)

def test_union_of_empty_sets_is_empty_set(self):
set1 = CustomSet()
set2 = CustomSet()
expected = CustomSet()
self.assertEqual(set1 + set2, expected)

def test_union_of_empty_set_and_non_empty_set_is_the_non_empty_set(self):
set1 = CustomSet()
set2 = CustomSet([2])
expected = CustomSet([2])
self.assertEqual(set1 + set2, expected)

def test_union_of_non_empty_set_and_empty_set_is_the_non_empty_set(self):
set1 = CustomSet([1, 3])
set2 = CustomSet()
expected = CustomSet([1, 3])
self.assertEqual(set1 + set2, expected)

def test_union_of_non_empty_sets_contains_all_unique_elements(self):
set1 = CustomSet([1, 3])
set2 = CustomSet([2, 3])
expected = CustomSet([1, 2, 3])
self.assertEqual(set1 + set2, expected)


if __name__ == '__main__':
unittest.main()
45 changes: 45 additions & 0 deletions exercises/custom-set/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
class CustomSet(object):
def __init__(self, elements=[]):
self.elements = list(elements)

def isempty(self):
return not self.elements

def __iter__(self):
return iter(self.elements)

def __contains__(self, element):
return element in self.elements

def issubset(self, other):
return all(x in other for x in self)

def isdisjoint(self, other):
return all(x not in other for x in self)

def __eq__(self, other):
return self.issubset(other) and other.issubset(self)

def add(self, element):
if element not in self:
self.elements.append(element)

def intersection(self, other):
result = CustomSet()
for x in self:
if x in other:
result.add(x)
return result

def __sub__(self, other):
result = CustomSet()
for x in self:
if x not in other:
result.add(x)
return result

def __add__(self, other):
result = CustomSet(self.elements)
for x in other:
result.add(x)
return result

0 comments on commit 09de6ff

Please sign in to comment.