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

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

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

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

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

Матчи: 45678, 23456

Не соответствует: 45679 или же 23459 (не по порядку)

4 ответа

Решение

РЕШИТЬ!

Смотрите в 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

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

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

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

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

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

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

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

Вот фрагмент кода 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 по мере необходимости.


Как это устроено

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

{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,

Рекомендации

Что-то вроде 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),

Смежные вопросы

Другие вопросы по тегам