I am coding a huffman coding tree in python, I have used one class for tree nodes, but I want the whole program to be object oriented. I just cant seem to be able to turn my functions into classes and run the whole thing as OOP. Is it possible to convert functions into classes/methods or does it involve rewriting the entire code in OOP style. The code works ok, im just trying to get my head around OOP and how to implement it. Any help would be great! Code below.
'''
import heapq
class TreeNode(object):
def __init__(self, freq, char=None, left=None, right=None):
self.char = char
self.freq = freq
self.left = left
self.right = right
def __lt__(self, other):
return self.freq < other.freq
def isLeaf(self):
return (self.left == None and self.right == None)
def createTree(freqData):
huffmanNodes = []
for char in freqData:
huffmanNodes.append(TreeNode(freqData[char], char))
heapq.heapify(huffmanNodes)
while (len(huffmanNodes) > 1):
# obtain the two minimum-frequency Huffman nodes
child1 = heapq.heappop(huffmanNodes)
child2 = heapq.heappop(huffmanNodes)
parent = TreeNode(child1.freq + child2.freq, left=child1, right=child2)
heapq.heappush(huffmanNodes, parent)
return None if huffmanNodes == [] else heapq.heappop(huffmanNodes)
def hTreeToHCode(hTree):
code = dict()
def getCode(hNode, curCode=""):
if (hNode == None): return
if (hNode.left == None and hNode.right == None):
code[hNode.char] = curCode
getCode(hNode.left, curCode + "0")
getCode(hNode.right, curCode + "1")
if hNode.char == None:
print("")
else:
print('Character = {} : Freq = {} --- Encoded into {}'.format(hNode.char, hNode.freq, curCode))
getCode(hTree)
return code
def encode(s, freqData):
hTree = createTree(freqData)
hCode = hTreeToHCode(hTree)
hEncoded = ""
for char in s:
hEncoded += hCode[char]
return hEncoded.strip()
def decode(s, freqData):
hTree = createTree(freqData)
decodedStr = ""
curTreeNode = hTree
for charCode in s:
if (charCode == "0"):
curTreeNode = curTreeNode.left
else:
curTreeNode = curTreeNode.right
if (curTreeNode.isLeaf()):
decodedStr += curTreeNode.char
curTreeNode = hTree
return decodedStr
words = "hello welcome to my huffman algorithm code"
charlst = {}
for char in words:
charlst[char] = charlst.get(char,0) + 1
freqData = charlst
encodedStr = encode(words, freqData)
print("encodedStr", encodedStr)
decodedStr = decode(encodedStr, freqData)
print("decodedStr", decodedStr)
'''
you can put function outside the NodeTree class in a Main class and add a run method with var initialisation etc and put at the end of your program a
if __name__=='__main__':
Main.run()
Related
i am implementing the trie data structure, why my pointer is not incrementing at line# 27. all the characters are getting into forst node only.
this is my code
class Trienode:
data:str
next:list = [None]*26
isTerminal:bool = False
def __init__(self,data):
self.data = data
class Trie:
def __init__(self):
self.root = Trienode('#')
def insert(self,data):
temp = self.root
for ch in data:
index = ord(ch)- ord('a')
# print(temp.next[index])
if temp.next[index]==None:
temp.next[index] = Trienode(ch)
temp = temp.next[index]
else:
temp = temp.next[index]
temp.isTerminal = True
def display(self):
temp = self.root
for i in range(26):
print(temp.next[i])
if __name__=='__main__':
root = Trie()
root.insert("apple")
root.insert("pineapple")
root.display()
This is the output on console i am printing the pointer array of first node
console output
i tried the same logic to increment pointer in Linkedlist it is working fine.
I've modified your sample a little bit.
Relevant changes are highlighted with a comment
class Trienode:
def __init__(self, data):
self.data: str = data
self.next: list = [None] * 26
self.isTerminal: bool = False
def __str__(self): # get more info on display
return f"{self.data} - {''.join(str(n) for n in self.next if n is not None)}"
def __repr__(self): # appears nicely in my IDE ;)
return f'Trienode({self.data})'
class Trie:
def __init__(self):
self.root = Trienode('#')
def insert(self, data):
temp = self.root
for ch in data:
index = ord(ch) - ord('a')
if temp.next[index] is None: # error was there I guess
temp.next[index] = Trienode(ch)
temp = temp.next[index] # and here also
temp.isTerminal = True
def display(self):
self._display(self.root)
def _display(self, node): # must use a recursion to display all the children
print(node)
for child in node.next:
if child is not None:
self._display(child)
if __name__ == '__main__':
root = Trie()
root.insert("apple")
root.insert("pineapple")
root.display
Hope this helps
I have a Binary Search Tree and I am trying to trace recursively in order through the tree and append each key,value to a list. It is only appending the first key,value to the list and not going through the list in order. I pasted my code below, along with the test code I used at the bottom. Any help on how to get past this issue is super appreciated!
class TreeMap:
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.left = None
self.right = None
def __init__(self):
self.root = None
self.numsearches = 0
self.numcomparisons = 0
def add(self, newkey, newvalue):
newkey = newkey.lower()
if self.root == None:
self.root = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(self.root, newkey, newvalue)
def add_helper(thisnode, newkey, newvalue):
if newkey <= thisnode.key:
if thisnode.left == None:
thisnode.left = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(thisnode.left, newkey, newvalue)
else:
if thisnode.right == None:
thisnode.right = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(thisnode.right, newkey, newvalue)
def print(self):
TreeMap.print_helper(self.root, 0)
def print_helper(somenode, indentlevel):
if somenode == None:
print(" "*(indentlevel),"---")
return
if not TreeMap.isleaf(somenode):
TreeMap.print_helper(somenode.right, indentlevel + 5)
print(" "*indentlevel + str(somenode.key) + ": " +str(somenode.value))
if not TreeMap.isleaf(somenode):
TreeMap.print_helper(somenode.left, indentlevel + 5)
def isleaf(anode):
return anode.left == None and anode.right == None
def listify(self, whichorder="in"):
'''
Returns a list consisting of all the payloads of the tree. (This returns a plain old Python List.)
The order of the payloads is determined by whichorder, which defaults to inorder.
The other possibilities are "pre" and "post".
If the tree is empty, return the empty list.
'''
assert type(whichorder) is str,"Whichorder is a string, and can only be pre, in or post"
assert whichorder in ["pre","in","post"],"Whichorder is a string, and can only be pre, in or post"
return TreeMap.listify_helper(self.root, whichorder)
def listify_helper(somenode, whichorder):
order_list = []
if somenode == None:
return order_list
elif somenode != None and whichorder == 'in':
TreeMap.listify_helper(somenode.left, 'in')
order_list.append(somenode.key+ '='+somenode.value)
TreeMap.listify_helper(somenode.right, 'in')
return order_list
TEST CODE:
import treemap
translator = treemap.TreeMap()
translator.add("cat", "Katze")
translator.add("bird", "Vogel")
translator.add("dog", "Hund")
translator.add("snake", "IDK")
translator.add("bear", "IDK")
translator.add("octopus", "Tintenfisch")
translator.add("horse", "Pferd")
translator.add("zebra", "IDK")
translator.print()
print("---------------------------------------------------")
print (translator.listify())
The problem is here:
def listify_helper(somenode, whichorder):
order_list = []
This function initialises its own local order_list every time it is invoked. Pass order_list as a parameter instead so that the same list is appended to by each recursive invocation.
Alternatively, append each element of the result of the recursive calls of listify_helper to order_list, although this approach could result in unneeded copying.
I Implemented a Trie data structure using python, now the problem is it doesn't display the keys that Trie is stored in its data structure.
class Node:
def __init__(self):
self.children = [None] * 26
self.endOfTheWord = False
class Trie:
def __init__(self):
self.root = self.getNode()
def getNode(self):
return Node()
def charToIndex(self ,ch):
return ord(ch) - ord('a')
def insert(self ,word):
current = self.root
for i in range(len(word)):
index = self.charToIndex(word[i])
if current.children[index] is None:
current.children[index] = self.getNode()
current = current.children[index]
current.endOfTheWord = True
def printKeys(self):
str = []
self.printKeysUtil(self.root ,str)
def printKeysUtil(self ,root ,str):
if root.endOfTheWord == True:
print(''.join(str))
return
for i in range(26):
if root.children[i] is not None:
ch = chr(97) + chr(i)
str.append(ch)
self.printKeysUtil(root.children[i] ,str)
str.pop()
You could perform a pre-order traversal of the nodes, and wherever you find an end-of-word marker, you zoom up to the root, capturing the letters as you go, in order to get the full word... except that to accomplish this, you would need to store the parent node in each node.
def printKeysUtil(self ,root ,str):
if root.endOfTheWord == True:
print(''.join(str))
return
for i in range(26):
if root.children[i] is not None:
ch = chr(97+i)
str.append(ch)
self.printKeysUtil(root.children[i] ,str)
str.pop()
I'm practicing creating a balanced binary search tree in python.
I already have these below, any idea on how to create a balance_bst funtion that passed a list of unique values that are
sorted in increasing order. It returns a reference to the root of a well-balanced binary search tree:
class LN:
def __init__(self,value,next=None):
self.value = value
self.next = next
def list_to_ll(l):
if l == []:
return None
front = rear = LN(l[0])
for v in l[1:]:
rear.next = LN(v)
rear = rear.next
return front
def str_ll(ll):
answer = ''
while ll != None:
answer += str(ll.value)+'->'
ll = ll.next
return answer + 'None'
# Tree Node class and helper functions (to set up problem)
class TN:
def __init__(self,value,left=None,right=None):
self.value = value
self.left = left
self.right = right
def height(atree):
if atree == None:
return -1
else:
return 1+ max(height(atree.left),height(atree.right))
def size(t):
if t == None:
return 0
else:
return 1 + size(t.left) + size(t.right)
def is_balanced(t):
if t == None:
return True
else:
return abs(size(t.left)-size(t.right)) <= 1 and is_balanced(t.left) and is_balanced(t.right)
def str_tree(atree,indent_char ='.',indent_delta=2):
def str_tree_1(indent,atree):
if atree == None:
return ''
else:
answer = ''
answer += str_tree_1(indent+indent_delta,atree.right)
answer += indent*indent_char+str(atree.value)+'\n'
answer += str_tree_1(indent+indent_delta,atree.left)
return answer
return str_tree_1(0,atree)
How do write the balance_bst?
def balance_bst(l):
Here is what I did:
def build_balanced_bst(l):
if l == None:
return None
else:
middle = len(l) // 2
return TN(l[middle],
build_balanced_bst(l[:middle]),
build_balanced_bst(l[middle + 1:]))
It gives me:
IndexError: list index out of range
How do I fix it?
I'm not going to write it for you since that's not what SO is about, but here's the general idea. Since the list is already sorted, the root should be the element in the middle of the list. Its left child will be the root of the balanced tree consisting of the elements to the left of the root in the list, and the right sub-tree will be the rest.
So this character ▯ appears when I run my code which I think means there is a missing character therefor it can't be displayed. (Not sure correct me if I am wrong) And well basically I want to be able to get rid of that character. Here is what it looks like when I run my code:
However in the back-end in the idle when I click on one of the boxes for it to be displayed up top it doesn't register and looks like this in idle:
Why does it appear on screen if it isn't going to appear in idle?
Also how can I get rid of the ▯ character from the main screen?
Here is my full code.
Here are segments in which I think the problem lies. (However I have not been able to solve the problem)
My classes for Tree comparison to find the sentences and their frequent use:
class Branch():
def __init__(self, value):
self.left = None
self.right = None
self.value = value
self.frequency = 1
def incFreq(self):
self.frequency = self.frequency + 1
def freq(self):
return self.frequency
class Tree():
highest = []
def __init__(self):
self.root = None
self.found = False
def findHighest(self):
from operator import itemgetter, attrgetter
self.highest = []
self.inorder(self.root)
self.highest = sorted(self.highest, key=itemgetter(1), reverse=True)
return self.highest
#lessThan function needed to compare strings
def lessThan(self, a, b):
if len(a) < len(b):
loopCount = len(a)
else:
loopCount = len(b)
for pos in range(0, loopCount):
if a[pos] > b[pos]:
return False
return True
def outputTree(self):
self.inorder(self.root)
def insert(self, value):
#increment freq if already exists, else insert
if not self.exists(value):
self.root = self.insertAtBranch(self.root, value)
def exists(self, value):
#set the class variable found to False to assume it is not there
self.found = False
self.findAtBranch(self.root, value)
return self.found
#Used to fine a value in a tree
def findAtBranch(self, branch, value):
if branch == None:
pass
else:
#print ("[" + branch.value + "][" + value + "]") # Error checking
if branch.value == value:
self.found = True
#print("found " + value)
branch.incFreq()
#print(branch.freq())
else:
self.findAtBranch(branch.left, value)
self.findAtBranch(branch.right, value)
def insertAtBranch(self, branch, value):
if branch == None:
return Branch(value)
else:
if self.lessThan(branch.value, value):
branch.right = self.insertAtBranch(branch.right, value)
else:
branch.left = self.insertAtBranch(branch.left, value)
return branch
def inorder(self, branch):
if branch == None: return
self.highest.append((branch.value, branch.freq()))
#print (branch.value)
#print (branch.freq())
#print(self.highest[0])
self.inorder(branch.left)
self.inorder(branch.right)
This is where I use the tree and pass sentences to be used on a different function:
def getPhrases(self, numToReturn):
topPhrases = []
phrasesTree = Tree()
#load tree with phrases from phrase text file
file = open('setPhrases.txt', 'r')
for line in file:
phrasesTree.insert(line)
#create a list of the top n of phrases to return
val = 0
for phrase in phrasesTree.findHighest():
if val < numToReturn:
topPhrases.append(phrase)
val = val + 1
return topPhrases
This is where I use the sentences to be able to display them on the screen:
def createPhrases(self):
print("createPhrases")
self.deletePanes()
self.show_keyboard = False
self.show_words = False
self.show_phrases = True
self.show_terminal = True
words = self.getPhrases(10)
for word, count in words:
self.addPane("{}".format(word, count), WORDS)
self.addPane("Boxes", PHRASE)
self.addPane("Keyboard", PHRASE)
self.addPane("OK", PHRASE)
self.drawPanes()
When you read lines from file, newline characters are at the end. pygame's documentation states that:
The text can only be a single line: newline characters are not rendered.
So, you should change this fragment:
file = open('setPhrases.txt', 'r')
for line in file:
phrasesTree.insert(line)
to this:
file = open('setPhrases.txt', 'r')
for line in file:
phrasesTree.insert(line.strip())