Quylthulg es un lenguaje de Chris Pressey que intenta resolver el problema de la notación infija usando lo que llama panfix :
Al igual que Postfix, Panfix no requiere el despliegue de artilugios arcanos como paréntesis para anular una precedencia de operador predeterminada. Al mismo tiempo, panfix permite que los términos se especifiquen en el mismo orden y forma que infix, una notación indudablemente natural e intuitiva para aquellos que se han acostumbrado a ello.
¿Cómo se obtiene la conveniencia de la notación de infijo junto con la inequívoca de prefijo o postfix? ¡Usa los tres, por supuesto!
=y=+*3*x*+1+=
Más formalmente, seamos +
un operador, a
y b
seamos expresiones. Entonces (a+b)
es una expresión infija válida (entre paréntesis), la representación panfix de esa expresión es +a+b+
, donde la yuxtaposición representa la concatenación.
Su objetivo es tomar una cadena de panfix y convertirla en un infijo completamente entre paréntesis:
(y=((3*x)+1))
Para simplificar, haremos los siguientes cambios:
- Los operadores solo pueden constar de dos caracteres únicos (puede elegir cualquiera, pero aquí usaré
*
y+
). - Solo hay un literal, que consiste en otro carácter distinto (puede elegir cualquiera, pero aquí lo usaré
_
). - La entrada será una expresión panfix bien formada.
Por complejidad , haremos el siguiente cambio:
- Los operadores pueden constar de cualquier número positivo de caracteres, no solo uno.
Esto hace que el desafío sea más complicado porque no se puede determinar necesariamente cómo se divide una subcadena determinada de caracteres del operador sin mirar el resto de la cadena.
Aquí hay una implementación de referencia para el desafío, cortesía de @ user202729.
Casos de prueba
format: input -> output
+*+_*+_*+++_+*+_*+_*+++ -> ((_*+_)+(_+(_*+_)))
**++*+***++_+_++_+*++*+***_*++*+*****_**_*_*** -> ((((_+_)+_)*++*+***_)*(_*(_*_)))
***_**_***_* -> ((_**_)*_)
+_+_+ -> (_+_)
*+*+++**+***+++++_*+*+++**+***+++++_*+*+++**+***+++++ -> (_*+*+++**+***+++++_)
*++++*+*_*_*+*+++****+_++****+_++****++*+*+++_*+++ -> (((_*_)+*+(_++****+_))*+++_)
+**+_*+_*+*_*+*_*+*_+*_+**+ -> (((_*+_)*_)+(_*(_+*_)))
+**+++++_+++++_+++++*_*+*+_++++++_+++++_+++++++* -> (((_+++++_)*_)+*(_+(_+++++_)))
+*+*+_+*+_+*+*_*+*_*+*+_+*+_+*+*+ -> (((_+*+_)*_)+(_*(_+*+_)))
**_**_**_*_****_* -> ((_*(_*(_*_)))*_)
Utilicé este programa para generar cadenas de infijo para este desafío (la conversión a panfix fue trivial, pero la inversión no lo es).
**_**_**_*_****_*
. Todas las respuestas que he probado han fallado en esta.(_ + _)
?Respuestas:
Prólogo (SWI) ,
194163 bytes¡Ahorré la friolera de 31 bytes usando este consejo de 0 ' !
El operador
^
toma para su argumento izquierdo una cadena que contiene una expresión panfix y establece su argumento derecho en una cadena que contiene la expresión infija entre paréntesis correspondiente. Se utilizax
como literal en lugar de_
.Pruébalo en línea!
Explicación
Como Prolog es un lenguaje declarativo, solo tenemos que describir la relación entre un panfix y una expresión entre paréntesis.
La explicación utiliza esta versión un poco no golfista:
Nuestra producción principal es
parenthesize
, que toma una expresión panfixX
como una cadena y envía la expresión infija entre paréntesis correspondienteP
como una cadena. Se utilizastring_chars
para convertir la cadena de entrada en una lista de caracteres y luego simplemente se la pasaexpr
.expr
toma una lista de caracteresL
, analiza la primera expresión panfix que encuentraL
y envía el equivalente entre paréntesisX
y el resto de la lista de caracteresR
. Hay dos tipos posibles de expresiones:L
esx
, entonces la expresión esx
y el resto es todo después dex
.O
(ver másoper
abajo); analizar una expresiónY
; analizar deO
nuevo; analizar otra expresiónZ
; y analizarO
por tercera vez. El resto es todo después de la tercera instancia deO
. La expresión es el resultado de la uniónY
,O
yZ
, rodeado de paréntesis, en una cadena.oper
toma una lista de personajes, donde está el primer personajeC
y el restoT
; analiza un operador (es decir, una serie de uno o más caracteres de operador) y envía el operadorO
y el resto de la lista de caracteresR
. Para formar un operador, el personajeC
debe ser algo distinto dex
; tambiénP
debe ser analizable desdeT
, con el restoR
; en este caso,O
es la concatenación deC
yP
; o,O
es el personaje únicoC
; En este caso,R
es justoT
.Un ejemplo trabajado
Tomemos la entrada
+*+x+x++*x+*
como ejemplo.+*+x+x++*x+*
. Esto no comienza conx
, por lo que analizamos un operador desde el principio.oper
analizará un operador lo más grande posible, así que lo intentamos+*+
.x+x++*x+*
. Esto tiene que serx
.+*+
, desde+x++*x+*
. Sin embargo, esto falla .+*
lugar.+x+x++*x+*
. Esto no comienza conx
, por lo que debemos analizar un operador.+
.x+x++*x+*
. Esto tiene que serx
.+
nuevo desde+x++*x+*
.x++*x+*
. Esto tiene que serx
.+
nuevamente desde++*x+*
.(x+x)
.+*
nuevamente el operador desde+*x+*
.x+*
. Esto tiene que serx
.+*
nuevamente desde+*
.((x+x)+*x)
.Como no quedan más caracteres, hemos traducido con éxito la expresión.
fuente
Perl,
7860585750 bytesIncluye
+1
parap
Usos
1
para+
y2
para*
(o, de hecho, cualquier dígito funciona para cualquier operador)Para una prueba conveniente en comparación con los ejemplos dados, puede usar esto, que realiza las traducciones y la eliminación de espacio por usted:
fuente
Limpio ,
200192189 bytesPruébalo en línea!
Define la función
f
, tomarString
y devolver un singleton[String]
con el resultado dentro.Algunas cosas ordenadas:
_
fuente
Retina 0.8.2 , 138 bytes
Pruébalo en línea! El enlace incluye los casos de prueba más rápidos. Explicación: El motor de expresiones regulares utiliza el retroceso para dividir la cadena en tokens que luego se empujan o se sacan del
i
grupo de equilibrio. Siempre se ejecuta al menos un operador al inicio antes de la primera variable. Después de una variable, aparece al menos un operador, momento en el cual un operador empujado ejecuta u otra variable es legal. Los operadores son empujados al grupo por duplicado para que puedan aparecer correctamente. Ejemplo:Desafortunadamente, esto no nos ayuda a capturar los resultados para agruparlos, por lo que el operador externo se compara manualmente. Los corchetes se agregan de afuera hacia adentro, por lo que la primera etapa envuelve toda la expresión entre corchetes y la última etapa los elimina ahora que se han propagado a las variables.
fuente
**_**_**_*_****_*
.Haskell ,
167166 bytesPruébalo en línea! Ejemplo de uso:
head.e "**_**_**_*_****_*"
rendimientos((_*(_*(_*_)))*_)
. Todos los caracteres excepto_
se interpretan como operadores, en_
sí denota un identificador.fuente
Python 3, 226 bytes
Define una función anónima llamada
R
.Pruébalo en línea!
fuente
_*+
; esos fueron justo lo que se utilizó en el ejemplo. Es posible que pueda usar esto para golf sus expresiones regulares (por ejemplo, usando en\d
lugar de[*+]
).