From ed4452d1afd1b8cd2aa39221c8efbe63e441e814 Mon Sep 17 00:00:00 2001 From: Sangeet K Date: Mon, 9 Sep 2019 21:38:32 -0700 Subject: [PATCH 1/4] Add delete to trie.py + tests --- data_structures/trie/trie.py | 46 +++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py index b6234c6704c6..da28e4a5fe2a 100644 --- a/data_structures/trie/trie.py +++ b/data_structures/trie/trie.py @@ -47,6 +47,35 @@ def find(self, word: str) -> bool: # noqa: E999 This syntax is Python 3 only curr = curr.nodes[char] return curr.is_leaf + def delete(self, word: str): + """ + Deletes a word in a Trie + :param word: word to delete + :return: None + """ + + def _delete(curr: TrieNode, word: str, index: int): + if index == len(word): + # If word does not exist + if not curr.is_leaf: + return False + curr.is_leaf = False + return len(curr.nodes) == 0 + char = word[index] + char_node = curr.nodes.get(char) + # If char not in current trie node + if not char_node: + return False + delete_curr = _delete( + char_node, word, index + 1 + ) # Flag to check if node can be deleted + if delete_curr: + del curr.nodes[char] + return len(curr.nodes) == 0 + return delete_curr + + _delete(self, word, 0) + def print_words(node: TrieNode, word: str): # noqa: E999 This syntax is Python 3 only """ @@ -56,20 +85,25 @@ def print_words(node: TrieNode, word: str): # noqa: E999 This syntax is Python :return: None """ if node.is_leaf: - print(word, end=' ') + print(word, end=" ") for key, value in node.nodes.items(): print_words(value, word + key) def test(): - words = ['banana', 'bananas', 'bandana', 'band', 'apple', 'all', 'beast'] + words = ["banana", "bananas", "bandana", "band", "apple", "all", "beast"] root = TrieNode() root.insert_many(words) # print_words(root, '') - assert root.find('banana') - assert not root.find('bandanas') - assert not root.find('apps') - assert root.find('apple') + assert root.find("banana") + assert not root.find("bandanas") + assert not root.find("apps") + assert root.find("apple") + root.delete("all") + assert not root.find("all") + root.delete("banana") + assert not root.find("banana") + test() From 32cf4e7b429338befbec08202e6463dce3ad3679 Mon Sep 17 00:00:00 2001 From: Sangeet K Date: Fri, 13 Sep 2019 03:31:02 -0700 Subject: [PATCH 2/4] Minor fixes + tests --- data_structures/trie/trie.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py index da28e4a5fe2a..077af4f44107 100644 --- a/data_structures/trie/trie.py +++ b/data_structures/trie/trie.py @@ -66,9 +66,8 @@ def _delete(curr: TrieNode, word: str, index: int): # If char not in current trie node if not char_node: return False - delete_curr = _delete( - char_node, word, index + 1 - ) # Flag to check if node can be deleted + # Flag to check if node can be deleted + delete_curr = _delete(char_node, word, index + 1) if delete_curr: del curr.nodes[char] return len(curr.nodes) == 0 @@ -100,10 +99,12 @@ def test(): assert not root.find("bandanas") assert not root.find("apps") assert root.find("apple") + assert root.find("all") root.delete("all") assert not root.find("all") root.delete("banana") assert not root.find("banana") + assert root.find("bananas") test() From 2015b518fa07b42363f8dcadfa50dd21ffea8c38 Mon Sep 17 00:00:00 2001 From: Sangeet K Date: Fri, 13 Sep 2019 12:02:42 -0700 Subject: [PATCH 3/4] Remove noqa comments + modify tests for Travis CI to detect --- data_structures/trie/trie.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py index 077af4f44107..916dc103f71a 100644 --- a/data_structures/trie/trie.py +++ b/data_structures/trie/trie.py @@ -12,7 +12,7 @@ def __init__(self): self.nodes = dict() # Mapping from char to TrieNode self.is_leaf = False - def insert_many(self, words: [str]): # noqa: E999 This syntax is Python 3 only + def insert_many(self, words: [str]): """ Inserts a list of words into the Trie :param words: list of string words @@ -21,7 +21,7 @@ def insert_many(self, words: [str]): # noqa: E999 This syntax is Python 3 only for word in words: self.insert(word) - def insert(self, word: str): # noqa: E999 This syntax is Python 3 only + def insert(self, word: str): """ Inserts a word into the Trie :param word: word to be inserted @@ -34,7 +34,7 @@ def insert(self, word: str): # noqa: E999 This syntax is Python 3 only curr = curr.nodes[char] curr.is_leaf = True - def find(self, word: str) -> bool: # noqa: E999 This syntax is Python 3 only + def find(self, word: str) -> bool: """ Tries to find word in a Trie :param word: word to look for @@ -76,7 +76,7 @@ def _delete(curr: TrieNode, word: str, index: int): _delete(self, word, 0) -def print_words(node: TrieNode, word: str): # noqa: E999 This syntax is Python 3 only +def print_words(node: TrieNode, word: str): """ Prints all the words in a Trie :param node: root node of Trie @@ -90,11 +90,12 @@ def print_words(node: TrieNode, word: str): # noqa: E999 This syntax is Python print_words(value, word + key) -def test(): +def test_trie(): words = ["banana", "bananas", "bandana", "band", "apple", "all", "beast"] root = TrieNode() root.insert_many(words) - # print_words(root, '') + # print_words(root, "") + assert all(root.find(word) for word in words) assert root.find("banana") assert not root.find("bandanas") assert not root.find("apps") @@ -105,6 +106,23 @@ def test(): root.delete("banana") assert not root.find("banana") assert root.find("bananas") + return True -test() +def print_results(msg: str, passes: bool) -> None: + print(str(msg), "works!" if passes else "doesn't work :(") + + +def pytests(): + assert test_trie() + + +def main(): + """ + >>> pytests() + """ + print_results("Testing trie functionality", test_trie()) + + +if __name__ == "__main__": + main() From 286be6c3d1ef4c08f939f9c356162acf7a290c6b Mon Sep 17 00:00:00 2001 From: John Law Date: Sat, 14 Sep 2019 04:17:38 +0800 Subject: [PATCH 4/4] Minor improvement --- data_structures/trie/trie.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py index 916dc103f71a..5a560b97c293 100644 --- a/data_structures/trie/trie.py +++ b/data_structures/trie/trie.py @@ -1,9 +1,8 @@ """ A Trie/Prefix Tree is a kind of search tree used to provide quick lookup of words/patterns in a set of words. A basic Trie however has O(n^2) space complexity -making it impractical in practice. It however provides O(max(search_string, length of longest word)) lookup -time making it an optimal approach when space is not an issue. - +making it impractical in practice. It however provides O(max(search_string, length of longest word)) +lookup time making it an optimal approach when space is not an issue. """ @@ -91,7 +90,7 @@ def print_words(node: TrieNode, word: str): def test_trie(): - words = ["banana", "bananas", "bandana", "band", "apple", "all", "beast"] + words = "banana bananas bandana band apple all beast".split() root = TrieNode() root.insert_many(words) # print_words(root, "")