D.R.
D.R.

Reputation: 1219

Regex to check for a repeating digit

I have a Java application where users must specify a PIN to log in. When creating the PIN, there are only 3 requirements:

I have tried:

\\d*(\\d)\\1{3}\\d*

but I believe the \1 is looking at the initial match to the \d* not the second match of (\d).


Answer used: I have updated to using:

\\d{6}
(0123|1234|2345|3456|4567|5678|6789|9876|8765|7654|6543|5432|4321|3210)
\\d*?(\\d)\\1{2,}\\d*

To satisfy the initially stated requirements plus a few I hadn't thought of! Thanks for all the help

Upvotes: 4

Views: 15792

Answers (5)

Alan Moore
Alan Moore

Reputation: 75222

It looks like you're doing three separate regex matches, presumably negating the result of the second and third ones. In that case, this should do the trick:

pinString.matches("^\\d{6}$")

!pinString.matches("^.*?(?:0123|1234|2345|3456|4567|5678|6789).*$")

!pinString.matches("^.*?(\\d)\\1{2}.*$")

With the matches() method you don't really need the anchors (^ and $), but they don't hurt and they make your intentions more obvious. Also, the first regex ensures that all six characters are digits, so it's safe to use . instead of \\d as the space filler in the other two.

Upvotes: 1

Cris Stringfellow
Cris Stringfellow

Reputation: 3808

I would :

  1. Check length == 6
  2. Check \d+
  3. Frequency count each digit:

int[] f = new int[10];
int pow10 = 1;
int npow10 = 10;
int nmod = 0, nmod2 = n % 10;
while(i < 6) do
  int iDigit = (nmod2 - nmod)/pow10
  if(++f[iDigit] > 2)
    return false;
  pow10 = npow10;
  npow10 *= 10;
  nmod = nmod2;
  nmod2 = n % npow10;
  i++;
end
return true;

Upvotes: 1

Dave
Dave

Reputation: 5173

Well your examples and your text do not match. You say it cannot repeat more than 3 times. 000 is a repeat of exactly 3 times so it should be OK, but 0000 is a repeat of 4 which is more than 3 so it should not. To match your text requirement, your regex should be

.*(\d)\1{3}.*

Which in a Java string should be

".*(\\d)\\1{3}.*"

This is similar to what you have, so maybe you're just misunderstanding the wording.

Note: I like this to test my regex in Java: http://www.regexplanet.com/simple/index.html

Upvotes: 0

Matthias
Matthias

Reputation: 12259

Do you want to block three repeating following numbers or just more than three numbers in general (such as in "112213")?

If the latter one is the case, Regex might not be the best solution to a problem:

public static boolean validate(String pin){
    if (pin == null || pin.length() != 6)
        return false;

    int[] count = new int[10];
    for (int i = 0; i < pin.length(); i++) {
        char c = pin.charAt(i);
        if(!Character.isDigit(c))
            return false;

        if (++count[c - '0'] > 3)
            return false;
    }

    return true;
}

Upvotes: 4

Rohaq
Rohaq

Reputation: 2046

Your regex is slightly off, since the first \d will match the first number. You only want to match 2 more after that.

\\d*(\\d)\\1{2}\\d*

should do the trick.

Quick edit: If you want to match 2 or more numbers in sequence, just add a comma to your count, without specifying a maximum number:

\\d*(\\d)\\1{2,}\\d*

Or at least, this works in Perl. Let us know how you go.

Upvotes: 9

Related Questions