I am working on a Morse Code encoding/ decoding tool. I have completed the encoder, and I'm working on the decoder. Currently the decoding function "MorseCodeDecoder(MSG)" can decode a single letter at a time. It does this by checking every character in a string one by one and copying them to the variable, "EncodedLetter". The program checks each character to see if it is a space, if it is the program identifies this a gap between letter, for example:
MSG = ".... .." -*the function runs*- EncodedLetter = "....".
Then that value is back searched through a dictionary(using lists) to find what EncodedLetter's key whould be, in this case it's "H", the program also checks for double spaces which represent the space between two words. At this point in time it may sound fully functional; however after finding one encoded letter it can't find another, so earlier ".... .." it can't find ".." even though I reset the variable after it successfully decodes a letter.
MorseCodeDictionary = {' ': ' ', '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': '--..', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----'}
def MorseCodeEncoder(MSG):
EncodedMSG = f"""Encoded Message:
"""
MSG = MSG.upper()
for i in range(0, len(MSG), 1):
Encode = (MSG[i])
EncodedMSG = f"{EncodedMSG} {(MorseCodeDictionary.get(Encode))}"
return EncodedMSG
def MorseCodeDecoder(MSG):
DecodedMSG = f"""Decoded Message:
"""
MSG = MSG.upper()
DecodedWord = ''
DecodedLetter = ''
EncodedLetter = ''
for i in range(0, len(MSG)):
DecodedLetter = ''
Decode = (MSG[i])
try:
if (MSG[i + 1]) == ' ':
EncodedLetter = f"{EncodedLetter + (MSG[i])}"
DecodedLetter = list(MorseCodeDictionary.keys())[list(MorseCodeDictionary.values()).index(EncodedLetter)]
DecodedWord = DecodedWord + DecodedLetter
EncodedLetter = ''
DecodedMSG = f"{DecodedMSG} {DecodedWord}"
elif (MSG[i + 1]) + (MSG[i + 2]) == ' ':
DecodedWord = ''
else:
EncodedLetter = f"{EncodedLetter + (MSG[i])}"
except (ValueError,IndexError):
pass
return DecodedMSG
Loop = 1
while Loop == 1:
Choice = str(input("""[1] Encode, or [2] decode?
"""))
if Choice == '1':
MSG = str(input("""Type the message you would like to encode. Do not use puncuation.
"""))
EncodedMSG = (MorseCodeEncoder(MSG))
print (EncodedMSG)
elif Choice == '2':
MSG = str(input("""Type what you wish to decode.
"""))
DecodedMSG = (MorseCodeDecoder(MSG))
print (DecodedMSG)
else:
print ('1, or 2')
Instead of blundering about with appending to strings and picking out each character from your encoded string to form a morse-code letter, you can just use str.join()
and str.split()
! Also, I suggest separating your encoded morse code letters by a character that cannot be a part of a correctly encoded string, such as /
. This way, you are sure that all spaces in the string are a space and all slashes in the string are letter separators. First, let's define the dictionaries for both encoding and decoding
en_to_morse = {' ': ' ', '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': '--..', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----'}
morse_to_en = {v: k for k, v in en_to_morse.items()} # Reverse lookup for encoder
The morse_to_en
dictionary can be created simply by reversing the keys and values in the en_to_morse
dictionary. These two could be combined, since they do not have any common keys (except space, which doesn't really matter because it remains the same), but I'm going to keep them separate for this example.
Then, you can write the encoder function like so:
def MorseEncode(msg):
morse_msg = [] # make an empty list to contain all our morse symbols
for char in msg.upper(): # Convert msg to uppercase. Then iterate over each character
morse_char = en_to_morse[char] # Get the translation from the dictionary
morse_msg.append(morse_char) # Append the translation to the list
return '/'.join(morse_msg) # Join symbols with a '/'
The decoder function is just the reverse of the encoder function.
def MorseDecode(msg):
morse_chars = msg.split("/") # Split at '/'
en_msg = "" # Empty message string
for char in morse_chars: # Iterate over each symbol in the split list
en_char = morse_to_en[char] # Translate to English
en_msg += en_char # Append character to decoded message
return en_msg
To run this:
encoded = MorseEncode("Hello World") # gives '...././.-../.-../---/ /.--/---/.-./.-../-..'
decoded = MorseDecode(encoded) # gives 'HELLO WORLD'
You lose case-information because Morse code doesn't separate symbols for have upper/lower case characters.
You could write your functions as one-liners too:
def MorseEncode(msg):
return '/'.join(en_to_morse[char] for char in msg.upper())
def MorseDecode(msg):
return ''.join(morse_to_en[char] for char in msg.split('/'))