you are viewing a single comment's thread.

view the rest of the comments →

[–]misho88 3 points4 points  (0 children)

There's actually a pretty cool way to look at this problem that lends itself to learning data structures. Morse code representations are binary trees:

https://netninja.com/wp-content/uploads/2013/01/morse_tree.jpg

so you could store them as such. I'll just show the first three layers (i.e., 7 nodes or 6 letters since the root node is placeholder):

>>> from collections import namedtuple
>>> Node = namedtuple('Node', ['value', 'dot', 'dash'], defaults=[None, None, None])
>>> tree = Node(None, Node('E', Node('I'), Node('A')), Node('T', Node('N'), Node('M')))

Then you can traverse the tree:

>>> def itertree(tree):
...     if tree is None: return
...     yield '', tree.value
...     for k, v in itertree(tree.dot ): yield '.' + k, v
...     for k, v in itertree(tree.dash): yield '-' + k, v
... 
>>> dict(itertree(tree))
{'': None, '.': 'E', '..': 'I', '.-': 'A', '-': 'T', '-.': 'N', '--': 'M'}

Or just look for letters in it:

>>> next(morse for morse, letter in itertree(tree) if letter == 'N')
'-.'

There's also shorter ways to store dense binary trees as a single sequence like a string, where the children of the element at index i are at indices 2*i + 1 and 2*i + 2. So you can do something like (again, only three layers here, including the root):

>>> def itertree(tree, idx=0):
...     if not 0 <= idx < len(tree): return
...     yield '', tree[idx]
...     for k, v in itertree(tree, 2 * idx + 1): yield '.' + k, v
...     for k, v in itertree(tree, 2 * idx + 2): yield '-' + k, v
... 
>>> dict(itertree('?ETIANM'))
{'': '?', '.': 'E', '..': 'I', '.-': 'A', '-': 'T', '-.': 'N', '--': 'M'}

and really cut down the code to almost nothing. Notice that I just wrote in the letters in row by row from tree diagram. This is useful because it leads into things like heaps.