匹配排列!


15

您的挑战是创建一个正则表达式,使其匹配自身的每个字符串排列,而不是其他任何内容。匹配项还必须区分大小写。

因此,例如,如果您的正则表达式为:

ABC

它应该匹配(并且仅匹配)以下字符串:

ABC
ACB
BAC
BCA
CAB
CBA

它不应该匹配以下内容:

AABC (contains an extra A)
ABCD (contains an extra D)
AC   (no B)
AAA  (no B and C, extra 2 A's)
abc  (case-sensitive)

规则:

  • 您可以使用任何喜欢的正则表达式。
  • 有标准漏洞。
  • 您的代码中必须至少包含两个不同的字符。这意味着类似1的解决方案是无效的。
  • 正则表达式应仅包含可打印的ASCII,而不能包含其他任何内容。



我以为是,(ABC|ACB|BAC|BCA|CAB|CBA)但您想要一个概括的答案。
Stephen Quan

Answers:


11

JavaScript, 64 57个字节

感谢Martin Ender,删除了4个字节。

^(?!.*([^])(.*\1){3}]?)[$$[-^?!!.'''-*11{33}5577\\-]{57}$

在这里尝试。

说明(已过时)

^                                  # Beginning of the string.
(?!.*                              # Match only the strings that don't contain...
  (.)(.*\1){4}                     #     5 occurrences of the same character.
  [^1]?[^1]?                       #     Something that doesn't matter.
)
[]zzz^(?!!!.**[)\\1{{44}}666]{64}  # 64 occurrences of these 16 characters.
                                   # Some are duplicated to make sure the regex
                                   # contains 4 occurrences of each character.
\z                                 # End of the string.

2
我认为这适用于60:^(?!.*(\S)(.*\1){3}[^1]?)[]zzSS[-^?!!.'''-*1{33}0066-]{60}\z regex101
Martin Ender,

这几乎可以在.NET中使用:^(?'4'(?!(.*\4){3})[]$$[\\^^?!!..'-*{}33-5-]){54}$[5]*
jimmy23013 '16

什么不起作用?尾随换行符?
Martin Ender

@MartinEnder是的。
jimmy23013 '16

2

Perl和PCRE正则表达式,280个字节

^(?=(.*z){2})(?=(.*\(){43})(?=(.*\)){43})(?=(.*\*){22})(?=(.*\.){23})(?=(.*0){2})(?=(.*1){6})(?=(.*2){16})(?=(.*3){7})(?=(.*4){4})(?=(.*5){1})(?=(.*6){3})(?=(.*7){2})(?=(.*8){2})(?=(.*9){1})(?=(.*=){22})(?=(.*\?){22})(?=(.*\\){11})(?=(.*\^){2})(?=(.*\{){23})(?=(.*\}){23}).{280}\z

(稍微)更具可读性:

^
(?=(.*z){2})
(?=(.*\(){43})
(?=(.*\)){43})
(?=(.*\*){22})
(?=(.*\.){23})
(?=(.*0){2})
(?=(.*1){6})
(?=(.*2){16})
(?=(.*3){7})
(?=(.*4){4})
(?=(.*5){1})
(?=(.*6){3})
(?=(.*7){2})
(?=(.*8){2})
(?=(.*9){1})
(?=(.*=){22})
(?=(.*\?){22})
(?=(.*\\){11})
(?=(.*\^){2})
(?=(.*\{){23})
(?=(.*\}){23})
.{280}\z

所写的时间为O(2 ^ n),因此效率极低。以测试它的最简单的方法是更换的每次出现.*.*?,这导致在那里它匹配最先被检查的情况下(这意味着它以线性时间相匹配,但是仍然需要指数时间,如果它不匹配)。

基本思想是,我们将正则表达式的长度强制等于280,并使用前瞻性断言强制正则表达式中的每个字符至少出现一定次数,例如,(?=(.*z){2})强制z字符至少出现两次。2+43+43+22+23+2+6+16+7+4+1+3+2+2+1+22+22+11+2+23+23是280,因此我们不能出现任何“多余”字符。

这是一个autogram的编程示例,这是一个句子,它通过列出其包含的每个字符的编号(在这种情况下,还包括总长度)来描述自己。我在构建它时很幸运(通常您必须使用蛮力,但在完全完成编写该程序之前,我在测试蛮力程序时偶然发现了该解决方案)。

Perl和PCRE regex,253字节,与Martin Ender合作

我假设可能会有较短的解决方案,省略了一些数字(最有可能是9、8或7)。Martin Ender找到了一个,如下所示:

^(?=(.*z){2})(?=(.*\(){39})(?=(.*\)){39})(?=(.*\*){20})(?=(.*\.){21})(?=(.*0){4})(?=(.*1){6})(?=(.*2){11})(?=(.*3){6})(?=(.*4){3})(?=(.*5){2})(?=(.*6){3})(?=(.*9){4})(?=(.*=){20})(?=(.*\?){20})(?=(.*\\){9})(?=(.*\^){2})(?=(.*{){21})(?=(.*}){21}).{253}\z

可读版本:

^
(?=(。* z){2})
(?=(。* \(){39})
(?=(。* \)){39})
(?=(。* \ *){20})
(?=(。* \。){21})
(?=(。* 0){4})
(?=(。* 1){6})
(?=(。* 2){11})
(?=(。* 3){6})
(?=(。* 4){3})
(?=(。* 5){2})
(?=(。* 6){3})
(?=(。* 9){4})
(?=(。* =){20})
(?=(。* \?){20})
(?=(。* \\){9})
(?=(。* \ ^){2})
(?=(。* {){21})
(?=(。*}){21})
。{253} \ z

我认为您不必{}在最后两个前期中逃脱这些操作。您也不需要添加类似的东西,(?=(.*5){1})因为5如果您没有那样的前瞻性就不会有。一个问题是$允许尾随换行符,因此您需要在\z那里使用而不是$像jimmy那样使用,但是我认为这不会花费您一个字节,因为您\在第一个前瞻中保存了。
马丁·恩德

我知道可以省略数字之类的东西。但是,它们可以使自动签名工作。删除程序的任何部分都将导致其余所有部分中断,因为它不再正确地描述该程序。(每行的计数就是每行的计数!因此,通常基本上无法更改程序。)至于$允许在字符串末尾使用换行符,这通常取决于周围环境对regex的调用方式。程序(它们通常在已经解析为行的代码上运行)。

或者更确切地说:(?=(.*5){1})在这种情况下,我确实需要。如果删除它,程序中将有一个5,因为该(?=(.*1){6})行现在必须读取(?=(.*1){5})

至于尾随换行符,对正则表达式的输入类型的挑战似乎没有任何限制,因此通常意味着它应适用于任何字符串,并且更改$\z不会造成任何伤害(并且不会不会破坏签名)。
马丁·恩德

哦,我懂了; 您将\$… 更改$z\z。这样可行; 我去改变它。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.