skip to Main Content

I’m writing a function that decodes a morse code message to plain text. The problem I’m running into, is that it doesn’t add spaces where needed. Keep in mind that every morse code character/letter, is separated with a blank space and every full word, is separated by 3 spaces. I want the function to add a single blank space to the plain text when it detects 3 blank spaces in a row in the morse code. I can’t figure it out so i’ve come here.

Here is the function as it is now.

public function decode($morseCode)
{
    // 1 space between characters, 3 spaces between words

    // split the string
    $morseArray = preg_split('/s+/', $morseCode, -1);

    $plainText = '';
    $blankSpaceCount = 0;
    // set each string as a morse code character
    foreach ($morseArray as $morseChar) 
    {
        if ($morseChar != ' ')
        {
            // check if the morsecode character is in the array
            if(isset($this->plainTextsByMorseCode[$morseChar]))
            {
                // if it is, convert it to the corresponding plain text
                $plainText .= $this->plainTextsByMorseCode[$morseChar];
                $blankSpaceCount = 0;
            }
        }           
        else {
            $blankSpaceCount++;
        
            if ($blankSpaceCount === 3) 
            {
                $plainText .= ' ';  // Append a single blank space
                $blankSpaceCount = 0;
            }
        }
    }           

    return trim($plainText);
}

If it helps, the phrase i’m trying to decode is as follows:

-.-- --- ..-   ... .... .- .-.. .-..   -. --- -   .--. .- ... ...

It says "YOU SHALL NOT PASS" and you can clearly see the triple blank spaces between the words and the singular blank space between the letters.

3

Answers


  1. $morsecode='your morse code';
    
    //empty array for decode words
    $decoded_words=[];
    
    //split the code in words on 3 spaces
    $morse_words=explode('   ',$morsecode); //3 spaces
    
    //loop the words
    foreach($morse_words as $word){
        //empty string for decoded characters
        $plain_word='';
        
        //split the word into characters on 1 space
        $morse_chars=explode(' ',$word); //1 space
        
        //loop the characters, decode and add to the plain word string
        foreach($morse_chars as $char){
            $plain_word.=decode_morse_character($char);
            }
        //Add decoded word to the words array
        $decoded_words[]=$plain_word;
        
        }
    
    //implode the decoded_words array with a space between every word
    $decoded=implode(' ',$decoded_words);
    
    Login or Signup to reply.
  2. As @Thefourthbird has pointed out, you are splitting into an array using spaces (regardless of the number) and then you are trying to count spaces again after that. It’s irrelevant because you already parsed the words into an array of letters.

    This simple test illustrates the mistake in your logic and the proper regex to break your cipher into any array of words.

    <?php
    
    $morseCode = '-.-- --- ..-   ... .... .- .-.. .-..   -. --- -   .--. .- ... ...';
    
    $morseArray = preg_split('/s{3}/', $morseCode, -1);
    
    var_dump($morseArray);
    

    The output is:

    array(4) {
      [0]=>
      string(12) "-.-- --- ..-"
      [1]=>
      string(21) "... .... .- .-.. .-.."
      [2]=>
      string(8) "-. --- -"
      [3]=>
      string(15) ".--. .- ... ..."
    }
    

    Once you have the array of words, you are only left to convert to letters, and add a space back for all but the final word in the word array.

    Login or Signup to reply.
  3. After the splitting, this part is always true if ($morseChar != ' ') so you will not reach the else clause.

    Here is another take on it, mapping the morse to the plain text characters exploding first on 3 spaces and then on a single space.

    public function decode($morseCode)
    {
        $decodedWords = [];
    
        foreach (explode('   ', $morseCode) as $morseWord) {
            $decodedWords[] = implode('', array_map(
                fn($morse) => $this->plainTextsByMorseCode[$morse] ?? '',
                explode(' ', $morseWord)
            ));
        }
    
        return implode(' ', $decodedWords);
    }
    

    The output will be

    YOU SHALL NOT PASS
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search