@@ -54,6 +54,14 @@ def _get_next_ind(self, ind: int) -> int:
5454 Get next index.
5555
5656 Implements linear open addressing.
57+ >>> HashMap(5)._get_next_ind(3)
58+ 4
59+ >>> HashMap(5)._get_next_ind(5)
60+ 1
61+ >>> HashMap(5)._get_next_ind(6)
62+ 2
63+ >>> HashMap(5)._get_next_ind(9)
64+ 0
5765 """
5866 return (ind + 1 ) % len (self ._buckets )
5967
@@ -82,6 +90,14 @@ def _is_full(self) -> bool:
8290 Return true if we have reached safe capacity.
8391
8492 So we need to increase the number of buckets to avoid collisions.
93+
94+ >>> hm = HashMap(2)
95+ >>> hm._add_item(1, 10)
96+ >>> hm._add_item(2, 20)
97+ >>> hm._is_full()
98+ True
99+ >>> HashMap(2)._is_full()
100+ False
85101 """
86102 limit = len (self ._buckets ) * self ._capacity_factor
87103 return len (self ) >= int (limit )
@@ -114,17 +130,104 @@ def _iterate_buckets(self, key: KEY) -> Iterator[int]:
114130 ind = self ._get_next_ind (ind )
115131
116132 def _add_item (self , key : KEY , val : VAL ) -> None :
133+ """
134+ Try to add 3 elements when the size is 5
135+ >>> hm = HashMap(5)
136+ >>> hm._add_item(1, 10)
137+ >>> hm._add_item(2, 20)
138+ >>> hm._add_item(3, 30)
139+ >>> hm
140+ HashMap(1: 10, 2: 20, 3: 30)
141+
142+ Try to add 3 elements when the size is 5
143+ >>> hm = HashMap(5)
144+ >>> hm._add_item(-5, 10)
145+ >>> hm._add_item(6, 30)
146+ >>> hm._add_item(-7, 20)
147+ >>> hm
148+ HashMap(-5: 10, 6: 30, -7: 20)
149+
150+ Try to add 3 elements when size is 1
151+ >>> hm = HashMap(1)
152+ >>> hm._add_item(10, 13.2)
153+ >>> hm._add_item(6, 5.26)
154+ >>> hm._add_item(7, 5.155)
155+ >>> hm
156+ HashMap(10: 13.2)
157+
158+ Trying to add an element with a key that is a floating point value
159+ >>> hm = HashMap(5)
160+ >>> hm._add_item(1.5, 10)
161+ >>> hm
162+ HashMap(1.5: 10)
163+
164+ 5. Trying to add an item with the same key
165+ >>> hm = HashMap(5)
166+ >>> hm._add_item(1, 10)
167+ >>> hm._add_item(1, 20)
168+ >>> hm
169+ HashMap(1: 20)
170+ """
117171 for ind in self ._iterate_buckets (key ):
118172 if self ._try_set (ind , key , val ):
119173 break
120174
121175 def __setitem__ (self , key : KEY , val : VAL ) -> None :
176+ """
177+ 1. Changing value of item whose key is present
178+ >>> hm = HashMap(5)
179+ >>> hm._add_item(1, 10)
180+ >>> hm.__setitem__(1, 20)
181+ >>> hm
182+ HashMap(1: 20)
183+
184+ 2. Changing value of item whose key is not present
185+ >>> hm = HashMap(5)
186+ >>> hm._add_item(1, 10)
187+ >>> hm.__setitem__(0, 20)
188+ >>> hm
189+ HashMap(0: 20, 1: 10)
190+
191+ 3. Changing the value of the same item multiple times
192+ >>> hm = HashMap(5)
193+ >>> hm._add_item(1, 10)
194+ >>> hm.__setitem__(1, 20)
195+ >>> hm.__setitem__(1, 30)
196+ >>> hm
197+ HashMap(1: 30)
198+ """
122199 if self ._is_full ():
123200 self ._size_up ()
124201
125202 self ._add_item (key , val )
126203
127204 def __delitem__ (self , key : KEY ) -> None :
205+ """
206+ >>> hm = HashMap(5)
207+ >>> hm._add_item(1, 10)
208+ >>> hm._add_item(2, 20)
209+ >>> hm._add_item(3, 30)
210+ >>> hm.__delitem__(3)
211+ >>> hm
212+ HashMap(1: 10, 2: 20)
213+ >>> hm = HashMap(5)
214+ >>> hm._add_item(-5, 10)
215+ >>> hm._add_item(6, 30)
216+ >>> hm._add_item(-7, 20)
217+ >>> hm.__delitem__(-5)
218+ >>> hm
219+ HashMap(6: 30, -7: 20)
220+
221+ # Trying to remove a non-existing item
222+ >>> hm = HashMap(5)
223+ >>> hm._add_item(1, 10)
224+ >>> hm._add_item(2, 20)
225+ >>> hm._add_item(3, 30)
226+ >>> hm.__delitem__(4)
227+ Traceback (most recent call last):
228+ ...
229+ KeyError: 4
230+ """
128231 for ind in self ._iterate_buckets (key ):
129232 item = self ._buckets [ind ]
130233 if item is None :
@@ -156,7 +259,13 @@ def __iter__(self) -> Iterator[KEY]:
156259 yield from (item .key for item in self ._buckets if item )
157260
158261 def __repr__ (self ) -> str :
159- val_string = " , " .join (
262+ val_string = ", " .join (
160263 f"{ item .key } : { item .val } " for item in self ._buckets if item
161264 )
162265 return f"HashMap({ val_string } )"
266+
267+
268+ if __name__ == "__main__" :
269+ import doctest
270+
271+ doctest .testmod ()
0 commit comments