Nizakat Hafsana
Nizakat Hafsana

Reputation: 21

Function that check if letters and or whole word is a contained in a given string

I want to solve the following problem through regular expression

  1. All 5 letters 'g', 'o', 'l', 'd','e','n' are included (in any sequence) and
  2. The string 'golden' is a substring of the given string.

If 1 holds (but 2 does not), return 1.
If both 1 and 2 hold, return 2. Otherwise return 0.

here is my code.

function checkstrling($input, $substring) 
{
    $voodoo = preg_match("(".implode("(.*?)",array_map('preg_quote',str_split($substring))).")",$input,$matches);
    if( !$voodoo) return 0; // no match
    $pieces = implode("",array_slice($matches,1)); // in-between bits
    if( $pieces !=="") return 1; // there was stuff in between
    return 2; // substring found without interruption
}

var_dump(checkstrling("xgolensssx","golden"));
var_dump(checkstrling("abcgxyommlgdqqesn","golden"));
var_dump(checkstrling("xgoldensssx","golden"));

The function work find when i call and provide the following parameter it work fine.

var_dump(checkstrling("xgolensssx","golden"));
var_dump(checkstrling("abcgxyommlgdqqesn","golden"));
var_dump(checkstrling("xgoldensssx","golden"));

But does not work properly when i call the function again with the following paramenter.

var_dump(checkstrling("somegxoxdxlxnmme","golden"));
var_dump(checkstrling("somegxoxlxdxemnmgoldenv","golden"));

Upvotes: 2

Views: 61

Answers (2)

ctwheels
ctwheels

Reputation: 22837

Brief

No need for regex here, it'll just complicate things.


Code

See code in use here

function checkstrling($input, $substring) 
{
    if (strpos($input, $substring) !== false) {
       return 2;
    }
    foreach (str_split($substring) as $char) {
        if (strpos($input, $char) === false) {
            return 0;
        }
    }
    return 1;
}

print checkstrling("xgolensssx","golden");              // 0
print checkstrling("abcgxyommlgdqqesn","golden");       // 1
print checkstrling("xgoldensssx","golden");             // 2

print checkstrling("somegxoxdxlxnmme","golden");        // 1
print checkstrling("somegxoxlxdxemnmgoldenv","golden"); // 2

Sidenote: You can change str_split($substring) to array_unique(str_split($substring)) to remove duplicates before going through the loop. This may improve performance for larger $substrings that contain duplicate letters (such as the word goldenrod: goldenr would be the resulting array).


Explanation

  • If word exists in string, return 2, otherwise, continue
  • Loop over each character in $substring
    • If the character is not found, return 0
  • This point is only reached if the loop was completed successfully, return 1

Upvotes: 3

Jan
Jan

Reputation: 43199

You could use multiple lookaheads:

(?=[^g]*g)
(?=[^o]*o)
(?=[^l]*l)
(?=[^d]*d)
(?=[^e]*e)
(?=[^n]*n)

The pattern is always the same: look for anything not g zero or more times, than look for g.


In PHP:

<?php

function checkstrling($input, $substring) {
    $regex = '~(?=[^g]*g)(?=[^o]*o)(?=[^l]*l)(?=[^d]*d)(?=[^e]*e)(?=[^n]*n).+~';

    if ((preg_match($regex, $input) && (strpos($input, $substring) !== false))) {
        return 2;
    } else if (preg_match($regex, $input)) {
        return 1;
    }
    return 0;
}

var_dump(checkstrling("xgolensssx","golden"));
var_dump(checkstrling("abcgxyommlgdqqesn","golden"));
var_dump(checkstrling("xgoldensssx","golden"));
var_dump(checkstrling("somegxoxdxlxnmme","golden"));
var_dump(checkstrling("somegxoxlxdxemnmgoldenv","golden"));
?>

Which yields

int(0)
int(1)
int(2)
int(1)
int(2)

Upvotes: 0

Related Questions