-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
custom-set: implement exercise (#1140)
* 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
1 parent
ad3be2a
commit 09de6ff
Showing
5 changed files
with
317 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |