编译正则表达式(通过替换)


21

您的任务是通过为正则表达式中的每个字符指定替换来编译正则表达式。

正则表达式

正则表达式支持这些

REGEX       = (LITERAL REGEX / GROUP REGEX / STAR REGEX / ALTERNATIVE)
LITERAL     = 1 / 0
GROUP       = '(' REGEX ')'
STAR        = (LITERAL / GROUP) '*'
ALTERNATIVE = '('REGEX ('|' REGEX)*')'

为什么只有1或0?这是为了简化。因此,正则表达式仅具有以下字符:

*()|10

其解释如下:

  1. * 是Kleene星号(重复左组或字面量0次或多次)。
  2. | 是交替(如果左侧的正则表达式或右侧的正则表达式匹配,则匹配)。
  3. () 正在分组。
  4. 1 匹配字符1。
  5. 0 匹配字符0。

怎么编译?

您指定了六个代码段:一个用于替换每个正则表达式字符。例如,如果您的答案是:

*FSAGFSDVADFS
|GSDGSAG
(GSDG
)GDSIH
1RGIHAIGH
0GIHEBN

然后,将每个正则表达式替换为其各自的代码段,因此:

(0|11)*

变成:

GSDGGIHEBNGSDGSAGRGIHAIGHRGIHAIGHGDSIHFSAGFSDVADFS

结果程序应该做什么?

您的程序将:

  1. 接受输入。
  2. 如果正则表达式匹配整个输入,则输出真实值。
  3. 否则输出虚假值。

外部输入01受约束的未定义行为。输入可以为空。

附加规则

  1. 对于给定的正则表达式字符,结果片段必须始终相同。
  2. 此后没有添加前缀或后缀字符。
  3. 正则表达式保证为非空。

计分

最少的摘要是获胜者。因此,示例案例的得分将计算如下:

FSAGFSDVADFS+ GSDGSAG+ GSDG+ GDSIH+ RGIHAIGH+GIHEBN

12 + 7 + 4 + 5 + 8 + 6 = 42


每个摘要的长度至少为1个字符吗?
trichoplax

该代码段的长度可以为零。编辑确定。
Akangka

RegEx语言是否可有效应对此挑战?:P
Loovjo 2015年

我认为RegEx具有RegEx内置功能。我被迫这样做。我想排除Retina和正则表达式,但是,根据Mego的说法,这是不允许的。不过,我不了解蜗牛和朋友。
Akangka

@ChristianIrwan有趣的是,我仍然不确定这在Retina中是否可以解决,即使是这样,它也远非竞争性的。
马丁·恩德

Answers:


7

蜗牛,48个字节

0 -> )0(\0!(l.)(~

1 -> )0(\1!(l.)(~

( -> )0({{(

) -> )0}}(~

| -> )0}|{(

* -> )0),(~

如果我们必须搜索部分匹配项而不是仅匹配全部输入项,那么这将非常容易。0会变成\01会变成\1*会变成,,其他人会映射到自己。取而代之的是,有很多诡计可以防止比赛从起点以外的地方开始或终点以外的地方结束。!(l.)是一个断言,如果匹配的开始不在输入的开始,该断言将失败。~匹配输入之外的单元格,因此将其添加到正则表达式末尾允许的所有字符中。如果后面还有另一个正则表达式字符,则用数字量符将其抵消0这要求将其匹配0次,实质上是将其注释掉。为了使*,)能够正常工作,尽管无法进行虚拟越界测试,因此大量使用了语言的括号匹配规则。从文档中:

匹配的圆括号()或花括号对{}将按预期方式运行(就像正则表达式中的圆括号一样),但也可以根据以下规则省略一对的一半并进行推断。)}将所有内容都分组到最左边的相同类型(({分别是)的未关闭组打开指令;如果不存在,则为模式的开头。它会在此范围的中间关闭任何相反类型的未关闭开启指令。否则不匹配({在模式结束时关闭。

像泥一样清澈,对不对?


igh,我忘记了正则表达式之外甚至还有匹配的语言。干得好,但是很抱歉,没有投票(也没有
投票

@ChristianIrwan实际上,在此站点上开发2d匹配语言存在很大的挑战,其中大多数具有1d退化的用法。codegolf.stackexchange.com/questions/47311/…–
Sparr

7

CJam,151个字节

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

这些行对应于字符01(|)*(按此顺序)。在线尝试!

这不使用内置的正则表达式或其他类型的模式匹配。实际上,CJam没有这两个功能。相反,它从它表示的正则表达式开始并构建它可能匹配的所有可能的字符串,以最终检查用户输入是否为其中之一。

试运行

以下使用从STDIN读取正则表达式的程序,用适当的代码段替换其每个字符,最后评估生成的代码,以查看其是否与命令行参数中指定的输入匹配。

$ cat regex.cjam
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

"N%ers~
$ cjam regex.cjam '' <<< '(|)'
1
$ cjam regex.cjam '0' <<< '(|)'
0
$ cjam regex.cjam '' <<< '0(|)'
0
$ cjam regex.cjam '0' <<< '0(|)'
1
$ cjam regex.cjam '' <<< '(0|11)*'
1
$ cjam regex.cjam '0' <<< '(0|11)*'
1
$ cjam regex.cjam '11' <<< '(0|11)*'
1
$ cjam regex.cjam '011011000' <<< '(0|11)*'
1
$ cjam regex.cjam '1010' <<< '(0|11)*'
0

不幸的是,这并不是特别快。如果输入中有9个以上的字符,或者正则表达式中有多个Kleene星号,它将非常快地阻塞。

以5个额外的字节(总共156个字节)为代价,我们可以生成较短的字符串以匹配潜在的输入并对其进行重复数据删除。这不会改变代码的工作方式。它只是使其更有效率。

$ cat regex-fast.cjam 
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+eas,)m*:sSf-L|\"T

"N%ers~
$ cjam regex-fast.cjam '0101001010' <<< '(01|10)*'
0
$ cjam regex-fast.cjam '011001101001' <<< '(01|10)*'
1
$ cjam regex-fast.cjam '0' <<< '(0*1)*'
0
$ time cjam regex-fast.cjam '101001' <<< '(0*1)*'
1

我仍然有一些想法,我怎样才能使它更短和/或更快。如果对结果感到满意,我将添加一个解释。
丹尼斯

似乎`-escaping of the 在模式中有多余的“` *。不管怎么说,即使对于最简单的正则表达式仅由a组成的情况,我也无法使该程序接受任何输入0(请参阅在线解释器中的测试)。我做错了吗?
matz 2015年

1
@matz我的代码使用命令行参数,该参数未在该解释器中实现。试试这个吧
丹尼斯
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.