Tutorial 6 - 13 April 2025
This commit is contained in:
parent
add0b19505
commit
8e5d4ea752
85
T6/Answer/Q1 - count_words.py
Normal file
85
T6/Answer/Q1 - count_words.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
class TrieNode:
|
||||||
|
def __init__(self, char=None):
|
||||||
|
self.char = char
|
||||||
|
self.first_child = None
|
||||||
|
self.next_sibling = None
|
||||||
|
self.is_end_of_word = False
|
||||||
|
|
||||||
|
class Queue:
|
||||||
|
def __init__(self):
|
||||||
|
self.items = []
|
||||||
|
|
||||||
|
def enqueue(self, item):
|
||||||
|
self.items.append(item) # Add to the end
|
||||||
|
|
||||||
|
def dequeue(self):
|
||||||
|
if not self.is_empty():
|
||||||
|
return self.items.pop(0) # Remove from the front
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return len(self.items) == 0
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return len(self.items)
|
||||||
|
|
||||||
|
def _find_child(node, char):
|
||||||
|
current = node.first_child
|
||||||
|
while current:
|
||||||
|
if current.char == char:
|
||||||
|
return current
|
||||||
|
current = current.next_sibling
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _add_child(node, char):
|
||||||
|
new_node = TrieNode(char)
|
||||||
|
new_node.next_sibling = node.first_child
|
||||||
|
node.first_child = new_node
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
class Trie:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = TrieNode()
|
||||||
|
|
||||||
|
def insert(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
child = _find_child(node, char)
|
||||||
|
if not child:
|
||||||
|
child = _add_child(node, char)
|
||||||
|
node = child
|
||||||
|
node.is_end_of_word = True
|
||||||
|
|
||||||
|
def search(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return False
|
||||||
|
return node.is_end_of_word
|
||||||
|
|
||||||
|
def count_words(self, node): #question 1
|
||||||
|
if node.is_end_of_word:
|
||||||
|
cnt = 1
|
||||||
|
else:
|
||||||
|
cnt = 0
|
||||||
|
|
||||||
|
child = node.first_child
|
||||||
|
while child:
|
||||||
|
cnt += self.count_words(child)
|
||||||
|
child = child.next_sibling
|
||||||
|
return cnt
|
||||||
|
|
||||||
|
trie = Trie()
|
||||||
|
trie.insert("cat")
|
||||||
|
trie.insert("car")
|
||||||
|
trie.insert("care")
|
||||||
|
trie.insert("cane")
|
||||||
|
trie.insert("camera")
|
||||||
|
trie.insert("campus")
|
||||||
|
trie.insert("camp")
|
||||||
|
trie.insert("dog")
|
||||||
|
trie.insert("dot")
|
||||||
|
|
||||||
|
print("Total words in Trie:", trie.count_words(trie.root))
|
98
T6/Answer/Q2 - find_words_with_prefix.py
Normal file
98
T6/Answer/Q2 - find_words_with_prefix.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
class TrieNode:
|
||||||
|
def __init__(self, char=None):
|
||||||
|
self.char = char
|
||||||
|
self.first_child = None
|
||||||
|
self.next_sibling = None
|
||||||
|
self.is_end_of_word = False
|
||||||
|
|
||||||
|
class Queue:
|
||||||
|
def __init__(self):
|
||||||
|
self.items = []
|
||||||
|
|
||||||
|
def enqueue(self, item):
|
||||||
|
self.items.append(item) # Add to the end
|
||||||
|
|
||||||
|
def dequeue(self):
|
||||||
|
if not self.is_empty():
|
||||||
|
return self.items.pop(0) # Remove from the front
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return len(self.items) == 0
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return len(self.items)
|
||||||
|
|
||||||
|
def _find_child(node, char):
|
||||||
|
current = node.first_child
|
||||||
|
while current:
|
||||||
|
if current.char == char:
|
||||||
|
return current
|
||||||
|
current = current.next_sibling
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _add_child(node, char):
|
||||||
|
new_node = TrieNode(char)
|
||||||
|
new_node.next_sibling = node.first_child
|
||||||
|
node.first_child = new_node
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
class Trie:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = TrieNode()
|
||||||
|
|
||||||
|
def insert(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
child = _find_child(node, char)
|
||||||
|
if not child:
|
||||||
|
child = _add_child(node, char)
|
||||||
|
node = child
|
||||||
|
node.is_end_of_word = True
|
||||||
|
|
||||||
|
def search(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return False
|
||||||
|
return node.is_end_of_word
|
||||||
|
|
||||||
|
def collect_all_words(self, node, prefix, results):
|
||||||
|
if node.is_end_of_word:
|
||||||
|
results.append(prefix)
|
||||||
|
|
||||||
|
child = node.first_child
|
||||||
|
while child:
|
||||||
|
self.collect_all_words(child, prefix + child.char, results)
|
||||||
|
child = child.next_sibling
|
||||||
|
|
||||||
|
def find_words_with_prefix(self, prefix): #question 2
|
||||||
|
results = []
|
||||||
|
node = self.root
|
||||||
|
|
||||||
|
for char in prefix:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return []
|
||||||
|
|
||||||
|
self.collect_all_words(node, prefix, results)
|
||||||
|
return results
|
||||||
|
|
||||||
|
trie = Trie()
|
||||||
|
trie.insert("cat")
|
||||||
|
trie.insert("car")
|
||||||
|
trie.insert("care")
|
||||||
|
trie.insert("cane")
|
||||||
|
trie.insert("camera")
|
||||||
|
trie.insert("campus")
|
||||||
|
trie.insert("camp")
|
||||||
|
trie.insert("dog")
|
||||||
|
trie.insert("dot")
|
||||||
|
|
||||||
|
prefix1 = "ca"
|
||||||
|
prefix2 = "do"
|
||||||
|
prefix3 = "z"
|
||||||
|
print(f"Words starting with '{prefix1}': ", trie.find_words_with_prefix(prefix1))
|
||||||
|
print(f"Words starting with '{prefix2}':", trie.find_words_with_prefix(prefix2))
|
||||||
|
print(f"Words starting with '{prefix3}':", trie.find_words_with_prefix(prefix3))
|
112
T6/Answer/Q3 - find_shortest_word_with_prefix.py
Normal file
112
T6/Answer/Q3 - find_shortest_word_with_prefix.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
class TrieNode:
|
||||||
|
def __init__(self, char=None):
|
||||||
|
self.char = char
|
||||||
|
self.first_child = None
|
||||||
|
self.next_sibling = None
|
||||||
|
self.is_end_of_word = False
|
||||||
|
|
||||||
|
class Queue:
|
||||||
|
def __init__(self):
|
||||||
|
self.items = []
|
||||||
|
|
||||||
|
def enqueue(self, item):
|
||||||
|
self.items.append(item) # Add to the end
|
||||||
|
|
||||||
|
def dequeue(self):
|
||||||
|
if not self.is_empty():
|
||||||
|
return self.items.pop(0) # Remove from the front
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return len(self.items) == 0
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return len(self.items)
|
||||||
|
|
||||||
|
def _find_child(node, char):
|
||||||
|
current = node.first_child
|
||||||
|
while current:
|
||||||
|
if current.char == char:
|
||||||
|
return current
|
||||||
|
current = current.next_sibling
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _add_child(node, char):
|
||||||
|
new_node = TrieNode(char)
|
||||||
|
new_node.next_sibling = node.first_child
|
||||||
|
node.first_child = new_node
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
class Trie:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = TrieNode()
|
||||||
|
|
||||||
|
def insert(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
child = _find_child(node, char)
|
||||||
|
if not child:
|
||||||
|
child = _add_child(node, char)
|
||||||
|
node = child
|
||||||
|
node.is_end_of_word = True
|
||||||
|
|
||||||
|
def search(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return False
|
||||||
|
return node.is_end_of_word
|
||||||
|
|
||||||
|
def find_shortest_word_with_prefix(self, prefix):#question 3
|
||||||
|
# Step 1: Traverse to the end of the prefix
|
||||||
|
node = self.root
|
||||||
|
for char in prefix:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return None # Prefix not found
|
||||||
|
|
||||||
|
# Step 2: BFS
|
||||||
|
queue = Queue()
|
||||||
|
queue.enqueue((node, prefix, 0)) # (node, word, depth)
|
||||||
|
shortest_words = []
|
||||||
|
min_depth = None
|
||||||
|
|
||||||
|
while not queue.is_empty():
|
||||||
|
node, word, depth = queue.dequeue()
|
||||||
|
|
||||||
|
if node.is_end_of_word:
|
||||||
|
if min_depth is None:
|
||||||
|
min_depth = depth
|
||||||
|
if depth == min_depth:
|
||||||
|
shortest_words.append(word)
|
||||||
|
elif depth > min_depth:
|
||||||
|
break # We already found the shortest level, skip deeper
|
||||||
|
|
||||||
|
if min_depth is not None and depth >= min_depth:
|
||||||
|
continue # don't enqueue deeper nodes
|
||||||
|
|
||||||
|
child = node.first_child
|
||||||
|
while child:
|
||||||
|
queue.enqueue((child, word + child.char, depth + 1))
|
||||||
|
child = child.next_sibling
|
||||||
|
|
||||||
|
return shortest_words
|
||||||
|
|
||||||
|
trie = Trie()
|
||||||
|
trie.insert("cat")
|
||||||
|
trie.insert("car")
|
||||||
|
trie.insert("care")
|
||||||
|
trie.insert("cane")
|
||||||
|
trie.insert("camera")
|
||||||
|
trie.insert("campus")
|
||||||
|
trie.insert("camp")
|
||||||
|
trie.insert("dog")
|
||||||
|
trie.insert("dot")
|
||||||
|
|
||||||
|
prefix1 = "ca"
|
||||||
|
prefix2 = "do"
|
||||||
|
prefix3 = "z"
|
||||||
|
print(f"Shortest word starting with '{prefix1}':", trie.find_shortest_word_with_prefix(prefix1))
|
||||||
|
print(f"Shortest word starting with '{prefix2}':", trie.find_shortest_word_with_prefix(prefix2))
|
||||||
|
print(f"Shortest word starting with '{prefix3}':", trie.find_shortest_word_with_prefix(prefix3))
|
75
T6/Base/Q1 - count_words.py
Normal file
75
T6/Base/Q1 - count_words.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
class TrieNode:
|
||||||
|
def __init__(self, char=None):
|
||||||
|
self.char = char
|
||||||
|
self.first_child = None
|
||||||
|
self.next_sibling = None
|
||||||
|
self.is_end_of_word = False
|
||||||
|
|
||||||
|
class Queue:
|
||||||
|
def __init__(self):
|
||||||
|
self.items = []
|
||||||
|
|
||||||
|
def enqueue(self, item):
|
||||||
|
self.items.append(item) # Add to the end
|
||||||
|
|
||||||
|
def dequeue(self):
|
||||||
|
if not self.is_empty():
|
||||||
|
return self.items.pop(0) # Remove from the front
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return len(self.items) == 0
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return len(self.items)
|
||||||
|
|
||||||
|
def _find_child(node, char):
|
||||||
|
current = node.first_child
|
||||||
|
while current:
|
||||||
|
if current.char == char:
|
||||||
|
return current
|
||||||
|
current = current.next_sibling
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _add_child(node, char):
|
||||||
|
new_node = TrieNode(char)
|
||||||
|
new_node.next_sibling = node.first_child
|
||||||
|
node.first_child = new_node
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
class Trie:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = TrieNode()
|
||||||
|
|
||||||
|
def insert(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
child = _find_child(node, char)
|
||||||
|
if not child:
|
||||||
|
child = _add_child(node, char)
|
||||||
|
node = child
|
||||||
|
node.is_end_of_word = True
|
||||||
|
|
||||||
|
def search(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return False
|
||||||
|
return node.is_end_of_word
|
||||||
|
|
||||||
|
def count_words(self, node): #question 1
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
trie = Trie()
|
||||||
|
trie.insert("cat")
|
||||||
|
trie.insert("car")
|
||||||
|
trie.insert("care")
|
||||||
|
trie.insert("cane")
|
||||||
|
trie.insert("camera")
|
||||||
|
trie.insert("campus")
|
||||||
|
trie.insert("camp")
|
||||||
|
trie.insert("dog")
|
||||||
|
trie.insert("dot")
|
||||||
|
|
||||||
|
print("Total words in Trie:", trie.count_words(trie.root))
|
83
T6/Base/Q2 - find_words_with_prefix.py
Normal file
83
T6/Base/Q2 - find_words_with_prefix.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
class TrieNode:
|
||||||
|
def __init__(self, char=None):
|
||||||
|
self.char = char
|
||||||
|
self.first_child = None
|
||||||
|
self.next_sibling = None
|
||||||
|
self.is_end_of_word = False
|
||||||
|
|
||||||
|
class Queue:
|
||||||
|
def __init__(self):
|
||||||
|
self.items = []
|
||||||
|
|
||||||
|
def enqueue(self, item):
|
||||||
|
self.items.append(item) # Add to the end
|
||||||
|
|
||||||
|
def dequeue(self):
|
||||||
|
if not self.is_empty():
|
||||||
|
return self.items.pop(0) # Remove from the front
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return len(self.items) == 0
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return len(self.items)
|
||||||
|
|
||||||
|
def _find_child(node, char):
|
||||||
|
current = node.first_child
|
||||||
|
while current:
|
||||||
|
if current.char == char:
|
||||||
|
return current
|
||||||
|
current = current.next_sibling
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _add_child(node, char):
|
||||||
|
new_node = TrieNode(char)
|
||||||
|
new_node.next_sibling = node.first_child
|
||||||
|
node.first_child = new_node
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
class Trie:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = TrieNode()
|
||||||
|
|
||||||
|
def insert(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
child = _find_child(node, char)
|
||||||
|
if not child:
|
||||||
|
child = _add_child(node, char)
|
||||||
|
node = child
|
||||||
|
node.is_end_of_word = True
|
||||||
|
|
||||||
|
def search(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return False
|
||||||
|
return node.is_end_of_word
|
||||||
|
|
||||||
|
def collect_all_words(self, node, prefix, results):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def find_words_with_prefix(self, prefix): #question 2
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
trie = Trie()
|
||||||
|
trie.insert("cat")
|
||||||
|
trie.insert("car")
|
||||||
|
trie.insert("care")
|
||||||
|
trie.insert("cane")
|
||||||
|
trie.insert("camera")
|
||||||
|
trie.insert("campus")
|
||||||
|
trie.insert("camp")
|
||||||
|
trie.insert("dog")
|
||||||
|
trie.insert("dot")
|
||||||
|
|
||||||
|
prefix1 = "ca"
|
||||||
|
prefix2 = "do"
|
||||||
|
prefix3 = "z"
|
||||||
|
print(f"Words starting with '{prefix1}': ", trie.find_words_with_prefix(prefix1))
|
||||||
|
print(f"Words starting with '{prefix2}':", trie.find_words_with_prefix(prefix2))
|
||||||
|
print(f"Words starting with '{prefix3}':", trie.find_words_with_prefix(prefix3))
|
80
T6/Base/Q3 - find_shortest_word_with_prefix.py
Normal file
80
T6/Base/Q3 - find_shortest_word_with_prefix.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
class TrieNode:
|
||||||
|
def __init__(self, char=None):
|
||||||
|
self.char = char
|
||||||
|
self.first_child = None
|
||||||
|
self.next_sibling = None
|
||||||
|
self.is_end_of_word = False
|
||||||
|
|
||||||
|
class Queue:
|
||||||
|
def __init__(self):
|
||||||
|
self.items = []
|
||||||
|
|
||||||
|
def enqueue(self, item):
|
||||||
|
self.items.append(item) # Add to the end
|
||||||
|
|
||||||
|
def dequeue(self):
|
||||||
|
if not self.is_empty():
|
||||||
|
return self.items.pop(0) # Remove from the front
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return len(self.items) == 0
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return len(self.items)
|
||||||
|
|
||||||
|
def _find_child(node, char):
|
||||||
|
current = node.first_child
|
||||||
|
while current:
|
||||||
|
if current.char == char:
|
||||||
|
return current
|
||||||
|
current = current.next_sibling
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _add_child(node, char):
|
||||||
|
new_node = TrieNode(char)
|
||||||
|
new_node.next_sibling = node.first_child
|
||||||
|
node.first_child = new_node
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
class Trie:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = TrieNode()
|
||||||
|
|
||||||
|
def insert(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
child = _find_child(node, char)
|
||||||
|
if not child:
|
||||||
|
child = _add_child(node, char)
|
||||||
|
node = child
|
||||||
|
node.is_end_of_word = True
|
||||||
|
|
||||||
|
def search(self, word):
|
||||||
|
node = self.root
|
||||||
|
for char in word:
|
||||||
|
node = _find_child(node, char)
|
||||||
|
if not node:
|
||||||
|
return False
|
||||||
|
return node.is_end_of_word
|
||||||
|
|
||||||
|
def find_shortest_word_with_prefix(self, prefix):#question 3
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
trie = Trie()
|
||||||
|
trie.insert("cat")
|
||||||
|
trie.insert("car")
|
||||||
|
trie.insert("care")
|
||||||
|
trie.insert("cane")
|
||||||
|
trie.insert("camera")
|
||||||
|
trie.insert("campus")
|
||||||
|
trie.insert("camp")
|
||||||
|
trie.insert("dog")
|
||||||
|
trie.insert("dot")
|
||||||
|
|
||||||
|
prefix1 = "ca"
|
||||||
|
prefix2 = "do"
|
||||||
|
prefix3 = "z"
|
||||||
|
print(f"Shortest word starting with '{prefix1}':", trie.find_shortest_word_with_prefix(prefix1))
|
||||||
|
print(f"Shortest word starting with '{prefix2}':", trie.find_shortest_word_with_prefix(prefix2))
|
||||||
|
print(f"Shortest word starting with '{prefix3}':", trie.find_shortest_word_with_prefix(prefix3))
|
Loading…
x
Reference in New Issue
Block a user