import java.util.*;
import java.util.regex.*;
import java.util.stream.*;

public class Matcher
{
    public Matcher (Rule[] rules, boolean debug)
    {
        _rules = rules;
        _debug = debug;
    }

    public long numberOfMatchingMessages (int ruleNumber, Message[] messages)
    {
        Pattern p = Pattern.compile(getRuleRegex(ruleNumber));
        Vector<String> messageContent = new Vector<String>();

        for (int i = 0; i < messages.length; i++)
            messageContent.add(messages[i].getContent());

        return 0;
    }

    public String expandRule (int ruleNumber)
    {
        Rule ruleToMatch = _rules[ruleNumber];
        String str = "";

        if (_debug)
            System.out.println("Looking at rule "+ruleToMatch);

        if (ruleToMatch.isCharacterRule())
            str = ""+ruleToMatch.getMatch();
        else
        {
            int[] leftRules = ruleToMatch.leftRules();

            str += " ( ";

            for (int i = 0; i < leftRules.length; i++)
            {
                str += expandRule(leftRules[i]);
            }

            int[] rightRules = ruleToMatch.rightRules();

            if (rightRules != null)
            {
                str += " | ";

                for (int j = 0; j < rightRules.length; j++)
                {
                    str += expandRule(rightRules[j]);
                }
            }

            str += " ) ";
        }

        return str;
    }

    private final String getRuleRegex (int ruleNumber)
    {
        Rule theRule = _rules[ruleNumber];

        if (theRule.isCharacterRule())
            return ""+theRule.getMatch();
        else
        {
            if (!theRule.hasOrRule())
                return String.format("(?:%s)", ruleListToRegex(theRule.leftRules()));
            else
                return String.format("(?:%s|%s)", ruleListToRegex(theRule.leftRules()), ruleListToRegex(theRule.rightRules()));
        }
    }

    private final String ruleListToRegex (int[] rules)
    {
        Vector<Integer> v = new Vector<Integer>();  // convert to stream for this bit

        for (int i = 0; i < rules.length; i++)
            v.add(rules[i]);

        return v.stream().map(this::getRuleRegex).collect(Collectors.joining());
    }

    private Rule[] _rules;
    private boolean _debug;
}
@@ -288,71 +288,8 @@
   %7B%0A
-        Pattern p = Pattern.compile(getRuleRegex(ruleNumber));%0A
     
@@ -468,16 +468,524 @@
     
-return 0
+String rule42Regex = getRegexForRule(42);%0A        String rule31Regex = getRegexForRule(31);%0A        String overallRegex = String.format(%22(%25s+)(%25s+)%22, rule42Regex, rule31Regex);%0A%0A        Pattern rule42Pattern = Pattern.compile(rule42Regex);%0A        Pattern rule31Pattern = Pattern.compile(rule31Regex);%0A        Pattern fullPattern = Pattern.compile(overallRegex);%0A%0A        return messageContent.stream()%0A                .filter(s -%3E matchesRules(s, fullPattern, rule42Pattern, rule31Pattern))%0A                .count()
 ;%0A  
@@ -1916,27 +1916,611 @@
 nal 
-String getRuleRegex
+boolean matchesRules (String message, Pattern pattern, Pattern patternOne, Pattern patternTwo)%0A    %7B%0A        java.util.regex.Matcher m = pattern.matcher(message);%0A%0A        if (m.matches())%0A            return numberOfMatches(patternOne, m.group(1)) %3E numberOfMatches(patternTwo, m.group(2));%0A        %0A        return false;%0A    %7D%0A%0A    private int numberOfMatches (Pattern pattern, String toMatch)%0A    %7B%0A        int count = 0;%0A        java.util.regex.Matcher m = pattern.matcher(toMatch);%0A%0A        while (m.find())%0A            count++;%0A%0A        return count;%0A    %7D%0A%0A    private final String getRegexForRule
  (in
@@ -3242,16 +3242,19 @@
 getR
-uleR
 egex
+ForRule
 ).co

Update Matcher.java