Search code examples
treeracketmorse-code

Morse-decoder for words


I'm trying to program a decoder for morse code. So far I've created a tree containing the morsecode for all letters.

(define gap '/)
(define long-gap '_)
(define long '-)
(define short '*)

(define morsetree
(make-node "-" gap 
         (make-node "E" short
          (make-node "I" short 
           (make-node "S" short 
            (make-node "H" short empty empty)
            (make-node "V" long empty empty))
           (make-node "U" long 
             (make-node "F" short empty empty)
             empty))
          (make-node "A" long 
                     (make-node "R" short
                                (make-node "L" short empty empty)
                                empty)
                     (make-node "W" long 
                                (make-node "P" short empty empty)
                                (make-node "J" long empty empty))))

        (make-node "T" long 
         (make-node "N" short
          (make-node "D" short
           (make-node "B" short empty empty)
           (make-node "X" long empty empty))
          (make-node "K" long
           (make-node "C" short empty empty)
           (make-node "Y" long empty empty)))
         (make-node "M" long
          (make-node "G" short
            (make-node "Z" short empty empty)
            (make-node "Q" long empty empty))
          (make-node "O" long empty empty)))))

I've got a working decoder for a single character:

(define (decode-character code atree)
  (cond
   ((symbol=? (first code) '*) (decode-character (rest code)(node-left atree)))
   ((symbol=? (first code) '-) (decode-character (rest code)(node-right atree)))
   ((symbol=? (first code) '/) (node-letter atree))))

But my decoder for words doesn't work correctly:

 (define (decode code atree)
 (cond
 ((symbol=? (first code) '*) (decode (rest code)(node-left atree)))
 ((symbol=? (first code) '-) (decode (rest code)(node-right atree)))
 ((symbol=? (first code) '/) (cons (node-letter atree) (decode (rest code) atree)))

 ((and (symbol=? (first code) '_) (empty? (rest code))) 
                                          (cons (node-letter atree) (cons " " empty)))
((and (symbol=? (first code) '_) (not(empty? (first (rest code))))) (cons (node-letter atree)  (cons " " (decode (rest code) atree))))))

Using this test: (decode (list '- '/ '* '* '/ '* '_) morsetree)

gives me (list "T" "D" "B" " ") instead of (list "T" "I" "E" " ") since the decoder stays at the position in the tree where it stopped. So instead of '* '* the decodes reads '- '* '*.

How can I "jump" to the beginning of my morsetree after a letter is decoded succesfully?

Lots of text for such a small problem. I don't need a code just a good hint at how I could solve this problem. Thanks in advance.


Solution

  • A quick fix to leave your code mostly unchanged:
    Supply a third parameter to decode, which is the full tree. Always pass the full tree to the next call as the third argument. On your recursive calls when you start a new letter, you pass the full tree to atree, so you aren't starting a new letter in the middle of your tree.

    A fix that will require more work, but would make it (in my opinion) a cleaner and better program:
    Inside your decode function, use your decode-character function that you've already made. There's no reason the decode function needs to know about the tree structure. You can get the first character from decode-character, and then call decode with the code that starts after the next '/ or '_