Skip to content

Commit 09de6ff

Browse files
cmccandlessNathan Parsons
authored andcommitted
custom-set: implement exercise (exercism#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
1 parent ad3be2a commit 09de6ff

5 files changed

Lines changed: 317 additions & 0 deletions

File tree

config.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,16 @@
12581258
"object_oriented_programming"
12591259
]
12601260
},
1261+
{
1262+
"uuid": "bb07c236-062c-2980-483a-a221e4724445dcd6f32",
1263+
"slug": "custom-set",
1264+
"core": false,
1265+
"unlocked_by": null,
1266+
"difficulty": 5,
1267+
"topics": [
1268+
"sets"
1269+
]
1270+
},
12611271
{
12621272
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
12631273
"slug": "accumulate",

exercises/custom-set/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Custom-Set
2+
3+
Create a custom set type.
4+
5+
Sometimes it is necessary to define a custom data structure of some
6+
type, like a set. In this exercise you will define your own set. How it
7+
works internally doesn't matter, as long as it behaves like a set of
8+
unique elements.
9+
10+
## Submitting Exercises
11+
12+
Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
13+
14+
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`.
15+
16+
For more detailed information about running tests, code style and linting,
17+
please see the [help page](http://exercism.io/languages/python).
18+
19+
## Submitting Incomplete Solutions
20+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

exercises/custom-set/custom_set.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class CustomSet(object):
2+
def __init__(self, elements=[]):
3+
pass
4+
5+
def isempty(self):
6+
pass
7+
8+
def __contains__(self, element):
9+
pass
10+
11+
def issubset(self, other):
12+
pass
13+
14+
def isdisjoint(self, other):
15+
pass
16+
17+
def __eq__(self, other):
18+
pass
19+
20+
def add(self, element):
21+
pass
22+
23+
def intersection(self, other):
24+
pass
25+
26+
def difference(self, other):
27+
pass
28+
29+
def union(self, other):
30+
pass
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import unittest
2+
3+
from custom_set import CustomSet
4+
5+
6+
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0
7+
8+
class CustomSetTest(unittest.TestCase):
9+
def test_sets_with_no_elements_are_empty(self):
10+
sut = CustomSet()
11+
self.assertIs(sut.isempty(), True)
12+
13+
def test_sets_with_elements_are_not_empty(self):
14+
sut = CustomSet([1])
15+
self.assertIs(sut.isempty(), False)
16+
17+
def test_empty_set_contains_nothing(self):
18+
sut = CustomSet()
19+
self.assertNotIn(1, sut)
20+
21+
def test_set_contains_when_element_in_set(self):
22+
sut = CustomSet([1])
23+
self.assertIn(1, sut)
24+
25+
def test_set_does_not_contains_when_element_not_in_set(self):
26+
sut = CustomSet([1, 2, 3])
27+
self.assertNotIn(4, sut)
28+
29+
def test_empty_set_is_subset_of_another_empty_set(self):
30+
set1 = CustomSet()
31+
set2 = CustomSet()
32+
self.assertIs(set1.issubset(set2), True)
33+
34+
def test_empty_set_is_subset_of_non_empty_set(self):
35+
set1 = CustomSet()
36+
set2 = CustomSet([1])
37+
self.assertIs(set1.issubset(set2), True)
38+
39+
def test_non_empty_set_is_not_subet_of_empty_set(self):
40+
set1 = CustomSet([1])
41+
set2 = CustomSet()
42+
self.assertIs(set1.issubset(set2), False)
43+
44+
def test_set_is_subset_of_set_with_exact_same_elements(self):
45+
set1 = CustomSet([1, 2, 3])
46+
set2 = CustomSet([1, 2, 3])
47+
self.assertIs(set1.issubset(set2), True)
48+
49+
def test_set_is_subset_of_larger_set_with_same_elements(self):
50+
set1 = CustomSet([1, 2, 3])
51+
set2 = CustomSet([4, 1, 2, 3])
52+
self.assertIs(set1.issubset(set2), True)
53+
54+
def test_set_not_subset_of_set_that_does_not_contain_its_elements(self):
55+
set1 = CustomSet([1, 2, 3])
56+
set2 = CustomSet([4, 1, 3])
57+
self.assertIs(set1.issubset(set2), False)
58+
59+
def test_empty_set_disjoint_with_itself(self):
60+
set1 = CustomSet()
61+
set2 = CustomSet()
62+
self.assertIs(set1.isdisjoint(set2), True)
63+
64+
def test_empty_set_disjoint_with_non_empty_set(self):
65+
set1 = CustomSet()
66+
set2 = CustomSet([1])
67+
self.assertIs(set1.isdisjoint(set2), True)
68+
69+
def test_non_empty_set_disjoint_with_empty_set(self):
70+
set1 = CustomSet([1])
71+
set2 = CustomSet()
72+
self.assertIs(set1.isdisjoint(set2), True)
73+
74+
def test_sets_not_disjoint_if_element_is_shared(self):
75+
set1 = CustomSet([1, 2])
76+
set2 = CustomSet([2, 3])
77+
self.assertIs(set1.isdisjoint(set2), False)
78+
79+
def test_sets_disjoint_if_not_elements_are_shared(self):
80+
set1 = CustomSet([1, 2])
81+
set2 = CustomSet([3, 4])
82+
self.assertIs(set1.isdisjoint(set2), True)
83+
84+
def test_empty_sets_are_equal(self):
85+
set1 = CustomSet()
86+
set2 = CustomSet()
87+
self.assertEqual(set1, set2)
88+
89+
def test_empty_set_not_equal_to_non_empty_set(self):
90+
set1 = CustomSet()
91+
set2 = CustomSet([1, 2, 3])
92+
self.assertNotEqual(set1, set2)
93+
94+
def test_non_empty_set_not_equal_to_empty_set(self):
95+
set1 = CustomSet([1, 2, 3])
96+
set2 = CustomSet()
97+
self.assertNotEqual(set1, set2)
98+
99+
def test_sets_with_same_exact_same_elements_are_equal(self):
100+
set1 = CustomSet([1, 2])
101+
set2 = CustomSet([2, 1])
102+
self.assertEqual(set1, set2)
103+
104+
def test_sets_with_different_elements_are_not_equal(self):
105+
set1 = CustomSet([1, 2, 3])
106+
set2 = CustomSet([1, 2, 4])
107+
self.assertNotEqual(set1, set2)
108+
109+
def test_set_is_not_equal_to_larger_set_with_same_elements(self):
110+
set1 = CustomSet([1, 2, 3])
111+
set2 = CustomSet([1, 2, 3, 4])
112+
self.assertNotEqual(set1, set2)
113+
114+
def test_add_to_empty_set(self):
115+
sut = CustomSet()
116+
sut.add(1)
117+
expected = CustomSet([1])
118+
self.assertEqual(sut, expected)
119+
120+
def test_add_to_non_empty_set(self):
121+
sut = CustomSet([1, 2, 4])
122+
sut.add(3)
123+
expected = CustomSet([1, 2, 3, 4])
124+
self.assertEqual(sut, expected)
125+
126+
def test_adding_existing_element_does_not_change_set(self):
127+
sut = CustomSet([1, 2, 3])
128+
sut.add(3)
129+
expected = CustomSet([1, 2, 3])
130+
self.assertEqual(sut, expected)
131+
132+
def test_intersection_of_two_empty_sets_is_empty_set(self):
133+
set1 = CustomSet()
134+
set2 = CustomSet()
135+
expected = CustomSet()
136+
self.assertEqual(set1.intersection(set2), expected)
137+
138+
def test_intersection_of_empty_set_and_non_empty_set_is_empty_set(self):
139+
set1 = CustomSet()
140+
set2 = CustomSet([3, 2, 5])
141+
expected = CustomSet()
142+
self.assertEqual(set1.intersection(set2), expected)
143+
144+
def test_intersection_of_non_empty_set_and_empty_set_is_empty_set(self):
145+
set1 = CustomSet([1, 2, 3, 4])
146+
set2 = CustomSet()
147+
expected = CustomSet()
148+
self.assertEqual(set1.intersection(set2), expected)
149+
150+
def test_intersection_of_sets_with_no_shared_elements_is_empty_set(self):
151+
set1 = CustomSet([1, 2, 3])
152+
set2 = CustomSet([4, 5, 6])
153+
expected = CustomSet()
154+
self.assertEqual(set1.intersection(set2), expected)
155+
156+
def test_intersection_contains_shared_elements_only(self):
157+
set1 = CustomSet([1, 2, 3, 4])
158+
set2 = CustomSet([3, 2, 5])
159+
expected = CustomSet([2, 3])
160+
self.assertEqual(set1.intersection(set2), expected)
161+
162+
def test_difference_of_two_empty_sets_is_empty_set(self):
163+
set1 = CustomSet()
164+
set2 = CustomSet()
165+
expected = CustomSet()
166+
self.assertEqual(set1 - set2, expected)
167+
168+
def test_difference_of_empty_set_and_non_empty_set_is_empty_set(self):
169+
set1 = CustomSet()
170+
set2 = CustomSet([3, 2, 5])
171+
expected = CustomSet()
172+
self.assertEqual(set1 - set2, expected)
173+
174+
def test_difference_of_non_empty_set_and_empty_set_is_non_empty_set(self):
175+
set1 = CustomSet([1, 2, 3, 4])
176+
set2 = CustomSet()
177+
expected = CustomSet([1, 2, 3, 4])
178+
self.assertEqual(set1 - set2, expected)
179+
180+
def test_difference_of_non_empty_sets_elements_in_first_set_only(self):
181+
set1 = CustomSet([3, 2, 1])
182+
set2 = CustomSet([2, 4])
183+
expected = CustomSet([1, 3])
184+
self.assertEqual(set1 - set2, expected)
185+
186+
def test_union_of_empty_sets_is_empty_set(self):
187+
set1 = CustomSet()
188+
set2 = CustomSet()
189+
expected = CustomSet()
190+
self.assertEqual(set1 + set2, expected)
191+
192+
def test_union_of_empty_set_and_non_empty_set_is_the_non_empty_set(self):
193+
set1 = CustomSet()
194+
set2 = CustomSet([2])
195+
expected = CustomSet([2])
196+
self.assertEqual(set1 + set2, expected)
197+
198+
def test_union_of_non_empty_set_and_empty_set_is_the_non_empty_set(self):
199+
set1 = CustomSet([1, 3])
200+
set2 = CustomSet()
201+
expected = CustomSet([1, 3])
202+
self.assertEqual(set1 + set2, expected)
203+
204+
def test_union_of_non_empty_sets_contains_all_unique_elements(self):
205+
set1 = CustomSet([1, 3])
206+
set2 = CustomSet([2, 3])
207+
expected = CustomSet([1, 2, 3])
208+
self.assertEqual(set1 + set2, expected)
209+
210+
211+
if __name__ == '__main__':
212+
unittest.main()

exercises/custom-set/example.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
class CustomSet(object):
2+
def __init__(self, elements=[]):
3+
self.elements = list(elements)
4+
5+
def isempty(self):
6+
return not self.elements
7+
8+
def __iter__(self):
9+
return iter(self.elements)
10+
11+
def __contains__(self, element):
12+
return element in self.elements
13+
14+
def issubset(self, other):
15+
return all(x in other for x in self)
16+
17+
def isdisjoint(self, other):
18+
return all(x not in other for x in self)
19+
20+
def __eq__(self, other):
21+
return self.issubset(other) and other.issubset(self)
22+
23+
def add(self, element):
24+
if element not in self:
25+
self.elements.append(element)
26+
27+
def intersection(self, other):
28+
result = CustomSet()
29+
for x in self:
30+
if x in other:
31+
result.add(x)
32+
return result
33+
34+
def __sub__(self, other):
35+
result = CustomSet()
36+
for x in self:
37+
if x not in other:
38+
result.add(x)
39+
return result
40+
41+
def __add__(self, other):
42+
result = CustomSet(self.elements)
43+
for x in other:
44+
result.add(x)
45+
return result

0 commit comments

Comments
 (0)