tags:

views:

70

answers:

1

I want to create a regex, where the occurence of one group, depends on whether or not another certain group has been found. I think this is easier to illustrate with an example!

I want to allow two patterns, illustrated by these two examples: JsJh, JJ. This is not allowed: JsJs, JsJ, JQ.

So if the user types one small letter after the first capital one, the regex expects another small letter after the second capital - but it should not be the same letter as the first one!

I match the first (Js) like this: ([123456789TJQKA]){1}([dsch]?){1} The second capital letter is matched by (\\2).

Now, I cannot seem to find a solution for the last small letter. I can get the small letters to match (which is obv. not what I want), but how do I, if its present, exclude the first letter from the last group, by still allowing (and expecting) one of the three remaining small letters?

+1  A: 

Why are you using regular expressions to implement the logic of a card game? Seems pretty crazy... nevertheless it can be done!

s.matches("([123456789TJQKA])([dchs])\\1(?!\\2)[dchs]|([123456789TJQKA])\\3")

Here is a test to verify that it works correctly (and it also documents my assumptions about the special cases that you haven't covered in your question):

public class Test
{
    private static void test(String input, boolean expected)
    {
        boolean result = input.matches("([123456789TJQKA])([dchs])\\1(?!\\2)[dchs]|([123456789TJQKA])\\3");
        if (result != expected)
            throw new RuntimeException("Failed!");
    }

    public static void main(String[] args) throws Exception
    {
        test("JJ", true);
        test("JsJd", true);
        test("11", true);
        test("2c2h", true);

        test("Js", false);
        test("JsJs", false);
        test("JsJ", false);
        test("JQ", false);
        test("1d1d", false);
        test("J", false);
        test("", false);
        test("3d3d", false);
        test("JsJdJ", false);
        test("JsJdJh", false);
        test("1A", false);
    }
}
Mark Byers
The regex is just for parsing hand-ranges. So the user can type in eg. {A2s+, JJ+, 88, AKo, TsTh} as the distribution of hands his opponent might have. Your suggestion works wonders! Now I just need to find out what actually happens.
Frederik Wordenskjold
@Frederik, Just a few minor points: I managed to miss the T - oops! It's added now. Also as Anon. points out you can shorten 123456789 to 1-9.
Mark Byers
Many thanks! I'm still wondering what the **** is going on though. This line: (?!\\2)[dchs]|([123456789TJQKA])\\3, what does it say? I cannot find anything about the '?!'-syntax anywhere. Maybe you have a good java regex reference? I cannot find many good resources. Sun's own seems... Not too comprehensive?
Frederik Wordenskjold
The (?! ... ) is a negative lookahead. See here: http://www.regular-expressions.info/lookaround.html
Mark Byers