正则表达式反向-分解正则表达式


16

问题

我有一堆需要在某些代码中使用的正则表达式,但是我使用的是不支持正则表达式的编程语言!幸运的是,我知道测试字符串将具有最大长度,并且仅由可打印的ASCII组成。

挑战

你必须输入一个正则表达式和一个号码n,并输出每一个可打印的ASCII(ASCII码32至126以下,组成的字符串~长的,没有突出部或换行符)小于或等于n相匹配的正则表达式。您可能根本不会在代码中使用内置的正则表达式或正则表达式匹配函数。正则表达式将限于以下内容:

  • 文字字符(和转义字符,使字符成为文字,因此\.是一个文字.\n是一个文字n(等效于just n),并且\w等价于w。您不需要支持转义序列。)
  • . -通配符(任何字符)
  • 字符类,[abc]表示“ a或b或c”,[d-f]表示从d到f的任何值(所以d或e或f)。在字符类中唯一具有特殊含义的字符是[](总是会被转义,所以不必担心),\(当然是转义符),^是在字符类的开头(这是一个否定) )和-(这是一个范围)。
  • |-OR运算符,交替。foo|bar表示foobar,并且(ab|cd)e匹配abecde
  • * -匹配先前的令牌重复零次或多次,贪婪(它尝试重复尽可能多的次数)
  • + -重复一次或多次,贪婪
  • ? -零或一遍
  • 带括号的分组,为组令牌|*+, 要么?

输入正则表达式将永远是有效的(也就是说,你不必处理像输入?abc(foo或任何无效的输入)。您可以按任意顺序输出字符串,但是每个字符串只能出现一次(不输出任何重复项)。

测试用例

输入:.*1
输出:(空字符串), ,, ,... ,!"}~

输入:w\w+3
输出:wwwww

输入:[abx-z][^ -}][\\]3
输出:a~\b~\x~\y~\z~\

输入:ab*a|c[de]*3
输出:ccdceaacdecedcddceeaba

输入:(foo)+(bar)?!?6
输出:foofoo!foofoofoobar

输入:(a+|b*c)d4
输出:adcdaadbcdaaadbbcd

输入:p+cg4
输出:pcgppcg

输入:a{3}4
输出:a{3}

获胜者,冠军

这是,所以最短的代码(以字节为单位)将获胜!


是否允许我们支持转义序列?那么这是微不足道的。
John Dvorak 2014年

3
您的解释|几乎没有道理。它似乎无法处理嵌套的组或a|b|c。在串联和交替绑定的强度方面,使用标准解释有什么问题?(而且没有不使用沙箱的借口)
Peter Taylor

1
@PeterTaylor实际上,他有一个借口:meta.codegolf.stackexchange.com/q/1305/9498
Justin

2
从您的示例来看,模式必须匹配整个字符串?(而不是子字符串)
Martin Ender 2014年

3
@KyleKanos现实世界中的问题让您觉得您不应该学习正则表达式,这真是令人遗憾。:P但是,它们并不是像看起来那样难以访问:regular-expressions.info/tutorial.html
Martin Ender 2014年

Answers:


7

哈斯克尔757 705 700 692 679 667

import Data.List
data R=L Char|A R R|T R R|E
h=[' '..'~']
k(']':s)a=(a,s)
k('^':s)_=l$k[]s
k('-':c:s)(a:b)=k([a..c]++b)s
k('\\':c:s)a=k s$c:a
k(c:s)a=k s$c:a
l(a,b)=(h\\a,b)
c#E=L c
c#r=A(L c)r
o(a,b)=(foldr(#)E a,b)
t%0=E
t%n=A(t%(n-1))$T t$t%(n-1)
d s n=m(fst$r s)[[]] where{m E a=a;m(L c)a=[b++[c]|b<-a,length b<n];m(A r s)x=nub$(m r x)++m s x;m(T r s)a=m s$m r a;r s=w$e s E;w(u,'|':v)=(\(a,b)->(A u a,b))$r v;w x=x;e(')':xs)t=(t,xs);e s@('|':_)t=(t,s);e s@(c:_)t=g t$f$b s;e[]t=(t,[]);g t(u,v)=e v$T t u;f(t,'*':s)=(t%n,s);f(t,'+':s)=(T t$t%n,s);f(t,'?':s)=(A t E,s);f(t,s)=(t,s);b('(':s)=r s;b('\\':s:t)=(L s,t);b('.':s)=o(h,s);b('[':s)=o$k s[];b(s:t)=(L s,t)}

输出:

ghci> d ".*" 1
[""," ","!","\"","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~"]
ghci> d "w\\w+" 3
["ww","www"]
ghci> d "[abx-z][^ -}][\\\\]" 3
["x~\\","y~\\","z~\\","b~\\","a~\\"]
ghci> d "ab*a|c[de]*" 3
["aa","aba","c","ce","cd","cee","cde","ced","cdd"]
ghci> d "(foo)+(bar)?!?" 6
["foo!","foobar","foo","foofoo"]
ghci> d "(a+|b*c)d" 4
["ad","aad","aaad","cd","bcd","bbcd"]
ghci> d "p+cg" 4
["pcg","ppcg"]
ghci> d "a{3}" 4
["a{3}"]

说明:这是教科书正则表达式的实现。R是正则表达式类型,具有构造函数A(备用),L(文字),T(然后)和E(空/ epsilon)。通常不会显示“星号”,因为我在解析过程中将其作为内联字符进行内联(请参见“%”)。“ m”运行模拟。解析器(从'rs = ....'开始)只是递归下降;“ k”解析范围。函数“#”将范围扩展为交替。


7

Python的V2.7 1069 1036 950 925 897 884 871 833 822

对于代码高尔夫来说,这个答案似乎很长,但是有很多运算符需要处理,我知道这个答案中每个字节的用途是什么。由于没有现有答案,因此我将其作为其他用户击败的目标。看看是否可以做一个简短的回答:)。

两个主要功能是fi第th个字符开始解析正则表达式,并d使用r我们可以递归为子正则表达式生成匹配的字符串,“ a”表示当前尚未处理的子正则表达式部分的数组,和一个字符串后缀s,表示到目前为止生成的字符串的一部分。

还要检查样品输出测试装置

import sys;V=sys.argv;n=int(V[2]);r=V[1];S=len;R=range;C=R(32,127)
Z=[];z=-1;D='d(r,p,';F='for j in '
def f(i,a):
 if i>=S(r):return a,i
 c=r[i];x=0;I="|)]".find(c)
 if c in"([|":x,i=f(i+1,Z)
 if I+1:return([c,a,x],[a],[c,a])[I],i
 if'\\'==c:i+=1;x=c+r[i]
 return f(i+1,a+[x or c])
def d(r,a,s):
 if S(s)>n:return
 while a==Z:
        if r==Z:print s;return
        a=r[z];r=r[:z]
 e=a[z];p=a[0:z]
 if'|'==a[0]:d(r,a[1],s);d(r,a[2],s)
 elif']'==a[0]:
        g=a[1];N=g[0]=='^';g=(g,g[1:])[N];B=[0]*127;O=[ord(c[z])for c in g]
        for i in R(0,S(g)):
         if'-'==g[i]:exec F+'R(O[i-1],O[i+1]):B[j]=1'
         else:B[O[i]]=1
        for c in C:N^B[c]<1or d(r,Z,chr(c)+s)
 elif' '>e:d(r+[p],e,s)
 else:c=p[:z];exec{'.':F+'C:'+D+'chr(j)+s)','?':D+'s);d(r,p[:z],s)','*':F+'R(0,n+1):d(r,c,s);c+=[p[z]]','+':"d(r,p+['*',p[z]],s)"}.get(e,D+'e[z]+s)')
d(Z,f(0,Z)[0],"")

请注意,原始解决方案中的选项卡已expand编辑。计算原始字符数unexpand < regex.py | wc


9
我从未见过python 如此恐怖。
user80551 2014年

您不能更改def E(a,b):c=a[:];c.extend(b);return cE=lambda a,b:a[:].extend(b),同上吗A
user80551 2014年

显然不是,因为.extend(b)不返回任何内容。
gmatht

1
对于elif isinstance(e,str):,我相信您可以将内部代码更改为:(exec{'.':'for c in C:d(r,p,s+chr(c))','?':'d(r,p,s);d(r,p[:z],s)','*':'''c=p[:z]#newline for i in R(0,n+1):d(r,c,s);c+=[p[z]]''','+':"d(r,p+['*',p[z]],s)",'\\':'d(r,p,e[1]+s)'}.get(e,'d(r,p,e+s)')请注意,这#newline是换行符)(源:stackoverflow.com/a/103081/1896169
贾斯汀2014年

1
如果您可以找到更多使用exec技巧的地方,我们可以轻松地将您的代码更改为不可读的代码:-)
Justin
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.