题
在另一个问题中,我学会了如何使用Regex计算直扑克手(这里).
现在,出于好奇,问题是: 我可以使用ASCII代码使用Regex计算同一件事吗?
就像是:
REGEX:[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连续的编码,而是使用数字用于非face卡,而是用于面部卡的非连续的非命令字符。
您需要在字符串开始时检测到 2345A, 23456, 34567, ..., 6789T, 789TJ, 89TJQ, 9TJQK
和 TJQKA
.
这些都是 不是 连续的ASCII代码,即使是,您也会遇到问题,因为 A2345
和 TJQKA
有效,你不会得到 A
既小于同一字符集中的其他字符,又比其他字符大。
如果它 拥有 要由正则表达式完成,然后是以下正则段:
(2345A|23456|34567|45678|56789|6789T|789TJ|89TJQ|9TJQK|TJQKA)
可能是您获得的最简单,最可读的内容。
当其他答案指出的那样 学习 REGEX,所以这是另一种可能是教学的meta-regex方法。
这是一个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
作为适当的。
这个怎么运作
.
metacharacter 匹配“任何”角色 (根据我们所处的模式,行分隔符可能是一个例外)。
这 {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组捕获的内容,然后是交替的metacharacter。
让我们考虑将其应用于较短的情况时会发生什么 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
.
参考
- 常规表达。Info/dot, 重复, 分组, 看看周围
就像是
regex: [C][C+1][C+2][C+3][C+4]
, , 存在C
ASCII代码(或喜欢)
在大多数正则口味中,您都无法远程接近此操作。这根本不是Regex设计的模式。
没有主流的正则表达式模式可以用来匹配任何两个连续的字符,以不同 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)
);
}
这使用元重新分解技术来生成模式。该模式可确保每个字符之后是正确的字符(或字符串的末端),使用 展望. 。然后,将这种模式重新分解为重复匹配5次。
你可以替代 alpha
必要时使用扑克序列。
请注意,这是一个 绝对不切实际 解决方案。更可读性的是,例如检查是否是否 alpha.contains(test) && (test.length() == 5)
.