Regex для расчета прямой покерной руки - Использование ASCII-кода - PullRequest
4 голосов
/ 14 августа 2010

В другом вопросе я узнал, как рассчитать стрит-покер, используя регулярное выражение ( здесь ).

Теперь, из любопытства, возникает вопрос: Могу ли я использовать регулярные выражения для вычисления того же, используя ASCII-код?

Что-то вроде:

регулярное выражение: [C] [C + 1] [C + 2] [C + 3] [C + 4], являясь C КОДОМ ASCII (или подобным образом)

Совпадения: 45678, 23456

Не соответствует: 45679 или 23459 (не в последовательности)

Ответы [ 4 ]

5 голосов
/ 14 августа 2010

Ваша главная проблема на самом деле состоит в том, что вы не используете последовательные кодировки ASCII для своих рук, вы используете цифры для не-лицевых карт и непоследовательные неупорядоченные символы для лицевых карт.

В начале строк необходимо обнаружить 2345A, 23456, 34567, ..., 6789T, 789TJ, 89TJQ, 9TJQK и TJQKA.

Это , а не последовательных кодов ASCII, и, даже если бы они были, у вас возникли бы проблемы, поскольку оба значения A2345 и TJQKA действительны, и вы не получите A, поскольку оба меньше чем и больше, чем другие символы в том же наборе символов.

Если это имеет для регулярного выражения, то следующий сегмент регулярного выражения:

(2345A|23456|34567|45678|56789|6789T|789TJ|89TJQ|9TJQK|TJQKA)

, вероятно, самый простой и самый читаемый, который вы получите.

4 голосов
/ 17 августа 2010

Не существует регулярного выражения, которое будет выполнять то, что вы хотите, как указывали другие ответы, но вы сказали, что хотите выучить регулярное выражение, поэтому вот еще один подход мета-регулярного выражения, который может быть учебным.

Вот фрагмент кода Java, который, учитывая строку, программно генерирует шаблон, который будет соответствовать любой подстроке этой строки длины 5.

    String seq = "ABCDEFGHIJKLMNOP";
    System.out.printf("^(%s)$",
        seq.replaceAll(
            "(?=(.{5}).).",
            "$1|"
        )
    );

Вывод ( как виднона ideone.com ):

^(ABCDE|BCDEF|CDEFG|DEFGH|EFGHI|FGHIJ|GHIJK|HIJKL|IJKLM|JKLMN|KLMNO|LMNOP)$

Вы можете использовать это для удобного создания шаблона регулярного выражения для соответствия прямым покерным рукам, инициализируя seq в зависимости от ситуации.


Как это работает

. метасимвол соответствует «любому» символу (разделители строк могут быть исключением в зависимости от режима, в котором мы находимся).

The {5} является точным повторением спецификатором..{5} соответствует в точности 5 ..

(?=…) - положительный прогноз ;он утверждает, что данный шаблон может быть сопоставлен, но поскольку он является только утверждением, он фактически не выполняет (то есть потребляет) совпадение из входной строки.

Просто (…) является захватомгруппа .Он создает обратную ссылку, которую вы можете использовать, возможно, позже в шаблоне или в подстановках, или по своему усмотрению.

Шаблон повторяется здесь для удобства:

     match one char
        at a time
           |
(?=(.{5}).).
\_________/
 must be able to see 6 chars ahead
 (capture the first 5)

Шаблон работаетсопоставляя один символ . за раз.Однако, прежде чем этот символ будет сопоставлен, мы утверждаем (?=…), что мы можем увидеть всего 6 символов впереди (.{5})., захватив (…) в группу 1 первым .{5}.Для каждого такого совпадения мы заменяем $1|, то есть все, что было захвачено группой 1, с последующим метасимволом чередования.

Давайте рассмотрим, что произойдет, когда мы применим это к более короткому String seq = "ABCDEFG";. обозначает нашу текущую позицию.

=== INPUT ===                                    === OUTPUT ===

 A B C D E F G                                   ABCDE|BCDEFG
↑
We can assert (?=(.{5}).), matching ABCDEF
in the lookahead. ABCDE is captured.
We now match A, and replace with ABCDE|

 A B C D E F G                                   ABCDE|BCDEF|CDEFG
  ↑
We can assert (?=(.{5}).), matching BCDEFG
in the lookahead. BCDEF is captured.
We now match B, and replace with BCDEF|

 A B C D E F G                                   ABCDE|BCDEF|CDEFG
    ↑
Can't assert (?=(.{5}).), skip forward

 A B C D E F G                                   ABCDE|BCDEF|CDEFG
      ↑
Can't assert (?=(.{5}).), skip forward

 A B C D E F G                                   ABCDE|BCDEF|CDEFG
        ↑
Can't assert (?=(.{5}).), skip forward

       :
       :

 A B C D E F G                                   ABCDE|BCDEF|CDEFG
              ↑
Can't assert (?=(.{5}).), and we are at
the end of the string, so we're done.

Итак, мы получаем ABCDE|BCDEF|CDEFG, которые являются всеми подстроками длины 5 из seq.

Ссылки

3 голосов
/ 14 августа 2010

Что-то вроде regex: [C][C+1][C+2][C+3][C+4], являющееся C КОДОМ ASCII (или как это)

Вы не можете сделать что-либо близко к этому в большинстве ароматов регулярных выражений. Это просто не те шаблоны, для которых разработано регулярное выражение.

Не существует основного шаблона регулярных выражений, который бы кратко совпадал с любыми двумя последовательными символами, которые отличаются на x в их кодировке ASCII.


В учебных целях ...

Вот, пожалуйста ( см. Также на ideone.com ):

    String alpha = "ABCDEFGHIJKLMN";
    String p = alpha.replaceAll(".(?=(.))", "$0(?=$1|\\$)|") + "$";

    System.out.println(p);
    // A(?=B|$)|B(?=C|$)|C(?=D|$)|D(?=E|$)|E(?=F|$)|F(?=G|$)|G(?=H|$)|
    // H(?=I|$)|I(?=J|$)|J(?=K|$)|K(?=L|$)|L(?=M|$)|M(?=N|$)|N$

    String p5 = String.format("(?:%s){5}", p);

    String[] tests = {
        "ABCDE",    // true
        "JKLMN",    // true
        "AAAAA",    // false
        "ABCDEFGH", // false
        "ABCD",     // false
        "ACEGI",    // false
        "FGHIJ",    // true
    };
    for (String test : tests) {
        System.out.printf("[%s] : %s%n",
            test,
            test.matches(p5)
        );
    }

При этом используется метод мета-регулярного выражения для генерации шаблона. Этот шаблон гарантирует, что за каждым символом следует правильный символ (или конец строки), используя lookahead . Затем этот шаблон подвергается мета-регулярному выражению для повторного сопоставления 5 раз.

При необходимости вы можете заменить alpha вашей покерной последовательностью.

Обратите внимание, что это АБСОЛЮТНО НЕПРАВИЛЬНОЕ решение. Это намного более читабельно, например, просто проверьте, если alpha.contains(test) && (test.length() == 5).

Похожие вопросы

0 голосов
/ 13 октября 2011

решено!

См. http://jsfiddle.net/g48K9/3

Я решил использовать замыкание, в js.

String.prototype.isSequence = function () {
    If (this == "A2345") return true; // an exception
    return this.replace(/(\w)(\w)(\w)(\w)(\w)/, function (a, g1, g2, g3, g4, g5) {
        return    code(g1) == code(g2) -1 &&
                code(g2) == code(g3) -1 &&
                code(g3) == code(g4) -1 &&
                code(g4) == code(g5) -1;
    })
};

function code(card){
    switch(card){
        case "T": return 58;
        case "J": return 59;
        case "Q": return 60;
        case "K": return 61;
        case "A": return 62;
        default: return card.charCodeAt();
    }
}


test("23456");
test("23444");
test("789TJ");
test("TJQKA");
test("8JQKA");

function test(cards) {
    alert("cards " + cards + ": " + cards.isSequence())
}

Простоуточнить, коды ascii:

ASCII-коды:

2 = 50
3 = 51
4 = 52
5 = 53
6 = 54
7 = 55
8 = 56
9 = 57
T = 84 -> 58
J = 74 -> 59
Q = 81 -> 60
K = 75 -> 61
A = 65 -> 62
...