This will surprise some. I am using regular expressions for my solution, but the other way around than in the question.
The input string with the %
sign in it is my regex. The percent sign is a wildcard (as in SQL, as you say). So I am going to match the known correct strings against the string with the wildcard. Correct strings include the empty string, AAAAAA33
and AAAAAA33AAA
.
Stop, you’re thinking, that won’t work for a couple of reasons. First the letters may be any letters in the English alphabet, not just capital A. And the digits are not only 3. Right you are, so we will have to substitute those. So I am going to change your input string AABB
to AAAA
, etc.
input.replaceAll("[a-zA-Z]", "A")
We also need to substitute the digits in the same way
replaceAll("[0-9]", "3")
We need to take a bit care with the two alphanumeric characters in the middle. If they are alphabetic in the input, they will still not match the 3
in the correct strings I gave above. Fortunately they are just two, so we can handle this be using more correct model strings. To cover all three cases from the question I am using 9 strings:
static final String[] correctModels = {
"", "AAAAAAAA", "AAAAAAA3", "AAAAAA3A", "AAAAAA33",
"AAAAAAAAAAA", "AAAAAAA3AAA", "AAAAAA3AAAA", "AAAAAA33AAA"
};
Now, if after substituting letters to A and digits to 3 one of these model strings matches the input, the input is correct.
Next, Java regex doesn’t recognize %
as a wildcard. So change to .*
(the regex pattern for any sequence including the empty sequence):
replaceAll("%", ".*")
We might have used [a-zA-Z0-9]*
, but since we have full control over the model strings, we don’t need to.
That’s it, we’re set. No wait, the user can fool us by putting valid regex syntax in the input string. Solution: First thing, check that the input only contains letters, digits and percent signs. This solves it because none of these has any special meaning in regex.
public static boolean matches(String input) {
// if input contains other chars than letter digits and percent, reject it
if (! input.matches("[a-zA-Z0-9%]*")) {
return false;
}
input = input.replaceAll("[a-zA-Z]", "A")
.replaceAll("[0-9]", "3")
.replaceAll("%", ".*");
Pattern p = Pattern.compile(input);
for (String model : correctModels) {
if (p.matcher(model).matches()) {
return true;
}
}
return false;
}
I have tested with all the examples in the question. They work as specified. I believe the solution is correct for all possible input.