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