Reputation: 2852
Regex is great, but I can't for the life of me figure out how I'd express the following constraint, without spelling out the whole permutation:
2 of any digit [0-9]
3 of any other digit [0-9] excluding the above
4 of any third digit [0-9] excluding the above
I've got this monster, which is clearly not a good way of doing this, as it grows exponentially with each additional set of digits:
^(001112222|001113333|001114444|001115555|001116666|0001117777|0001118888|0001119999|0002220000|...)$
OR
^(0{2}1{3}2{4}|0{2}1{3}3{4}|0{2}1{3}4{4}|0{2}1{3}5{4}|0{2}1{3}6{4}|0{2}1{3}7{4}|0{2}1{3}8{4}|...)$
Upvotes: 2
Views: 52
Reputation: 174465
Depending on whether your target environment/framework/language supports lookaheads, you could do something like:
^(\d)\1(?!\1)(\d)\2\2(?!\1|\2)(\d)\3\3\3$
First capture group ((\d)
) allows us to enforce the "two identical consecutive digits" by referencing the capture value (\1
) as the next match, after which the negative lookahead ensures the next sequence doesn't start with the previous digit - then we just repeat this pattern twice
Note: If you want to exclude only the digit used in the immediately preceding sequence, change (?!\1|\2)
to just (?!\2)
Upvotes: 2
Reputation: 75840
Looks like the following will work:
^((\d)\2(?!.+\2)){2}\2(\d)\3{3}$
It may look a bit tricky, using recursive patterns, but it may look more intimidating then it really is. See the online demo.
^
- Start string anchor.(
- Open 1st capture group:
(\d)
- A 2nd capture group that does capture a single digit ranging from 0-9.\2
- A backreference to what is captured in this 2nd group.(?!.+\2)
- Negative lookahead to prevent 1+ characters followed by a backreference to the 2nd group's match.){2}
- Close the 1st capture group and match this two times.\2
- A backreference to what is most recently captured in the 2nd capture group.(\d)
- A 3rd capture group holding a single digit.\3{3}
- Exactly three backreferences to the 3rd capture group's match.$
- End string anchor.EDIT:
Looking at your alternations it looks like you are also allowing numbers like "002220000" as long as the digits in each sequence are different to the previous sequence of digits. If that is the case you can simplify the above to:
^((\d)\2(?!.\2)){2}\2(\d)\3{3}$
With the main difference is the "+" modifier been taken out of the pattern to allow the use of the same number further on.
See the demo
Upvotes: 3