正则表达式计算直接扑克牌 - 使用ASCII码

时间:2010-08-14 05:27:53

标签: regex poker

在另一个问题中,我学会了如何使用正则表达式计算直接扑克牌(here)。

现在,出于好奇,问题是:我可以使用正则表达式使用ASCII代码计算相同的东西吗?

类似的东西:

正则表达式:[C] [C + 1] [C + 2] [C + 3] [C + 4],是C的ASCII码(或者像这样)

匹配:4567823456

不匹配:4567923459(不按顺序)

4 个答案:

答案 0 :(得分:5)

你的主要问题实际上是你手上没有使用ASCII连续编码,你使用非面部卡的数字,以及面部卡的非连续,无序字符。< / p>

您需要在字符串的开头检测2345A, 23456, 34567, ..., 6789T, 789TJ, 89TJQ, 9TJQKTJQKA

这些不是连续的ASCII码,即使它们是,也会遇到问题,因为A2345TJQKA都有效,你不会得到{ {1}}小于和大于同一字符集中的其他字符。

如果 由正则表达式完成,那么以下正则表达式段:

A

可能是最简单,最易读的。

答案 1 :(得分:4)

正如其他答案所指出的那样,没有正则表达式可以做你想要的,但你确实说过你想要学习正则表达式,所以这里是另一种可能是教学的元正则表达式方法

这是一个Java片段,给定一个字符串,以编程方式生成将匹配该长度为5的字符串的任何子字符串的模式。

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

输出为(as seen on ideone.com):

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

通过适当初始化seq,您可以使用它来方便地生成正则表达式模式以匹配直接的扑克牌。


如何运作

.元字符matches "any" character(行分隔符可能是个例外,具体取决于我们所处的模式)。

{5}是一个精确的repetition说明符。 .{5}完全匹配5 .

(?=…)positive lookahead;它断言给定的模式可以匹配,但由于它只是一个断言,它实际上并没有从输入字符串中产生(即消耗)匹配。

简单地(…)capturing group。它会创建一个后向引用,您可以在模式中稍后使用,或者在替换中使用,或者您认为合适。

为方便起见,此处重复此模式:

     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,这是seq长度为5的所有子串。

参考

答案 2 :(得分:3)

  

类似regex: [C][C+1][C+2][C+3][C+4]C ASCII代码(或类似内容)

在大多数正则表达式中,您无法远程执行任何操作。这根本不是正则表达式所设计的那种模式。

没有主流正则表达式模式可以匹配任何两个在ASCII编码中相差x的连续字符。


出于教学目的......

你去(see also on 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)

相关问题

答案 3 :(得分:0)

<强>解决!

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