diff --git a/applications/no_dups/no_dups.py b/applications/no_dups/no_dups.py index caa162c8c..6e01c1b95 100644 --- a/applications/no_dups/no_dups.py +++ b/applications/no_dups/no_dups.py @@ -1,6 +1,20 @@ def no_dups(s): - # Your code here + # edge case of empty string + if s == "": + return "" + # separate the list of words into an array + word_array = s.split(" ") + # create an empty list + no_dups_array = [] + # check to see if the word was already in the array + for word in word_array: + # if not then add + if word not in no_dups_array: + no_dups_array.append(word) + + # put the array back into a string and return + return " ".join(no_dups_array) if __name__ == "__main__": diff --git a/applications/word_count/word_count.py b/applications/word_count/word_count.py index a20546425..d5c52d9c4 100644 --- a/applications/word_count/word_count.py +++ b/applications/word_count/word_count.py @@ -1,9 +1,41 @@ +import re def word_count(s): - # Your code here + # make the list all lower case + lower_s = s.lower() + #remove special characters + special_chars = ['"', ':', ';', ',', '.', '-', '+', '=', '/', '\\', '|', '[', ']', '{', '}', '(', ')', '*', '^', '&'] + for special in special_chars: + lower_s = lower_s.replace(special, '') + for s in ['\r','\t','\n']: + lower_s = lower_s.replace(s, " ") + + # create an array from the string separating on empty spaces + word_list = lower_s.split(" ") + # create an empty dictionary + word_dic = {} + #check for edge case of empty string + if s == "": + return {} + + # loop through array + for word in word_list: + # ignore if empty space + if word == "": + continue + #if the word is in the dictionary add by 1 + if word in word_dic: + word_dic[word] += 1 + # else create a new element in the dictionary + else: + word_dic[word] = 1 + + # return the dictionary + return word_dic if __name__ == "__main__": + print(word_count('a a\ra\na\ta \t\r\n')) print(word_count("")) print(word_count("Hello")) print(word_count('Hello, my cat. And my cat doesn\'t say "hello" back.')) diff --git a/hashtable/hashtable.py b/hashtable/hashtable.py index 0205f0ba9..e2391d2f8 100644 --- a/hashtable/hashtable.py +++ b/hashtable/hashtable.py @@ -11,7 +11,6 @@ def __init__(self, key, value): # Hash table can't have fewer than this many slots MIN_CAPACITY = 8 - class HashTable: """ A hash table that with `capacity` buckets @@ -21,7 +20,9 @@ class HashTable: """ def __init__(self, capacity): - # Your code here + self.capacity = MIN_CAPACITY + self.storage = [None] * capacity + self.length = 0 def get_num_slots(self): @@ -34,7 +35,7 @@ def get_num_slots(self): Implement this. """ - # Your code here + return self.capacity def get_load_factor(self): @@ -43,7 +44,7 @@ def get_load_factor(self): Implement this. """ - # Your code here + return self.length / self.capacity def fnv1(self, key): @@ -52,9 +53,7 @@ def fnv1(self, key): Implement this, and/or DJB2. """ - - # Your code here - + def djb2(self, key): """ @@ -62,8 +61,11 @@ def djb2(self, key): Implement this, and/or FNV-1. """ - # Your code here + hash = 5381 + for i in key: + hash = (( hash << 5) + hash)+ ord(i) + return hash & 0xffffffff def hash_index(self, key): """ @@ -81,7 +83,44 @@ def put(self, key, value): Implement this. """ - # Your code here + # index = self.hash_index(key) + # self.storage[index] = value + + # the index is the spot where it's going + index = self.hash_index(key) + # node is the entry itself + new_node = HashTableEntry(key, value) + + # keep track of the current node = head + current_node = self.storage[index] + + # If this is the first node, create the node and increase the length to 1 + if current_node is None: + self.storage[index] = new_node + self.length += 1 + return + + # as long as we aren't working with an empty or repeat node + while current_node is not None and current_node.key != key: + # the current node will now be the previous + prev = current_node + # we are making the current node the next one in line + current_node = current_node.next + + # if we are working with an empty list, the new_node is now the previous node + if current_node is None: + prev.next = new_node + self.length += 1 + # otherwise assign the value to the current node + else: + current_node.value = value + + # calculate the load factor + load_factor = self.get_load_factor() + + # if the load factor is higher than 0.7 double the capacity + if load_factor > 0.7: + self.resize(self.capacity * 2) def delete(self, key): @@ -92,7 +131,31 @@ def delete(self, key): Implement this. """ - # Your code here + index = self.hash_index(key) + node = self.storage[index] + + if node.key == key: + self.storage[index] = node.next + self.length -= 1 + return + + while node is not None and node.key != key: + prev_node = node + node = node.next + + if node is None: + return None + + prev_node.next = node.next + self.length -= 1 + + load_factor = self.get_load_factor() + + if load_factor < MIN_CAPACITY: + self.resize(self.capacity) + + + self.storage[index] = None def get(self, key): @@ -103,8 +166,21 @@ def get(self, key): Implement this. """ - # Your code here - + # keep track of the index of the hashtable + index = self.hash_index(key) + # return self.storage[index] + + # this is to keep track of the linked list inside each container + node = self.storage[index] + + # we are going to loop through the entire linked list until we run out of entries + # or we find a match + while node is not None and node.key != key: + # if we find a match then we assign the value of the next node to our node. + node = node.next + # if we don't find the value we return none + # if we find it then we return the value + return None if node is None else node.value def resize(self, new_capacity): """ @@ -113,7 +189,17 @@ def resize(self, new_capacity): Implement this. """ - # Your code here + old_storage = self.storage + self.capacity = new_capacity + self.storage = [None] * self.capacity + + for i in range(len(old_storage)): + node = old_storage[i] + + while node is not None: + index = self.hash_index(node.key) + self.storage[index] = node + node = node.next