For example, I have a string:
R-G-B-G
I want to know is this string contains at least 2 'G', 1 'R' and 1 'B'.
String can change it size from 1 to 11 symbols, letters can appear at random position separated by '-'.
3 'R' -> R-R-G-R-R-B -> match
2 'B' -> ... -> not match
1 'R' 1 'G' 1 'B' -> ... -> match
Edit:
Moving forward i need to check some more cases.
My strings consist of Sockets, Links and Colors, ex:
R R-R B-R-R has 6 Sockets, one 2-link, one 3-link, 5R, 1B and 0G colors.
User sends me a number of sockets, length of the link, and desired colors in that link, and i must tell if it has all that or not. I've built expressions to match each individual case, but i cant figure out how to put them together.
6 sockets, Link with size 2, 2 R colors
All of that combined must return true because R R-R B-R-R, on the other hand, string: R R R B-R-R must be false because 2 R link is part of a 3 link B-R-R.
Or should i just run 3 separate expressions with output of previous sent as an input to the next.
You can chain look-aheads (?=...) after the start ^ for each required letter.
F.e. for at least two 'R' and two 'G' and one 'B'.
And for a string that's 1 to 11 long.
^(?=(?:.*?R){2})(?=(?:.*?G){2})(?=(?:.*?B){1}).{1,11}$
Test here on regex101
Note that the lazy searches *? used in those look-aheads is just a speed optimalization.
It won't matter much in this case, since it's such a short string.
Related
I need to create a regex to validate a password and then create a DFA with it.
The sets are:
a = {a,...,z}
| A = {A,...,Z}
| d = {0,...,9}
The criteria are:
Must begin with a letter (doesn't matter if upper or lower case).
| Must contain at least 1 upper case.
| Must contain at least 1 lower case.
| Must contain at least 1 number.
So far, I've come with the following Regex:
(aa\*(AA\*a\*dd\*|dd\*a\*AA\*)|AA\*(aa\*A\*dd\*|dd\*A\*aa\*))(a|A|d)\*
Is it correct?
The inner parts of your expression are slightly wrong. For example, with AA*a*dd*, you trying to check the case where it begins with 'a' and then 'A' occurs before 'd', but this does not match "aAaAd". Here is a correct version:
(aa*(d(a|d)*A|A(a|A)*d)|AA*(d(A|d)*a|a(A|a)*d))(a|A|d)*
The DFA you should do as an exercise. It should have 7 states including start and end. Think about establishing one state for each combination of characters that you have left to match.
I need to grab the 2 character letter and numbers after that:
What I want is:
AB 12 CD-12345-67 -> CD-12345
AB12 CD 12345-67 -> CD 12345
AB-12CD12345-6 -> CD12345
ABC1234556 -> no match, as I look for 2 character letter and numbers after that.
ABC-1234556 -> no match, as I look for 2 character letter and numbers after that.
A1-BC-12D345-56 -> no match, after 2 characters letter, numbers must come
I used this regex
[A-Z]{2}[ |\-]?\d+
Which grabs CD-12345 and AB 12, in the first example. I just need CD-12345. Also it grabs BC1234556,BC-1234556, BC-12 in the last three example which i don't want.
Sometimes, space,no space or - character placed between numbers and letters block.
Thank you very much.
based on what you posted
^.*(?<![A-Z])([A-Z]{2}[- ]?\d++)(?![A-Z])
Demo
I am developing an application with MVC 4, razor. For one change Password view I need to do some validation which has following conditions:
It should match at least 3 of the following:
1. Upper case alphabetic characters
2. Lower case alphabetic characters
3. Numbers
4. Special keyboard characters (except script tags)
Now, I have written following regular expression in my model
[RegularExpression("^([a-zA-Z0-9#$%=#!{},`~&*()'?.:;_|^/+\"-]{8,32})$", ErrorMessage = "Current Password is invalid")]
but, this will match any of the given subsets. I need to match atleast 3 of them. Can anybody please help me how do I do that?
It might not be a good idea to use regex for password validation, but using lookaheads and the or operator | allows you to do this:
^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])|(?=.*[#$%=#!{},`~&*()'?.:;_|^/+\"-])(?=.*[a-z])(?=.*[0-9])|(?=.*[A-Z])(?=.*[#$%=#!{},`~&*()'?.:;_|^/+\"-])(?=.*[0-9])|(?=.*[A-Z])(?=.*[a-z])(?=.*[#$%=#!{},`~&*()'?.:;_|^/+\"-])).{8,32}$
There are 4 parts in this regex:
(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])
Makes sure there's at least 1 lower alpha, 1 upper alpha and 1 number.
(?=.*[#$%=#!{},`~&*()'?.:;_|^/+\"-])(?=.*[a-z])(?=.*[0-9])
Makes sure there's at least 1 special character, 1 upper alpha and 1 number.
(?=.*[A-Z])(?=.*[#$%=#!{},`~&*()'?.:;_|^/+\"-])(?=.*[0-9])
Makes sure there's at least 1 upper alpha, 1 special character and 1 number.
(?=.*[A-Z])(?=.*[a-z])(?=.*[#$%=#!{},`~&*()'?.:;_|^/+\"-])
Makes sure there's at least 1 upper alpha, 1 lower alpha and 1 special character.
And using | with those four (grouped into a non-capturing group) gives you the 3 out of 4 validation.
Then use .{8,32} for the length of the password
Better explained with examples:
HHH
HHHH
HHHBBHHH
HHHBH
BB
HHBH
I need to come up with a regexp that matches only 3 H's or a multiple of 3 H's (so 6, 9, 12, ... H's are ok as well) and 5 H's are not ok. And if possible I don't want to use Perl regexps.
So for the input above the regexp would match (1), (3) and (6) only.
I'm just starting with regular expressions here so I don't exactly know how I'm supposed to approach this.
edit
Just to clear something up:, an H can only be in one group of 3 H's. The group of 3 H's might be HHH or HHBH.
That's why in example 2 above it is not a match because the last H is not in a group of 3 H's. And you can't take the last 3 H's in a group because the middle 2 H's have already been inside a group before.
You can use the following regular expression:
^([^H]*H[^H]*H[^H]*H[^H]*)+$
It matches any string which contains in total 3 H or any multiple of 3. In between there might be any other character.
Explanation:
^ begin of string
( start of group
[^H]*H any string of characters (or none) not including 'H' plus a single 'H'
[^H]*H any string of characters (or none) not including 'H' plus a single 'H'
[^H]*H any string of characters (or none) not including 'H' plus a single 'H'
[^H]* any string of characters (or none) which is not 'H'
)+ containing the group once or twice or ...
$ end of string
By repeating the subpattern [^H]*H three times we make sure that there are indeed 3 H included, [^H]* allows any separating characters.
Note: use either egrep or run grep with additional argument -E.
Use this to match a multiple of 3 H's:
(H{3})+
Here is a complete regex for your examples:
^(H{3})+B*(H{3})*$
Edit: It looks like you need to count non-consecutive H's. In that case:
^(([^H]*H){3})+[^H]*$
That should match any string with a multiple of 3 H's.
Given the requirement that H's can be arbitrarily interleaved with non-H's, but that the total number of H's must be a non-zero multiple of 3 (so XXX, containing no H's, is not a match), then the total regular expression is anything but trivial. This is not a beginner's regular expression.
I'm going to assume that the dialect of regular expression treats {} and () as metacharacters for counting and grouping, and includes + for one-or-more. If you're using a regular expression system that has a different requirement (\{\}, for example) then adjust accordingly.
You need the regex to match the whole string, so there are no stray H's allowed. So, it must start with ^ and end with $. You need to allow an arbitrary number of non-H's at front and back. The H's may be separated by an arbitrary number of non-H's. That leads to:
^([^H]*H[^H]*H[^H]*H)+[^H]*$
Ouch; that is hard to read! It says the line must consist of 1 or more (+) groups of an arbitrary number of non-H's followed by an H, an arbitrary number of non-H's, another H, an arbitrary number of non-H's and a third H; all of which can be followed by an arbitrary number of non-H's.
Using the {} for counting:
^(([^H]*H){3})+[^H]*$
That's still hard to read. Note that my description said "arbitrary number of non-H's at front and back", but I only use the [^H]* at the back; that's because the repeating pattern allows an arbitrary number of non-H's at the front anyway so there's no need to repeat that fragment.
How do I construct strings with exactly one occurrence of 111 from a set E* consisting of all possible combinations of elements in the set {0,1}?
You can generate the set of strings based on following steps:
Some chucks of numbers and their legal position are enumerated:
Start: 110
Must have one, anywhere: 111
Anywhere: 0, 010, 0110
End: 011
Depend on the length of target string (the length should be bigger than 3)
Condition 1: Length = 3 : {111}
Condition 2: 6 > Length > 3 : (Length-3) = 1x + 3y + 4z
For example, if length is 5: answer is (2,1,0) and (1,0,1)
(2,1,0) -> two '0' and one '010' -> ^0^010^ or ^010^0^ (111 can be placed in any one place marked as ^)
(1,0,1) -> one '0' and one '0110' ...
Condition 3: If 9 > Length > 6, you should consider the solution of two formulas:
Comments:
length – 3 : the length exclude 111
x: the times 0 occurred
y: the times 010 occurred
z: the times 0110 occurred
Finding all solutions {(x,y,z) | 1x + 3y + 4z = (Length - 3)} ----(1)
For each solution, you can generate one or more qualified string. For example, if you want to generate strings of length 10. One solution of (x,y,z) is (0,2,1), that means '010' should occurred twice and '0110' should occurred once. Based on this solution, the following strings can be generated:
0: x0 times
010: x 2 times
0110: x1 times
111: x1 times (must have)
Finding the permutations of elements above.
010-0110-010-111 or 111-010-010-0110 …
(Length - 6) = 1x + 3y + 4z ---(2)
Similar as above case, find all permutations to form an intermediate string.
Finally, for each intermediate string Istr, Istr + 011 or 110 + Istr are both qualified.
For example, (10-6) = 1*0 + 3*0 + 4*1 or = 1*1 + 3*1 + 4*0
The intermediate string can be composed by one '0110' for answer(0,0,1):
Then ^0110^011 and 110^0110^ are qualified strings (111 can be placed in any one place marked as ^)
Or the intermediate string can also be composed by one '0' and one '010' for answer (1,1,0)
The intermediate string can be 0 010 or 010 0
Then ^0010^011 and 110^0100^ are qualified strings (111 can be placed in any one place marked as ^)
Condition 4: If Length > 9, an addition formula should be consider:
(Length – 9) = 1x + 3y + 4z
Similar as above case, find all permutations to form an intermediate string.
Finally, for each intermediate string Istr, 110 + Istr + 011 is qualified.
Explaination:
The logic I use is based on Combinatorial Mathematics. A target string is viewed as a combination of one or more substrings. To fulfill the constraint ('111' appears exactly one time in target string), we should set criteria on substrings. '111' is definitely one substring, and it can only be used one time. Other substrings should prevent to violate the '111'-one-time constraint and also general enough to generate all possible target string.
Except the only-one-111, other substrings should not have more than two adjacent '1'. (Because if other substring have more than two adjacent 1, such as '111', '1111', '11111,' the substring will contain unnecessary '111'). Except the only-one-111, other substrings should not have more than two consecutive '1'. Because if other substring have more than two consecutive 1, such as '111', '1111', '11111,' the substring will contain unnecessary '111' . However, substrings '1' and '11' cannot ensure the only-one-111 constraint. For example, '1'+'11,' '11'+'11' or '1'+'1'+'1' all contain unnecessary '111'. To prevent unnecessary '111,' we should add '0' to stop more adjacent '1'. That results in three qualified substring '0', '010' and '0110'. Any combined string made from three qualified substring will contain zero times of '111'.
Above three qualified substring can be placeed anywhere in the target string, since they 100% ensure no additional '111' in target string.
If the substring's position is in the start or end, they can use only one '0' to prevent '111'.
In start:
10xxxxxxxxxxxxxxxxxxxxxxxxxxxx
110xxxxxxxxxxxxxxxxxxxxxxxxxxx
In end:
xxxxxxxxxxxxxxxxxxxxxxxxxxx011
xxxxxxxxxxxxxxxxxxxxxxxxxxxx01
These two cases can also ensure no additional '111'.
Based on logics mentioned above. We can generate any length of target string with exactly one '111'.
Your question could be clearer.
For one thing, does "1111" contain one occurrence of "111" or two?
If so, you want all strings that contain "111" but do not contain either "1111" or "111.*111". If not, omit the test for "1111".
If I understand you correctly, you're trying to construct an infinite subset of the infinite set of sequences of 0s and 1s. How you do that is probably going to depend on the language you're using (most languages don't have a way of representing infinite sets).
My best guess is that you want to generate a sequence of all sequences of 0s and 1s (which shouldn't be too hard) and select the ones that meet your criteria.