开发者

Regex to match all permutations of {1,2,3,4} without repetition

开发者 https://www.devze.com 2023-01-04 06:23 出处:网络
I am implementing the following problem in ruby. Here\'s the pattern that I want : 1234, 1324, 1432, 1423, 2341 and so on

I am implementing the following problem in ruby.

Here's the pattern that I want :

1234, 1324, 1432, 1423, 2341 and so on

i.e. the digits in the four digit number should be between [1-4] and should also be non-repetitive.

to make you understand in a simple manner I take a two digit pattern and the solutio开发者_如何学Cn should be : 12, 21

i.e. the digits should be either 1 or 2 and should be non-repetitive.

To make sure that they are non-repetitive I want to use $1 for the condition for my second digit but its not working.

Please help me out and thanks in advance.


You can use this (see on rubular.com):

^(?=[1-4]{4}$)(?!.*(.).*\1).*$

The first assertion ensures that it's ^[1-4]{4}$, the second assertion is a negative lookahead that ensures that you can't match .*(.).*\1, i.e. a repeated character. The first assertion is "cheaper", so you want to do that first.

References

  • regular-expressions.info/Lookarounds and Backreferences

Related questions

  • How does the regular expression (?<=#)[^#]+(?=#) work?


Just for a giggle, here's another option:

^(?:1()|2()|3()|4()){4}\1\2\3\4$

As each unique character is consumed, the capturing group following it captures an empty string. The backreferences also try to match empty strings, so if one of them doesn't succeed, it can only mean the associated group didn't participate in the match. And that will only happen if string contains at least one duplicate.

This behavior of empty capturing groups and backreferences is not officially supported in any regex flavor, so caveat emptor. But it works in most of them, including Ruby.


I think this solution is a bit simpler

^(?:([1-4])(?!.*\1)){4}$

See it here on Rubular

^                  # matches the start of the string
    (?:            # open a non capturing group 
        ([1-4])    # The characters that are allowed the found char is captured in group 1
        (?!.*\1)   # That character is matched only if it does not occur once more
    ){4}           # Defines the amount of characters
$

(?!.*\1) is a lookahead assertion, to ensure the character is not repeated.

^ and $ are anchors to match the start and the end of the string.


While the previous answers solve the problem, they aren't as generic as they could be, and don't allow for repetitions in the initial string. For example, {a,a,b,b,c,c}. After asking a similar question on Perl Monks, the following solution was given by Eily:

^(?:(?!\1)a()|(?!\2)a()|(?!\3)b()|(?!\4)b()|(?!\5)c()|(?!\6)c()){6}$

Similarly, this works for longer "symbols" in a string, and for variable length symbols too.

0

精彩评论

暂无评论...
验证码 换一张
取 消