Python Forum
(python) Can i get some help fixing a English to Morse translator? Pls
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
(python) Can i get some help fixing a English to Morse translator? Pls
#1
The problem that I have is that when I type a message for example (hello) instead of only translating those words the program would translate from the letter (A) all the way to the letter (O). The output would look something like this (ABCDEFGHIJKLMNO) but in morse. I'm still pretty new to python so i dont know if I have to put a break somewhere to stop it from doing that.

import winsound
import time

EnglishLetters = ['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', ', ', '.', '?',
                  '/', '-', '(', ')', '@']

MorseCodes = ['.-', '-... ', '-.-.', '-..', '.', '..-.', '--.', '....', '..', '.---', '-.-', '.-..', '--', '-.',
              '---', '.--.', '--.-', '.-.', '...', '-', '..-', '...-', '.--', '-..-', '-.--', '--..', '.----', '..---',
              '...--', '....-', '.....', '-....', '--...', '---..', '----.', '-----', '--..--', '.-.-.-', '..--..',
              '-..-.', '-....-', '-.--.', '-.--.-', '.--.-.']

msg = input("Enter message: ")

MorseMsg = ' '

for ch in msg:
    if ch != ' ':
        i = -1


while (ch.lower() != EnglishLetters[i]):
    i = i + 1
    MorseMsg += MorseCodes[i] + ' '

else:
    MorseMsg += ' '
    print("Morse : " + MorseMsg)


for MorseCodes in MorseMsg:
    if MorseCodes == '.':
        frequency = 750
        duration = 200
        winsound.Beep(frequency, duration)

if MorseCodes == '-':
    frequency = 750
    duration = 600
    winsound.Beep(frequency, duration)

if MorseCodes == ' ':
    time.sleep(0.8)
Output:
Enter message: hello Morse : .- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- (#this translate to 'ABCDEFGHIJKLMNO' )
Reply
#2
It would make your logic a lot easier if you were to replace lines 4-11 with a dictionary.
Then you could pick up the morse code for a letter directly instead of lines 17-28.
Paul
AlexPython likes this post
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#3
How about:
import string

EnglishLetters = list(string.ascii_lowercase + string.digits + ',./-()@ ')

MorseCodes = ['.-', '-... ', '-.-.', '-..', '.', '..-.', '--.', '....', '..', '.---', '-.-', '.-..', '--', '-.',
              '---', '.--.', '--.-', '.-.', '...', '-', '..-', '...-', '.--', '-..-', '-.--', '--..', '.----', '..---',
              '...--', '....-', '.....', '-....', '--...', '---..', '----.', '-----', '--..--', '.-.-.-', '..--..',
              '-..-.', '-....-', '-.--.', '-.--.-', '.--.-.', ' ']

morsedict = dict(zip(EnglishLetters, MorseCodes))

def convert_msg(msg):
    for letter in list(msg):
        print(f"{morsedict[letter]} ", end='')
    print()


convert_msg('cq cq cq de kq9tft')
Output:
-.-. --.- .--.-. -.-. --.- .--.-. -.-. --.- .--.-. -.. . .--.-. -.- --.- ----- - ..-. -
AlexPython likes this post
Reply
#4
There are a few problems.

This is an indentation error.
for ch in msg:
    if ch != ' ':
        i = -1
 
while (ch.lower() != EnglishLetters[i]):   # <- this is not in the for loop
    i = i + 1
    MorseMsg += MorseCodes[i] + ' '
 
else:  # This else is not connected to any if statement
    MorseMsg += ' '
    print("Morse : " + MorseMsg)
Python does not have special code block characters, so indentation serves that purpose. I think you want your code to be indented like this:
for ch in msg:
    if ch != ' ':
        i = -1
        while (ch.lower() != EnglishLetters[i]):
            i = i + 1
            MorseMsg += MorseCodes[i] + ' '
    
    else:
        MorseMsg += ' '
        print("Morse : " + MorseMsg)
And another indentation error here.
for MorseCodes in MorseMsg:
    if MorseCodes == '.':
        frequency = 750
        duration = 200
        winsound.Beep(frequency, duration)
 
if MorseCodes == '-':   #<- Due to indentation this is not in the for loop
    frequency = 750
    duration = 600
    winsound.Beep(frequency, duration)
 
if MorseCodes == ' ':   #<- Due to indentation this is not in the for loop
    time.sleep(0.8)
I assume you want to play a dit, day or pause for each "MorseCodes" in MorseMsg. What will actually happen is you will send all the dits first, possibly followed by one dah or a pause. All three if's need to be indented the same level. I also think you should use elif after the first if to make it really obvious that all three are related.

Though it is not an error, I think it is a bad idea to reuse "MorseCodes". MorseCodes is a list of the Morse codes that map to EnglishLetters. It is confusing to reuse that variable name here to represent something different.

This is your real problem. A logic error.
        i = -1
        while (ch.lower() != EnglishLetters[i]):
            i = i + 1
            MorseMsg += MorseCodes[i] + ' '
I assume what you want to do is append the MorseCodes[index] for the EnglishLetters[index] that is equal to ch. What you are doing instead is appending all MorseCodes starting at 0 and ending at index-1

Python has a command named index() that will find the location of a value in a list (or other indexable type). You probably want to do this:
for ch in msg:
    if ch != ' ':
        MorseMsg.append(MorseCodes[EnglishLetters.index(ch)])
    
    else:
        MorseMsg += ' '
        print("Morse : " + MorseMsg)
This would work, but as others have suggested, a dictionary is a better tool for this job.

After fixing the above errors you have something like this:
msg = input("Enter message: ").lower() # Convert to lower case
MorseMsg = ' '

# This converts the message to 
for ch in msg:
    if ch != ' ':
        MorseMsg += MorseCodes[EnglishLetters(ch)]
    
    else:
        MorseMsg += ' '
        print("Morse : " + MorseMsg)
 
 
for code in MorseMsg:
    if code == '.':
        winsound.Beep(750, 200)
    elif code == '-':
        winsound.Beep(750, 600)
    elif code == ' ':
        time.sleep(0.8)
This works, somewhat, but the printout is wrong. If I enter "The quick brown fox" the program will print.
Output:
- .... . - .... . / --.- ..- .. -.-. -.- - .... . / --.- ..- .. -.-. -.- / -... .-. --- .-- -.
Each time your program encounters a space it prints the MorseMsg. The MorseMsg keeps getting longer and longer because it includes all the words up to that point, not just the word since the last space. And since there is no space after "fox" the last print never happens.

The simple solution is to just wait until the entire message is translated, then print the entire Morse translation.
EnglishLetters = ['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', ', ', '.', '?',
                  '/', '-', '(', ')', '@', ' ']  # Notice the added blank ' '
 
MorseCodes = ['.-', '-... ', '-.-.', '-..', '.', '..-.', '--.', '....', '..', '.---', '-.-', '.-..', '--', '-.',
              '---', '.--.', '--.-', '.-.', '...', '-', '..-', '...-', '.--', '-..-', '-.--', '--..', '.----', '..---',
              '...--', '....-', '.....', '-....', '--...', '---..', '----.', '-----', '--..--', '.-.-.-', '..--..',
              '-..-.', '-....-', '-.--.', '-.--.-', '.--.-.', ' ']  # Notice the added blank ' '

msg = input("Enter message: ")
MorseMsg = ' '

for ch in msg:
    MorseMsg += MorseCodes[EnglishLetters.index(ch)]
print(MorseMsg)
 
for code in MorseMsg:
    if code == '.':
        winsound.Beep(750, 200)
 
    elif code == '-':
        winsound.Beep(750, 600)
    
    elif code == ' ':
        time.sleep(0.8)
Personally, I think it would be more fun to print the characters as the code is being played out.
for ch in input("Enter message: "):
    code = MorseCodes[EnglishLetters.index(ch)]
    print(ch, code)
    for ditdah in code]:
        if ditdah == '.':
            winsound.Beep(750, 200)
        elif ditdah == '-':
            winsound.Beep(750, 600)
        elif ditdah == ' ':
            time.sleep(0.8)
AlexPython likes this post
Reply
#5
The code that I presented in post # 3, does not include sound output, but is simple, efficient, and straight forward.
As shown in the output, works very well for converting ASCII string to Morse code.
It can be called directly from the sound output module (instead of printing string, return conversion).
AlexPython likes this post
Reply
#6
Thank you so much for the help guys <3
Reply
#7
When I was playing with the program it didn't sound quite right. When playing the dits and dahs you need a rest after each letter. The rest is equal in length to a dit. If a dit (.) is 200 msec long, the time to send "s" is 800 msec (dit, dit, dit, rest). The sending code should look like this.
for ch in input("Enter message: "):
    code = MorseCodes[EnglishLetters.index(ch)]
    print(ch, code, flush=True)  # Makes the letters appear as soon as printed
    for ditdah in code]:
        if ditdah == '.':
            winsound.Beep(750, 200)  # 200 msec for dit
        elif ditdah == '-':
            winsound.Beep(750, 600) # 600 msec for day
        elif ditdah == ' ':
            time.sleep(0.6) # 600 msec for pause after word
    time.sleep(0.2) # 200 msec rest after letter
AlexPython likes this post
Reply
#8
(Sep-12-2022, 01:35 AM)deanhystad Wrote: When I was playing with the program it didn't sound quite right. When playing the dits and dahs you need a rest after each letter. The rest is equal in length to a dit. If a dit (.) is 200 msec long, the time to send "s" is 800 msec (dit, dit, dit, rest). The sending code should look like this.
for ch in input("Enter message: "):
    code = MorseCodes[EnglishLetters.index(ch)]
    print(ch, code, flush=True)  # Makes the letters appear as soon as printed
    for ditdah in code]:
        if ditdah == '.':
            winsound.Beep(750, 200)  # 200 msec for dit
        elif ditdah == '-':
            winsound.Beep(750, 600) # 600 msec for day
        elif ditdah == ' ':
            time.sleep(0.6) # 600 msec for pause after word
    time.sleep(0.2) # 200 msec rest after letter

I was also trying to do this Big Grin Thank you so much. I was messing around with the duration and frequency number to try to get it to make the same sound that the morse code on this page does (https://morsecode.world/international/translator.html) but I couldn't guess the correct numbers Cry
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to fix bugs in Morse alphabet code? dokipo 10 2,869 Oct-26-2021, 06:43 PM
Last Post: deanhystad
  write a program which prints the day in english ben1122 10 4,016 Jul-25-2021, 05:55 PM
Last Post: ben1122
  More non english characters johnboy1974 8 4,496 Apr-23-2021, 02:35 PM
Last Post: snippsat
  Invalid syntax error - need help fixing calgk01 3 3,308 Feb-23-2021, 08:41 PM
Last Post: nilamo
  i want to write symbole as varibales in python to make translator rachidel07 9 3,534 Feb-03-2021, 09:57 PM
Last Post: nilamo
  Fixing a code error Twoshawns 5 2,777 May-14-2020, 11:56 AM
Last Post: Twoshawns
  Help Fixing Code kianwalters05 5 3,978 May-12-2020, 12:13 PM
Last Post: kianwalters05
  letter translator (or someting) Obsilion 4 2,466 Apr-28-2020, 12:40 PM
Last Post: deanhystad
  reset on inactivity (building a morse decoder) gerrit1985 7 3,561 Apr-17-2020, 10:22 AM
Last Post: deanhystad
  Fixing "PermissionError: [Errno 13] Permission denied" puredata 17 72,679 Mar-09-2020, 03:20 PM
Last Post: syssy

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020