El problema
¡Tengo un montón de expresiones regulares que necesito usar en algún código, pero estoy usando un lenguaje de programación que no admite expresiones regulares! Afortunadamente, sé que la cadena de prueba tendrá una longitud máxima y estará compuesta solo de ASCII imprimible.
El reto
Debe ingresar una expresión regular y un número n
, y generar cada cadena compuesta de ASCII imprimible (códigos ASCII 32 a 126 inclusive, a
~
, sin pestañas o nuevas líneas) de longitud menor o igual que n
esa coincidencia con esa expresión regular. Es posible que no utilizar construido en expresiones regulares o funciones coincidentes de expresiones regulares en su código. Las expresiones regulares se limitarán a lo siguiente:
- Caracteres literales (y escapes, que obligan a un carácter a ser literal, por lo que
\.
es un literal.
,\n
es un literaln
(equivalente a justn
) y\w
es equivalente aw
. No es necesario admitir secuencias de escape). .
- comodín (cualquier personaje)- Clases de caracteres,
[abc]
significa "a o b o c" y[d-f]
significa cualquier cosa de d a f (entonces, d o e o f). Los únicos caracteres que tienen un significado especial en una clase de caracteres son[
y]
(que siempre se\
escaparán , así que no se preocupe por eso), (el carácter de escape, por supuesto),^
al comienzo de la clase de caracteres (lo cual es una negación ) y-
(que es un rango). |
- el operador OR, alternancia.foo|bar
significafoo
obar
, y(ab|cd)e
coincide conabe
ocde
.*
- coincide con el token anterior repetido cero o más veces, codicioso (intenta repetir tantas veces como sea posible)+
- repetido una o más veces, codicioso?
- cero o una vez- Agrupación con paréntesis, a fichas de grupo para
|
,*
.+
o?
La expresión regular de entrada siempre será válida (es decir, no tiene que manejar entradas como ?abc
o(foo
o cualquier entrada no válida). Puede generar las cadenas en el orden que desee, pero cada cadena debe aparecer solo una vez (no generar duplicados).
Los casos de prueba
Entrada: .*
, 1
Salida: (cadena vacía), ,
!
, "
, ...,}
,~
Entrada: w\w+
, 3
Salida:ww
,www
Entrada: [abx-z][^ -}][\\]
, 3
Salida: a~\
, b~\
, x~\
,y~\
,z~\
Entrada: ab*a|c[de]*
, 3
Salida: c
, cd
, ce
, aa
, cde
, ced
, cdd
,cee
,aba
Entrada: (foo)+(bar)?!?
, 6
Salida: foo
, foo!
, foofoo
,foobar
Entrada: (a+|b*c)d
, 4
Salida: ad
, cd
, aad
, bcd
, aaad
,bbcd
Entrada: p+cg
, 4
Salida: pcg
,ppcg
Entrada: a{3}
, 4
Salida:a{3}
El ganador
Este es el código de golf , por lo que el código más corto en bytes ganará.
fuente
|
tiene muy poco sentido. No parece manejar grupos anidados oa|b|c
. ¿Qué tiene de malo usar las explicaciones estándar en términos de cuán fuertemente se unen la concatenación y la alternancia? (Y no tienes excusa para no usar el sandbox)Respuestas:
Haskell
757 705 700 692 679667salida:
Explicación: esta es una implementación de expresiones regulares de libros de texto. R es el tipo de expresiones regulares, con los constructores A (alternativo), L (literal), T (luego) y E (vacío / épsilon). La 'estrella' habitual no aparece porque la alineo como alternativa durante el análisis (ver '%'). 'm' ejecuta la simulación. El analizador (comienza en 'rs = ....') es solo un descenso recursivo; 'k' analiza los rangos. La función '#' expande los rangos en alternancias.
fuente
Python v2.7
10691036950925897884871833822Esta respuesta parece bastante larga para un código de golf, pero hay muchos operadores que deben manejarse y sé qué propósito tiene cada byte en esta respuesta. Como no hay una respuesta existente, presento esto como un objetivo para que otros usuarios lo superen. Vea si puede hacer una respuesta más corta :).
Las dos funciones principales son las
f
que analizan la expresión regular que comienza en eli
carácter th, y lad
que genera las cadenas coincidentes, utilizandor
las sub-expresiones regulares en las que podemos recurrir, 'a' la matriz que representa la parte de la expresión regular actual que aún no se procesó, y un sufijo de cadenas
que representa la parte de la cadena generada hasta ahora.También verifique la salida de muestra y un arnés de prueba .
Tenga en cuenta que las pestañas en la solución original se han
expand
editado. Para contar el número de caracteres en el uso originalunexpand < regex.py | wc
.fuente
def E(a,b):c=a[:];c.extend(b);return c
aE=lambda a,b:a[:].extend(b)
, ídem paraA
elif isinstance(e,str):
, creo que podría cambiar el código interno a: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)')
(tenga en cuenta que#newline
es una nueva línea) (fuente: stackoverflow.com/a/103081/1896169 )