'Match single unknown parameter php (Morse-code Regex)

I have an function that checks if string( parameter) matches values in an array and returns an array of possibilities key

function find_possible_match( $criteria ) {

  $possible_match = array();


      $possibilities = array(
"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"=>"----.",
"."=>".-.-.-",
","=>"--..--",
"?"=>"..--..",
"/"=>"-..-.",
" "=>" ");


  foreach ( $possibilities as $key => $value ) {

         if( $value == $criteria ){
            array_push(  $possible_match , $key );
        }
  }

  return $possible_match;
} 

this is pretty standard is all criteria where string like

find_possible_match( ".-" );

will return [a]... etc

but the twist is that, what if the params has an unknown, example

find_possible_match("?");

should return [e, t], likewise

find_possible_match("?.")

should return ['i','n'] and

find_possible_match(".?")

should return ['i','a']

? in this case is the wildcard. How do i modify the above code to do just that. Thank you



Solution 1:[1]

You could use preg_match() you check if the $criteria match to $value. You could replace the $criteria according to regular expression requirements (escape dot, convert ? to [.-]):

function find_possible_match( $criteria ) {

    $criteria = str_replace(['.','?'],['\.','[.-]'],$criteria);
    $regexp = '~^'.$criteria.'$~';

    $possibilities = array(
        "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"=>"----.",
        "."=>".-.-.-",
        ","=>"--..--",
        "?"=>"..--..",
        "/"=>"-..-.",
        " "=>" ");


    $possible_match = array();
    foreach ($possibilities as $key => $value) {
        if (preg_match($regexp, $value)) {
            array_push($possible_match, $key);
        }
    }
    return $possible_match;
}

print_r(find_possible_match(".-")); // ['a']
print_r(find_possible_match("?")); // ['e','t']
print_r(find_possible_match("?.")); // ['i','n']
print_r(find_possible_match(".?")); // ['i','a']

Outputs:

Array
(
    [0] => a
)
Array
(
    [0] => e
    [1] => t
)
Array
(
    [0] => i
    [1] => n
)
Array
(
    [0] => a
    [1] => i
)

Solution 2:[2]

You could use array filtering and basic regular expressions to match the $criteria argument:

<?php

function find_possible_match($criteria)
{

    $possible_match = array();

    $possibilities = array(
        "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" => "----.",
        "." => ".-.-.-",
        "," => "--..--",
        "?" => "..--..",
        "/" => "-..-.",
        " " => " ",
    );

    // If the criteria matches a possible morse code (including '.' and '-' only)
    if(preg_match('~^[\.-]+$~', $criteria)) {

        // Filters the array to match the criteria
        $possible_match = array_filter($possibilities, function($value) use ($criteria) {
            return $value === $criteria;
        });

    }

    // If the criteria includes a wildcard
    else if(preg_match('~[?\.-]~', $criteria)) {

        // Creates a regular expression to match according to the given wildcards
        // Each ? will match a single . or -
        $regex = str_replace('.', '\.', $criteria);
        $regex = str_replace('?', '[\.-]', $regex);
        $regex = "~^{$regex}$~";

        // Filters the array to match the criteria
        $possible_match = array_filter($possibilities, function($value) use ($criteria, $regex) {
            return preg_match($regex, $value);
        });


    }

    // Return matches
    return array_keys($possible_match);

}

// Test cases
$test = array(
    '.-',
    '?',
    '?.',
    '.?',
);

foreach($test as $criteria) {
    print_r(find_possible_match($criteria));
}

Output:

Array
(
    [0] => a
)
Array
(
    [0] => e
    [1] => t
)
Array
(
    [0] => i
    [1] => n
)
Array
(
    [0] => a
    [1] => i
)

Solution 3:[3]

You can do it this way:

function get_morse() {
  return $morse_codes = array(
        "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"=>"----.",
        "."=>".-.-.-",
        ","=>"--..--",
        "?"=>"..--..",
        "/"=>"-..-.",
        " "=>" "
    );
}

function possibilities($signals) {
  
    $signals = str_replace(['.','?'],['\.','[.-]'],$signals);
    $regexp = '~^'.$signals.'$~';
    $morse_codes = get_morse();
    $result = [];
  
    foreach ($morse_codes as $key => $value) {
        if (preg_match($regexp, $value)) { 
          $result[$value] = $key;
        }
    }
    krsort($result);
    return array_values($result);
  
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Syscall
Solution 2
Solution 3 Kasim Ridwan