Want to find valid 10-digit number with the following points.
- a 10-digit integer number
- a number without special characters
- a number, where the first digit cannot be zero
- a number with the ten digits having one number occurring exactly twice or thrice, one or two digits appear zero times and the other digits appear exactly once.
First 3 points can be validated with (^[1-9])(\d{9}), simple regex.
Trying to find valid regex for last point (secondPattern).
Tried:
(?:\d{2}){2,3}
(?:\\d{2}){2,3} (\\?:\\d){0,2}
(?s)(\\d)(?=.*\\1){2,3}
But could not find out. any help here.
private void validateNumber() {
var basePattern = Pattern.compile("(^[1-9])(\\d{9})");
var secondPattern = Pattern.compile("(?s)(\\\\d)(?=.*\\\\1){2,3}");
var result = getNumbers()
.stream()
.filter(num ->basePattern.matcher(num).matches() &&
secondPattern.matcher(num).matches()
).collect(Collectors.toList());
System.out.println(result);
}
private List<String> getNumbers() {
return List.of(
"1134567890",
"2123456789",
"1234267890",
"1671812342",
"1934466892:6",
"1234@56789",
"3563893124",
"4412356789",
"2349780915",
"981651321182234556",
"1234567890",
"10000000000",
"02346ex789",
"0000 000",
"0234567 894",
"8232527884",
"02325278847",
"02345678945",
"2323456789",
"8152228374",
"0234527834",
"8183746528",
"0435465768",
"3245657689"
//etc
);
}
and welcome any other solutions. Thanks in advance.
CodePudding user response:
Don't try to detect this with a regex. It's hard to do that because the digits meeting the various requirements can appear anywhere in the string.
Do it by counting the number of occurrences of each digits, then check the conditions:
if (input.length() != 10) {
return false;
}
// a number, where the first digit cannot be zero
if (input.startsWith("0")) {
return false;
}
int[] counts = new int[10];
for (int i = 0; i < input.length(); i) {
char c = input.charAt(i);
if (c < '0' || c > '9') {
// Not a number.
return false;
}
counts[c - '0'] ;
}
// Now check your requirements:
// having one number occurring exactly twice or thrice
if (IntStream.of(counts).filter(c -> c == 2 || c == 3).count() != 1) {
return false;
}
// one or two digits appear zero times
long zeros = IntStream.of(counts).filter(c -> c == 0).count();
if (zeros != 1 && zeros != 2) {
return false;
}
// and the other digits appear exactly once.
return IntStream.of(counts).filter(c -> c != 2 && c != 3 && c != 0).allMatch(c -> c == 1);