tags:

views:

116

answers:

5

hi, how can i check for a pattern occuring a certain number of times?

eg:

4444444 => return 4

4444332 => return 4

4444431 => return 4

4443333 => return 0

4243424 => return ?

but if character 4 occurs less than 4 times then return 0

i am just looking for 4 here. if it appears more than or equal to 4 times then value returned would be 4. the other 3 numbers in the string can range from 1 to 3 only.

thank you.

+1  A: 

To check for 4 consecutive same digits between 1 to 4 you can use the regex:

([1-4])\1{3}
codaddict
+1  A: 

If you need four consecutive 4s, it's just 4{4} or 4444. If they don't need to be consecutive, 4.*4.*4.*4 will do it. If it can be any number, but has to be four times, then ([1-4])\1{3} or ([1-4]).*\1.*\1.*\1 depending on whether you need them to be consecutive or not.

Charles
Pattern.matches("4.*4.*4.*4.*[1-4]", inputString) this worked! thanks :)
jillika iyer
but strangely does not work for 4443334
jillika iyer
That should be `Pattern.matches("4.*4.*4.*4", inputString)` or `Pattern.matches("([1-4]).*\1.*\1.*\1", inputString)`.
Charles
Now this one has catastrophic backtracking. Don't abuse the `.*` like this. Be more specific whenever you can (such as in this case).
polygenelubricants
A: 

Then, to count the patterns:

public static void main(String[] args)
{
    String input = "44444123444441234444";
    Pattern pattern = Pattern.compile("4444");
    Matcher matcher = pattern.matcher(input);
    int count = 0;
    int lookupPosition = 0;

    while (matcher.find(lookupPosition))
    {
        count++;
        lookupPosition = matcher.start() + 1;
    }

    System.out.println(count);
}
gawi
Well... this is not correct as find does not expect the pattern too start at the specified position. Not that easy.
gawi
Code is OK now.
gawi
I read the question too fast. You are not asking to count the pattern but merely detect it and return the character that was repeated, right? Was should "1111222233334444" returns then? 1? 1234? Your question needs work.
gawi
lenght of the string is just 7.I just want to find the pattern for repeated number of 4's
jillika iyer
Ok then it's: String input = "44414111"; if (input.matches(".*4.?4.?4.?4.*")) { System.out.println("4"); } else { System.out.println("0"); }
gawi
+2  A: 

It looks like ^[1-3]*4[1-3]*4[1-3]*4[1-3]*4[1-4]*$ is what you basically need.

Match the '4' 4 times surrounded by numbers from 1-3. The last case basically says, after 4 is matched 4 times, there can be any numbers 1-4 till the end of the string. This works for the patterns you suggested above. The problem with the above expression is that if there is a failure, and your string is long (>100 chars), then you could have what is known as Catastrophic Backtracking (see comments below...). To avoid that, you will need possessive matchers, or the more commonly supported independent sub-expressions. That will look like (note, you could also do this with possessive matchers *+ etc):

^(?>[1-3]*)4(?>[1-3]*)4(?>[1-3]*)4(?>[1-3]*)4(?>[1-4]*)$
Java Drinker
"Greedy" is the default behavior for quantifiers; adding a `+` (`*+`, `++`, etc.) makes them *possessive*. But catastrophic backtracking is not an issue here because there's no overlap in the "territories" covered by different quantifiers. For example, the first `[1-3]*` will never try to match the same characters as the second `[1-3]*` because there has to be a `4` between them. If you had used `[0-9]*` or `.*` instead of `[1-3]*`, you could have had a problem.
Alan Moore
Of course, there's no *harm* in using possessive quantifiers or atomic groups, and they do make the regex more efficient because it doesn't have to save the state information that would make backtracking possible.
Alan Moore
Ah yes, possessive is the word I was looking for. And you're right, in this case there is no "catastrophic" backtracking, only needless backtracking in case of errors. A very long string with a 'bad' char towards the end will take many more steps. I admit it may have been a bit misleading on my part. Thanks for the informative comment!
Java Drinker
A: 

You can use the pattern "(4[^4]*){4}"

  List<String> inputs = Arrays.asList("4444444", "4444332", "4443333", 
      "4243424", "4444431");
  Pattern pattern = Pattern.compile("(4[^4]*){4}");
  for(String input: inputs) {
    Matcher matcher = pattern.matcher(input);
    System.out.printf("Min 4 fours in '%s'? %b\n", input, matcher.find());
  }

Output:

Min 4 fours in '4444444'? true
Min 4 fours in '4444332'? true
Min 4 fours in '4443333'? false
Min 4 fours in '4243424'? true
Min 4 fours in '4444431'? true
Marimuthu Madasamy