Quiero probar un nuevo tipo de desafío regex golf, que le pide que resuelva tareas computacionales no triviales con nada más que la sustitución de expresiones regulares. Para hacer esto más posible y menos complicado, se le permitirá aplicar varias sustituciones, una tras otra.
El reto
Comenzaremos de manera simple: dada una cadena que contiene dos enteros positivos, como números decimales separados por a ,
, se produce una cadena que contiene su suma, también como un número decimal. Entonces, muy simple
47,987
debería convertirse en
1034
Su respuesta debería funcionar para enteros positivos arbitrarios.
El formato
Cada respuesta debe ser una secuencia de pasos de sustitución, cada paso compuesto por una expresión regular y una cadena de reemplazo. Opcionalmente, para cada uno de esos pasos en la secuencia, puede elegir repetir la sustitución hasta que la cadena deje de cambiar. Aquí hay un ejemplo de envío (que no resuelve el problema anterior):
Regex Modifiers Replacement Repeat?
\b(\d) g |$1 No
|\d <none> 1| Yes
\D g <empty> No
Dada la entrada 123,456
, esta presentación procesará la entrada de la siguiente manera: la primera sustitución se aplica una vez y produce:
|123,|456
Ahora la segunda sustitución se aplica en un bucle hasta que la cadena deja de cambiar:
1|23,|456
11|3,|456
111|,|456
111|,1|56
111|,11|6
111|,111|
Y, por último, la tercera sustitución se aplica una vez:
111111
Tenga en cuenta que el criterio de terminación para los bucles es si la cadena cambia, no si la expresión regular encontró una coincidencia. (Es decir, también podría terminar si encuentra una coincidencia, pero el reemplazo es idéntico a la coincidencia).
Tanteo
Su puntaje principal será el número de pasos de sustitución en su envío. Cada sustitución repetida contará para 10 pasos. Entonces, el ejemplo anterior se puntuaría 1 + 10 + 1 = 12
.
En el caso (no muy improbable) de un empate, la puntuación secundaria es la suma de los tamaños de todos los pasos. Para cada paso, agregue la expresión regular ( sin delimitadores), los modificadores y la cadena de sustitución. Para el ejemplo anterior esto sería (6 + 1 + 3) + (3 + 0 + 2) + (2 + 1 + 0) = 18
.
Reglas misceláneas
Puede usar cualquier sabor regex (que debe indicar), pero todos los pasos deben usar el mismo sabor. Por otra parte, se debe no utilizar las funciones del lenguaje anfitrión del sabor, como las devoluciones de llamada de repuesto o de Perl e
modificador, que evalúa código Perl. Toda manipulación debe ocurrir exclusivamente a través de la sustitución de expresiones regulares.
Tenga en cuenta que depende de su sabor y modificadores si cada reemplazo reemplaza todos los sucesos o solo uno. Por ejemplo, si elige el sabor ECMAScript, un solo paso reemplazará de manera predeterminada solo una aparición, a menos que use el g
modificador. Por otro lado, si está utilizando el sabor .NET, cada paso siempre reemplazará todas las ocurrencias.
Para los idiomas que tienen diferentes métodos de sustitución para el reemplazo único y global (por ejemplo, Ruby's sub
vs. gsub
), suponga que el reemplazo único es el predeterminado y trate el reemplazo global como un g
modificador.
Pruebas
Si su sabor elegido es .NET o ECMAScript, puede usar Retina para probar su envío (me han dicho, también funciona en Mono). Para otros sabores, probablemente tendrá que escribir un pequeño programa en el idioma del host que aplique las sustituciones en orden. Si lo hace, incluya este programa de prueba en su respuesta.
fuente
Respuestas:
Sabor .NET, puntuación: 2
Todavía no me molesto en jugar golf, y
x
es solo por ignorar los espacios en blanco.Primero inserte
9876543210
en cada posición, luego elimine los caracteres originales y los caracteres que no son el dígito actual de la suma.La expresión regular grande (1346 bytes sin espacios en blanco y comentarios):
Esto me hizo pensar en el nivel final de Manufactoria ... Pero creo que .NET regex, que obviamente ya no es "regular", puede resolver cualquier problema en PH. Y esto es solo un algoritmo en L.
fuente
Puntuación: 24
Creo que esto funciona ...
Todavía no he pasado mucho tiempo jugando golf con las expresiones regulares individuales. Intentaré publicar una explicación pronto, pero ya se está haciendo tarde. Mientras tanto, aquí está el resultado entre cada paso:
Programa completo de perl:
fuente
Cualquier sabor regex, 41
Probemos unario.
d
sirve para un separador de orden de dígitos,x
almacena el valor. Primero desarmamos cada dígito, luego exprimimos los multiplicadores x10 a la izquierda, luego soltamos todos los separadores, luego volvemos a insertar los multiplicadores, luego convertimos cada orden nuevamente en dígitos.fuente
.NET Regex, 14
No es tan bueno como la solución de user23013, pero fue divertido. Ninguno de los reemplazos tiene modificadores.
La razón de la expresión regular de .NET no se debe al equilibrio de los grupos por una vez: solo probé con Retina , que usa .NET, y también descubrí que las miradas de longitud variable me ayudaron mucho.
Reemplazo 1 (repetir = no)
Regex:
Reemplazo
Cambie los dos números, rellenando para tener el mismo número de ceros a la izquierda.
Reemplazo 2 (repetir = no)
Regex:
Reemplazo:
Agrega un espacio antes de cada número
Reemplazo 3 (repetir = no)
Reemplazo:
Agregue un bit de acarreo (el
&0
) así como la tabla de búsqueda gigante de<c> <a> <b> <carry of a+b+c> <last digit of a+b+c>
.Reemplazo 4 (repetir = sí)
Regex:
Reemplazo:
Sigue tomando los últimos dígitos de cada número y encuentra su (suma, acarreo). Pon la suma al comienzo de la cuerda y reemplaza el carry.
Reemplazo 5 (repetir = no)
Regex:
Reemplazo:
Limpiar.
Ejecución de ejemplo
(Al combinar algunos de los pasos puedo obtener 12, pero dado que se vuelve bastante complicado y no ganará de todos modos, creo que seguiré con esta versión más elegante).
fuente
Puntuación:
50403121Gracias por este excelente desafío. Esta solución no es muy elegante, pero, dadas las restricciones, no pude ver ninguna forma de manejar un dígito genéricamente en la salida.
Esta solución presenta grupos de captura que a veces no coinciden y depende de que estén vacíos cuando eso ocurre. Esto funciona en Perl, aunque normalmente produce una advertencia.
Ejemplo completo de código Perl, con explicación e impresión de resultados intermedios:
Actualización: pude combinar dos de las expresiones regulares en bucle, ahorrando 10.
Actualización 2: logré descifrar la conversión de dígitos de entrada con una sola expresión regular.
Actualización 3: reduje a una sola expresión regular de bucle.
fuente
${1}
diferente de$1
? Además, es posible que desee incluir el recuento de bytes en caso de empate.\1
, etc., en cambio, guardando algunos caracteres.