I am trying to code a program that encodes/decodes Morse Code using a binary tree. Initially my code worked by taking an input when run and successfully converted it to Morse code.
However, I am trying to make it so that the terminal command encode('xyz') will take the xyz string and convert to the Morse, returning the result. To do this, I have had to rejig the code, and am now running into errors. Is there something obvious I am missing?
class BTree:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
def insert(self, data):
if self.data:
if data < self.data:
if self.left:
self.left.insert(data)
else:
self.left = BTree(data)
elif data > self.data:
if self.right:
self.right.insert(data)
else:
self.right = BTree(data)
else:
self.data = data
def output(self):
if self.left:
self.left.output()
print(self.data)
if self.right:
self.right.output()
def encode(self, msg: str):
dotsdashes = []
code = "".join(dotsdashes)
for character in msg:
self.getMorse(code, character, dotsdashes)
morseCode = morseCode + code + " "
def getMorse(self, node, character, code):
if node==None:
return False
elif node.data == character:
return True
else:
if self.getMorse(node.left,character,code) == True:
code.insert(0,".")
return True
elif self.getMorse (node.right,character,code)==True:
code.insert(0,"-")
return True
My main function (won't format properly when copied and pasted as one):
if __name__ == '__main__':
root = BTree("Root")
root.left = BTree("E")
root.right = BTree("T")
root.left.left = BTree("I")
root.left.right = BTree("A")
root.right.left = BTree("N")
root.right.right = BTree("M")
root.left.left.left = BTree("S")
root.left.left.right = BTree("U")
root.left.right.left = BTree("R")
root.left.right.right = BTree("W")
root.right.left.left = BTree("D")
root.right.left.right = BTree("K")
root.right.right.left = BTree("G")
root.right.right.right = BTree("O")
root.left.left.left.left = BTree("H")
root.left.left.left.right = BTree("V")
root.left.left.right.left = BTree("F")
root.left.left.right.right = BTree("")
root.left.right.left.left = BTree("L")
root.left.right.left.right = BTree("")
root.left.right.right.left = BTree("P")
root.left.right.right.right = BTree("J")
root.right.left.left.left = BTree("B")
root.right.left.left.right = BTree("X")
root.right.left.right.left = BTree("C")
root.right.left.right.right = BTree("Y")
root.right.right.left.left = BTree("Z")
root.right.right.left.right = BTree("Q")
root.right.right.right.left = BTree("")
root.right.right.right.right = BTree("")
Also wondering if populating the binary tree in the main function rather than it's own function was the right thing to do?
I'm relatively new to using binary trees so apologies for the potentially poor explanation/silly question.
EDIT: I should have included that the most recent error I am getting is: line 41, in getMorse elif node.data == character: AttributeError: 'str' object has no attribute 'data'
There are these issues:
In
morseCode = morseCode + code + " "
you referencemorseCode
on the right side of the assignment, but it was never initialised with a value. So you need to initialise it before the loop with the empty stringIn the call
self.getMorse(code, character, dotsdashes)
you pass a stringcode
as first argument, but the function expects a node there. So you should passself
as argument instead ofcode
self.getMorse
returns a boolean, but in the above call you never look at this boolean. You should probably do something when that returned value is false.code = "".join(dotsdashes)
is happening too soon (and only once). This should happen in the loop after you made the call toself.getMorse
as only thendotsdashes
will have been populated.dotsdashes = []
should happen each time before you callself.getMorse
, as otherwise it will just accumulate the new morse code adjacent to what it already had from a previous iteration.encode
should return the result.Here is a correction of that
encode
function:Remarks:
self.getMorse
, which it populates. Better is to make that the return value, and to returnNone
if there is no Morse code available.insert
method implements a binary search tree, which is not what you need here. It should not be included in your class.Alternative tree
The tree you have created is a complete binary tree (even a perfect one), so you can encode that tree in a list (as is often done for binary heaps). And since the data for each node is just a character, it could be a string instead of a list.
The binary representation of an index in that string could then be made to be the Morse code (where 0,1 maps to dot,dash respectively) of the character at that index. To make sure that all binary 0 are included in the binary representation, even when they occur before any 1, we can go for binary representations where the first 1 is ignored, and all other binary digits represent the actual Morse code.
This leads to the following code, which is still tree-based: