seeking for the good pattern in preg_match

This is a discussion on seeking for the good pattern in preg_match within the PHP Language forums, part of the PHP Programming Forums category; Hi, Suppose I have one string $str = "ABCCD" Here are some examples for which I want to return ...


Go Back   Usenet Forums > PHP Programming Forums > PHP Language

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 12-12-2007
geantbrun
 
Posts: n/a
Default seeking for the good pattern in preg_match

Hi,
Suppose I have one string $str = "ABCCD"

Here are some examples for which I want to return TRUE:
"ABCD"
"BACC"
"DCA"

and others for which I want to return FALSE:
"ABCDE"
"BACDD"
"ABB"

You see the pattern? You have to choose letters from the string only,
the order has no importance but you must not have more letters of one
kind than found in the string $str.

What would be the correct preg_match pattern for this problem?
Any hint appreciated,
Patrick
Reply With Quote
  #2 (permalink)  
Old 12-12-2007
Toby A Inkster
 
Posts: n/a
Default Re: seeking for the good pattern in preg_match

geantbrun wrote:

> What would be the correct preg_match pattern for this problem?


I don't think there would be one in general. You need to do something
like this:

$str = 'ABCCD';
$testing = 'DCA';
$pass = TRUE;
$cs = ''; // change to 'i' to make it case-insensitive
while (strlen($testing))
{
$char = substr($testing, 0, 1);
$testing = substr($testing, 1);

if (!preg_match("/$c/$cs", $str))
{
$pass = FALSE;
break;
}

$str = preg_replace("/([^$c]$)c/$cs", '\1', $str);
}
echo $pass ? 'passed' : 'failed';


--
Toby A Inkster BSc (Hons) ARCS
[Geek of HTML/SQL/Perl/PHP/Python/Apache/Linux]
[OS: Linux 2.6.17.14-mm-desktop-9mdvsmp, up 5 days, 9:40.]

Sharing Music with Apple iTunes
http://tobyinkster.co.uk/blog/2007/1...tunes-sharing/
Reply With Quote
  #3 (permalink)  
Old 12-13-2007
geantbrun
 
Posts: n/a
Default Re: seeking for the good pattern in preg_match

Thank you for the answer Tony.
First did you mean $char instead of $c in your code? (3 occurences?)
I would like to better understand your algorithm because it does not
seem to work with $testing="DDCA" (it passed but it's supposed to
fail). I understand that you test first if each character is in $str
but what's the point of your preg_replace at the end?
Cheers,
Patrick
Reply With Quote
  #4 (permalink)  
Old 12-13-2007
Csaba Gabor
 
Posts: n/a
Default Re: seeking for the good pattern in preg_match

geantbrun wants to know when a test string is a subsequence of a permutation of another given string:

$str = "ABCCD";
$aTest = array("ABCD", "BACC", "DCA", "DDCA",
"ABCDE", "BACDD", "ABB");

print "For base string '$str':<br><br>\n";
foreach ($aTest as $test)
print (subPerm ($test, $str) ? "Passed" : "Failed")
. " on '$test'<br>\n";

function subPerm ($test, $str) {
/* returns true iff $sub is a subsequence of a permutation of $subject */
$aStr = count_chars($str, 1);
foreach (count_chars($test, 1) as $ord=>$count)
if (!array_key_exists($ord, $aStr) || $aStr[$ord] < $count)
return false;
return true; }


Csaba Gabor from Vienna
Reply With Quote
  #5 (permalink)  
Old 12-13-2007
Toby A Inkster
 
Posts: n/a
Default Re: seeking for the good pattern in preg_match

geantbrun wrote:

> First did you mean $char instead of $c in your code? (3 occurences?)


Yep -- this is what happens when you post code without testing it! ;-)

Or the other way around, I meant '$c' when I wrote '$char'. Either way,
they should both be the same!

> I would like to better understand your algorithm because it does not seem
> to work with $testing="DDCA" (it passed but it's supposed to fail). I
> understand that you test first if each character is in $str but what's
> the point of your preg_replace at the end?


The preg_replace at the end if broken. Should be:

$str = preg_replace("/([^$c])$c/$cs", '\1', $str);

(I had the ')$' as '$)' instead, which is wrong!)

What this does, is removes the first occurrence of $c from $str.

So basically, as a whole, the algorithm does this:

For each character in $testing:

Check to see if it exists in $str.
If not, then fails the test.
Otherwise, remove that character from $str and continue.

--
Toby A Inkster BSc (Hons) ARCS
[Geek of HTML/SQL/Perl/PHP/Python/Apache/Linux]
[OS: Linux 2.6.17.14-mm-desktop-9mdvsmp, up 5 days, 21:50.]

Sharing Music with Apple iTunes
http://tobyinkster.co.uk/blog/2007/1...tunes-sharing/
Reply With Quote
  #6 (permalink)  
Old 12-13-2007
geantbrun
 
Posts: n/a
Default Re: seeking for the good pattern in preg_match


Thanks Tony,
If I understand well, the preg_replace line should be:
$str = preg_replace("/$c/$cs", '\1', $str, 1 );

I did 2 replacements:
1- I put a one for the count parameter (you must replace only one
letter from $str)
2- I removed the ([^$c]) from the pattern because the character can be
at first position.

At first glance, it seems to work. I did't have the time to look at
the code from Csaba right now.
Thank you again folks!
Patrick

Reply With Quote
  #7 (permalink)  
Old 12-13-2007
gosha bine
 
Posts: n/a
Default Re: seeking for the good pattern in preg_match

On Dec 12, 10:31 pm, geantbrun <agin.patr...@gmail.com> wrote:
> Hi,
> Suppose I have one string $str = "ABCCD"
>
> Here are some examples for which I want to return TRUE:
> "ABCD"
> "BACC"
> "DCA"
>
> and others for which I want to return FALSE:
> "ABCDE"
> "BACDD"
> "ABB"
>
> You see the pattern? You have to choose letters from the string only,
> the order has no importance but you must not have more letters of one
> kind than found in the string $str.
>
> What would be the correct preg_match pattern for this problem?
> Any hint appreciated,
> Patrick


Hi

I'd suggest

function test($test, $pattern) {
$map = count_chars($pattern, 0);
foreach(count_chars($test, 1) as $chr => $cnt)
if($cnt > $map[$chr]) return false;
return true;
}

$pat = "ABCCD";
$test = "ABCCD BACC DCA ABCDE BACDD ABB XX" ;

foreach(preg_split("~\s+~", $test) as $t)
printf("%20s %d\n", $t, test($t, $pat));


--
gosha bine

[gui for google chart api http://www.tagarga.com/files/gcui]
[makrell http://www.tagarga.com/blok/makrell]
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 02:23 PM.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0