Reputation: 31
I was solving this question from Hackerrank
https://www.hackerrank.com/contests/find-google/challenges/find-google/problem
and came up with this pattern "^[gG][o0O()\[\]{}][o0O()\[\]{}][gG][lLI][eE3]" But this is giving wrong answer for test case g()()GI3. Can anyone tell me the error? Also tell me if there is more efficient expression for this.
import java.util.regex.*;
import java.io.*;
import java.util.*;
class Main {
public static void main (String[] args) {
Scanner s = new Scanner(System.in);
String str = s.next();
Pattern pattern = Pattern.compile("^[gG][o0O()\\[\\]{}][o0O()\\[\\]{}][gG][lLI][eE3]",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
if(matcher.matches())
System.out.println("YES");
else System.out.println("NO");
}}
Upvotes: 1
Views: 203
Reputation: 264
I propose you this version of the regex string along with the code:
String string = bufferedReader.readLine();
String regex = "^[gG]([o0O]|\\(\\)|\\[\\]|\\{\\}|\\<\\>){2}[gG][lLI][eE3]";
String result = Pattern.matches(regex, string) ? "True" : "False";
System.out.println(result);
Since it's a "one shot" search you can use the static method "matches" of the Pattern class. That is, desume the result directly from a one-time match against your regex.
The regex is mostly the same as the one you devised, but some points are worth noting.
It is dangerous (if not erroneous) using case insensitivity when your regex tries to pick up letters of differente case. If you want to do the matching the classic way, avoid using the flag of case insensitivity. (in this particular case it would match a "google" written with a lower case "i" in place of a "L", which would lead to false positives).
Since there is only one way to express the "o", it is better to group its definition in a single sub-expression and then use the quantifier " {2} " to say that you exactly want two instances of that subexpression to match.
You want to find two occurrences of EITHER
Last but not least, if you are looking for simple, square, curly or angular braces, you must escape them because those are special characters in a regexp. Moreover, you must escape them the java way, using a double blackslash.
Here is the full code:
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String string = bufferedReader.readLine();
String regex = "^[gG]([o0O]|\\(\\)|\\[\\]|\\{\\}|\\<\\>){2}[gG][lLI][eE3]";
String result = Pattern.matches(regex, string) ? "True" : "False";
System.out.println(result);
bufferedReader.close();
}
It prints "True" when fed with the input "g()()GI3"
Upvotes: 0
Reputation: 626738
The problem with the current regex is that []
, ()
and <>
are put inside a character class that matches a single char inside it, but ()
, <>
and []
char sequences consist of 2 chars.
You need to use a grouping construct with an alternation operator here to match o
s.
You may use this pattern with Pattern.matches()
:
Pattern pattern = Pattern.compile("[gG](?:[oO0]|\(\)|\[]|<>){2}[gG][LlI][eE3]");
See the regex demo
Details
[gG]
- g
or G
(?:[oO0]|\(\)|\[]|<>){2}
- two occurrences of
[o0]
- o
, O
or 0
|
- or \(\)
- a ()
substring|
- or \[]
- a []
substring|
- or <>
- a <>
substring[gG]
- g
or G
[LlI]
- l
, L
or I
[eE3]
- e
, E
or 3
.Upvotes: 4
Reputation: 37755
You can use this
You do not need to add both uppercase and lowercase of a letter when you use case insensitive
flag.
g(?:o|0|<>|\[]){2}g[li][e3]
g
- Matches g
or G
( as case insensitive flag is on )(?:o|0|<>|\[])
- Matches o
or 0
or <>
or []
.[li]
- Matches L
or l
or I
or i
.[e3]
- Matches e
or E
or 3
Upvotes: 1