Reputation: 1219
I have a Java application where users must specify a PIN to log in. When creating the PIN, there are only 3 requirements:
Must be 6 digits:
\\d{6}
Must not have 4 or more sequential numbers:
\\d*(0123|1234|2345|3456|4567|5678|6789)\\d*
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)
.
\\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
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
Reputation: 3808
I would :
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
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
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
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