Home > Mobile >  How to decode morse code in a more pythonic way
How to decode morse code in a more pythonic way

Time:02-13

I have made a morse_code decoder in python as an assignment as shown below. It handles all characters available in morse_code. Although my approach works, it feels like a very amateurish way of doing things in python. The format in which morse code is sent:

  1. Characters are encoded by substituting them with combinations of '.' and '-'
  2. Characters are separated with " " (whitespace)
  3. Words are separated with " " (triple whitespace)

In my code below I create an empty list, which get filled with a list in which each item represents a single morse code character, that is then replaced with the actual character. Finally, the lists within the list are joined, and the resulting list is joined as well so it can be returned as a string value. The reason I work with lists is because strings are immutable in python. I can't create an empty string, go into a for loop, and append to the string. I can not create a new string within the for loop either, since the variable will be lost upon leaving the for loop scope.

I have tried to do it with the replace method first, but I ran into trouble because replace doesn't have the flexibility needed to decode morse code.

decode_morse(morse_code):
    morse_code_q = " " morse_code " "
    morse_code_r = morse_code_q.replace(" .- ", ' A ').replace(" -... ", ' B ').replace(' -.-. ', ' C ').replace(' -.. ', 'D ').replace(' . ', ' E ').replace(' ..-. ', ' F ').replace(' --. ', ' G ').replace(' .... ', ' H ').replace(' .. ', ' I ').replace(' .--- ', ' J ').replace(' .-. ', ' K ').replace(' .-.. ', ' L ').replace(' -- ', ' M ').replace(' -. ', ' N ').replace(' --- ', ' O ').replace(' .--. ', ' P ').replace(' --.- ', ' Q ').replace(' .-. ', ' R ').replace(' ... ', ' S ').replace(' - ', ' T ').replace(' ..- ', ' U ').replace(' ...- ', ' V ').replace(' .--', ' W ').replace(' -..- ', ' X ').replace(' -.-- ', ' Y ').replace(' --.. ', ' Z ').replace(' ----- ', '0').replace(' .---- ', '1').replace(' ..--- ', '2').replace(' ...-- ', '3').replace(' ....- ', '4').replace(' ..... ', '5').replace(' -.... ', '6').replace(' --... ', '7').replace(' ---.. ', '8').replace(' ----. ', '9').replace(' .-.-.- ', '.').replace(' --..-- ', ',').replace(' ..--.. ', '?')
    return morse_code_r.strip()
print(decode_morse('.... . -.--   .--- ..- -.. .'))

This returns H E Y J U D E, rather than HEY JUDE. Leaving out the spaces won't do much good. After replacing a character, the next replace function won't be able to find a character, because it needs the spaces to determine the start and the end of a character (else .... for H would resolve to EEEE, since . = E)

So here is my very ugly but working approach:

def decode_morse(morse_code):
  result=[]
  words = morse_code.split("   ")
  for j in range(0,len(words)):
    reverser = words[j].split(" ")
    for i in range(0,len(reverser)):
      if reverser[i]==".-":
          reverser[i]='A'
      elif reverser[i]=="-...":
        reverser[i]='B'
      elif reverser[i]=="-.-.":
        reverser[i]='C'
      elif reverser[i]=="-..":
        reverser[i]='D'
      elif reverser[i]==".":
        reverser[i]='E'
      elif reverser[i]=="..-.":
        reverser[i]='F'
      elif reverser[i]=="--.":
        reverser[i]='G'
      elif reverser[i]=="....":
        reverser[i]='H'
      elif reverser[i]=="..":
        reverser[i]='I'
      elif reverser[i]==".---":
        reverser[i]='J'
      elif reverser[i]==".-.":
        reverser[i]='K'
      elif reverser[i]==".-..":
        reverser[i]='L'
      elif reverser[i]=="--":
        reverser[i]='M'
      elif reverser[i]=="-.":
        reverser[i]='N'
      elif reverser[i]=="---":
        reverser[i]='O'
      elif reverser[i]==".--.":
        reverser[i]='P'
      elif reverser[i]=="--.-":
        reverser[i]='Q'
      elif reverser[i]==".-.":
        reverser[i]='R'
      elif reverser[i]=="...":
        reverser[i]='S'
      elif reverser[i]=="-":
        reverser[i]='T'
      elif reverser[i]=="..-":
        reverser[i]='U'
      elif reverser[i]=="...-":
        reverser[i]='V'
      elif reverser[i]==".--":
        reverser[i]='W'
      elif reverser[i]=="-..-":
        reverser[i]='X'
      elif reverser[i]=="-.--":
        reverser[i]='Y'
      elif reverser[i]=="--..":
        reverser[i]='Z'
      elif reverser[i]=="-----":
        reverser[i]='0'
      elif reverser[i]==".----":
        reverser[i]='1'
      elif reverser[i]=="..---":
        reverser[i]='2'
      elif reverser[i]=="...--":
        reverser[i]='3'
      elif reverser[i]=="....-":
        reverser[i]='4'
      elif reverser[i]==".....":
        reverser[i]='5'
      elif reverser[i]=="-....":
        reverser[i]='6'
      elif reverser[i]=="--...":
        reverser[i]='7'
      elif reverser[i]=="---..":
        reverser[i]='8'
      elif reverser[i]=="----.":
        reverser[i]='9'
      elif reverser[i]==".-.-.-":
        reverser[i]='.'
      elif reverser[i]=="--..--":
        reverser[i]=','
      elif reverser[i]=="..--..":
        reverser[i]='?'
    result.append(reverser)
    final =[]
    for h in range(0,len(result)):
      final.append("".join(result[h]) " ")
  return "".join(final)

print(decode_morse('.... . -.--   .--- ..- -.. .'))  #returns HEY JUDE

Anyone with a solution that makes this more pythonic? For this exercise, we are not allowed to use regexp library. Thanks in advance.

CodePudding user response:

Always turn code into data whenever possible.

decode_table = {
    ".-": "A",
    "-...": "B",
    "-.-.": "C",
    "-..": "D",
    ".": "E",
    "..-.": "F",
    "--.": "G",
    "....": "H",
    "..": "I",
    ".---": "J",
    ".-.": "K",
    ".-..": "L",
    "--": "M",
    "-.": "N",
    "---": "O",
    ".--.": "P",
    "--.-": "Q",
    ".-.": "R",
    "...": "S",
    "-": "T",
    "..-": "U",
    "...-": "V",
    ".--": "W",
    "-..-": "X",
    "-.--": "Y",
    "--..": "Z",
    "-----": "0",
    ".----": "1",
    "..---": "2",
    "...--": "3",
    "....-": "4",
    ".....": "5",
    "-....": "6",
    "--...": "7",
    "---..": "8",
    "----.": "9",
    ".-.-.-": ".",
    "--..--": ",",
    "..--..": "?",
    "SPACE": " ",
}

Now, simply:

def decode(encoded):
    symbols = encoded.replace("   ", " SPACE ").split(" ")
    return "".join(decode_table[x] for x in symbols)

Test:

>>> decode(".... . -.--   .--- ..- -.. .")
'HEY JUDE'

CodePudding user response:

here is the best way to implement morse code decoder and encoder :

morseAlphabet ={
    "A" : ".-",
    "B" : "-...",
    "C" : "-.-.",
    "D" : "-..",
    "E" : ".",
    "F" : "..-.",
    "G" : "--.",
    "H" : "....",
    "I" : "..",
    "J" : ".---",
    "K" : "-.-",
    "L" : ".-..",
    "M" : "--",
    "N" : "-.",
    "O" : "---",
    "P" : ".--.",
    "Q" : "--.-",
    "R" : ".-.",
    "S" : "...",
    "T" : "-",
    "U" : "..-",
    "V" : "...-",
    "W" : ".--",
    "X" : "-..-",
    "Y" : "-.--",
    "Z" : "--..",
    " " : "/"
    }

inverseMorseAlphabet=dict((v,k) for (k,v) in morseAlphabet.items())

def decodeMorse(code, positionInString = 0):
    
    if positionInString < len(code):
        morseLetter = ""
        for key,char in enumerate(code[positionInString:]):
            if char == " ":
                positionInString = key   positionInString   1
                letter = inverseMorseAlphabet[morseLetter]
                return letter   decodeMorse(code, positionInString)
            
            else:
                morseLetter  = char
    else:
        return ""
    

def encodeToMorse(message):
    encodedMessage = ""
    for char in message[:]:
        encodedMessage  = morseAlphabet[char.upper()]   " "
            
    return encodedMessage
  • Related