Search code examples
pythonuser-inputmorse-code

If String ONLY contains "-" or "."


I'm writing a small function which checks to see if an inputted string is morse code. The function should do something like "If "-" or "." only in Inputted_string: " But i can't seem to find a way to do the only bit on Python3. The current way i have this implemented is very messy and not very Pythonic

if "-" in message:
    # message might be morse code so check even more
        if "." in message:
            # Message IS morse code so return true
            return True
        else:
            # TODO you can use a REGEX for the below things
            if '--' in message:
                # if the messsage contains only hyphens, then check to see if
                # message contans hyphen only morse code by checking all hyphen
                # only morse code against message
                return True
            elif '-----' in message:
                # if message contains 0 in morse code, return True
                return True
    if "." in message:
        # message might contain morse code
        if "-" in message:
            # message IS morse code.
            return True
        else:
            # check to see if message is dots only morse code
            # TODO you can use a REGEX for the below things
            if ".." in message:
                # message IS Morse Code
                return True
            elif "..." in message:
                # message IS Morse Code
                return True
            elif "....":
            # message IS Morse Code
                return True
        # if dots or dash not in message, return none
        return("Message has no hyphens or full stops")

the formatting is slightly off when i pasted, but that's the general gist. When it checks to see if message is "----" or ".." etc, this is because some morse code letters are only those charecters, but i'm sure there's a much easier way to go around this!


Solution

  • def is_morse(message):
        allowed = {".", "-", " "}
        return allowed.issuperset(message)
    

    But because the message has all the characters does not mean it is valid. You would need to check if each is valid which you can do using a dict mapping letters to morse, you also need to have some format which is unambiguous i.e a space between letters and 2 or more spaces between words:

    morse = {'---': 'O', '--.': 'G', '-...': 'B', '-..-': 'X', '.-.': 'R', '--.-': 'Q',
             '--..': 'Z', '.--': 'W', '..---': '2', '.-': 'A', '..': 'I', '-.-.': 'C',
             '..-.': 'F', '-.--': 'Y', '-': 'T', '.': 'E', '.-..': 'L', '...': 'S',
             '..-': 'U', '.----': '1', '-----': '0', '-.-': 'K', '-..': 'D', '----.':
                 '9', '-....': '6', '.---': 'J', '.--.': 'P', '....-': '4', '--': 'M',
             '-.': 'N', '....': 'H', '---..': '8', '...-': 'V', '--...': '7', '.....':
            '5', '...--': '3',"":" "}
    
    
    msg = ".... . .-.. .-.. -----  .-- --- .-. .-.. -.."
    
    def is_morse(message):
        spl = message.split(" ")
        return  all(m in morse for m in spl)
    
    if is_morse(msg):
        print("".join([morse[ch] for ch in msg.split(" ")]))
    

    It is possible to parse it as a single string getting all variations, it just take a lot more work.

    If you want to go the other way then you just reverse the mappings:

    to_morse = {v: k for k, v in morse.items()}
    
    def can_morse(msg):
        return all(ch in to_morse for ch in msg.upper())
    
    
    msg = "Hello  World"
    if can_morse(msg):
        print(" ".join([to_morse[ch] for ch in msg.upper()]))
    

    I choose extra spaces to delimit the words, you can choose whatever you like just make sure to add the characters to the dict mapping then to a space or whatever you want the words delimited by.