-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
custom-set: implement exercise #1140
Changes from 8 commits
d685063
bf1cd61
1de55a0
459fe3d
872ba8c
9f6d264
5129f3a
4d6c6a9
5d5e619
a2daea4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
class CustomSet(object): | ||
def __init__(self, elements=[]): | ||
pass | ||
|
||
def empty(self): | ||
pass | ||
|
||
def __iter__(self): | ||
pass | ||
|
||
def subset(self, other): | ||
pass | ||
|
||
def disjoint(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 |
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.empty(), True) | ||
|
||
def test_sets_with_elements_are_not_empty(self): | ||
sut = CustomSet([1]) | ||
self.assertIs(sut.empty(), 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.subset(set2), True) | ||
|
||
def test_empty_set_is_subset_of_non_empty_set(self): | ||
set1 = CustomSet() | ||
set2 = CustomSet([1]) | ||
self.assertIs(set1.subset(set2), True) | ||
|
||
def test_non_empty_set_is_not_subet_of_empty_set(self): | ||
set1 = CustomSet([1]) | ||
set2 = CustomSet() | ||
self.assertIs(set1.subset(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.subset(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.subset(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.subset(set2), False) | ||
|
||
def test_empty_set_disjoint_with_itself(self): | ||
set1 = CustomSet() | ||
set2 = CustomSet() | ||
self.assertIs(set1.disjoint(set2), True) | ||
|
||
def test_empty_set_disjoint_with_non_empty_set(self): | ||
set1 = CustomSet() | ||
set2 = CustomSet([1]) | ||
self.assertIs(set1.disjoint(set2), True) | ||
|
||
def test_non_empty_set_disjoint_with_empty_set(self): | ||
set1 = CustomSet([1]) | ||
set2 = CustomSet() | ||
self.assertIs(set1.disjoint(set2), True) | ||
|
||
def test_sets_not_disjoint_if_element_is_shared(self): | ||
set1 = CustomSet([1, 2]) | ||
set2 = CustomSet([2, 3]) | ||
self.assertIs(set1.disjoint(set2), False) | ||
|
||
def test_sets_disjoint_if_not_elements_are_shared(self): | ||
set1 = CustomSet([1, 2]) | ||
set2 = CustomSet([3, 4]) | ||
self.assertIs(set1.disjoint(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() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
class CustomSet(object): | ||
def __init__(self, elements=[]): | ||
self.elements = list(elements) | ||
|
||
def empty(self): | ||
return not any(self.elements) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch... fixing. |
||
|
||
def __iter__(self): | ||
return iter(self.elements) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I somehow was not aware of the |
||
|
||
def subset(self, other): | ||
return all(x in other for x in self) | ||
|
||
def disjoint(self, other): | ||
return all(x not in other for x in self) | ||
|
||
def __eq__(self, other): | ||
return self.subset(other) and other.subset(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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these should be
isdisjoint
andissubset
to match with Python's implementation ofset
. I would also then changeempty
toisempty
for consistency.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.