1

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.

5
  • 5
    That could have been clearer... Are you only looking for four or more fours? What if there's four threes? If so, what would be the answer, 4 or 3? What if you have both four threes and four fours (or is the string always 7 characters)? What if the fours are not at the beginning of the string? Can you have two fours, then something else, then two more fours? Commented Aug 25, 2010 at 16:39
  • As Amadan says, the question is unclear, and the title is far too generic - please correct these. Commented Aug 25, 2010 at 16:42
  • thank you. i edited the post above. sorry for the confusion Commented Aug 25, 2010 at 16:50
  • Ok, I've added a couple more examples to clarify, but can you confirm if 4343434 should return 4 or 0 ? Commented Aug 25, 2010 at 16:58
  • should return a 4. and it need not be consecutive 4 Commented Aug 25, 2010 at 17:56

5 Answers 5

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Pattern.matches("4.*4.*4.*4.*[1-4]", inputString) this worked! thanks :)
That should be Pattern.matches("4.*4.*4.*4", inputString) or Pattern.matches("([1-4]).*\1.*\1.*\1", inputString).
Now this one has catastrophic backtracking. Don't abuse the .* like this. Be more specific whenever you can (such as in this case).
Pattern.matches("([1-4]).*\1.*\1.*\1", inputString), been looking for this expression. will check it out
2

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

([1-4])\1{3}

Comments

2

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]*)$

3 Comments

"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.
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.
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!
0

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);
}

4 Comments

Well... this is not correct as find does not expect the pattern too start at the specified position. Not that easy.
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.
lenght of the string is just 7. I just want to find the pattern for repeated number of 4's
Ok then it's: String input = "44414111"; if (input.matches(".*4.?4.?4.?4.*")) { System.out.println("4"); } else { System.out.println("0"); }
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.