Reputation: 19
Thread's title might be little bit misleading, but I didnt find out any better way to name it. I want to find a way using regex to look for words that contains only letters x and y, but x has to be used an even-numbered times and y has to be used odd-numbered times.
Upvotes: 0
Views: 492
Reputation: 34395
Here's a tested JavaScript example function implementing a single regex that meets your requirements. I am assuming that zero is an acceptable (even) number of Xs. The regex is documented in a multi lined comment.
function has_even_X_odd_Y_word(text) {
/*#!(?#!js\/i re_even_x_odd_y Rev:20170125_2100)
# Match word having even count of X and odd count of Y.
\b # Anchor to start of word.
# First assert odd, non-zero count of Ys in this word.
(?= # Assert odd count of Y.
(?: # Zero or more or more Y pairs.
x*y # Optional Xs preceeding 1st Y.
x*y # Optional Xs preceeding 2nd Y.
)* # End zero or more Y pairs.
x*yx* # Optional Xs around last (odd) Y.
\b # Anchor to end of word.
) # End assert odd count of Y.
# Match even number of Xs (can be zero = even).
(?: # Zero or more X pairs.
y*x # Optional Ys preceeding 1st X.
y*x # Optional Ys preceeding 2nd X.
)* # End zero or more X pairs.
y* # Optional Ys after last (even) X.
\b # Anchor to end of word.
!#*/
var re_even_x_odd_y = /\b(?=(?:x*yx*y)*x*yx*\b)(?:y*xy*x)*y*\b/i;
if (re_even_x_odd_y.test(text)) { return true; }
return false;
} // End has_even_X_odd_Y_word().
The function returns true if a matching word is found in the passed text and false otherwise.
Upvotes: 0
Reputation: 377
I've tested this in my editor:
(?=([^x]*x[^x]*x[^x]*)*)(?=([^y]*y[^y]*y[^y]*)*[^y]*y[^y]*)
This will find substrings, so you may want to add space, beginning, end of line characters:
[^\s](?=([^x]*x[^x]*x[^x]*)*)(?=([^y]*y[^y]*y[^y]*)*[^y]*y[^y]*)[$\s]
To break it down, [^x]*x[^x]*x[^x]*
will grab all not-x, until it finds the first x, then grabs whatever following non-x until it finds the second x, then again grabs whatever else follows until another x. This is enclosed in ( )* so that it is repeated unlimited number of times, so that it finds all pairs of x's. If there is an odd x left over (odd x's), the regex will not be able to match that single x left.
Similarly for the y case, it matches all pairs of y's, then makes sure there is a single y left followed by all not-y's.
I used ?= so that it matches but does not capture, so that we can check for x's then in the same string check for y's.
Upvotes: 0
Reputation: 308
I would know how to do that with two regex's.
This one checks if there is an even number of x (and at least two):
/^(y*xy*x)+y*$/
And this one checks if there is an odd number of y (and at least one):
/^(x*yx*y)*x*yx*$/
Both will match only strings exclusively formed of x an y.
Upvotes: 1