Déjame contarte sobre un sistema numérico simple. (que hice solo para este desafío)
Este sistema contiene las funciones ()
, []
, {}
, y <>
.
1) ()
Cuando no ()
se le dan argumentos, se evalúa como 0
.
Cuando ()
se le dan uno o más argumentos, se evalúa como la suma de los argumentos.
2) []
Cuando no []
se le dan argumentos, se evalúa como -1
.
Cuando []
se le dan uno o más argumentos, se evalúa como el primer argumento menos la suma de los otros argumentos.
3) {}
Cuando no {}
se le dan argumentos, se evalúa como 1
.
Cuando {}
se le dan uno o más argumentos, se evalúa el producto de esos argumentos.
4) <>
Cuando no <>
se le dan argumentos, se evalúa como 1
.
Cuando <>
se le dan uno o más argumentos, se evalúa en el primer entero de argumento dividido por el producto de los otros argumentos.
Tu tarea
Dada una cadena que contiene un número válido (lo que significa que los corchetes están equilibrados, no hay división por 0, etc.) en este sistema numérico simple, imprima su valor.
Casos de prueba
() -> 0
(()()) -> 0
([][]) -> -2
({}<>) -> 2
({}[]) -> 0
[] -> -1
[[][]] -> 0
[()<>] -> -1
{()} -> 0
{([]<>)} -> 0
Recuerde, este es el código de golf , por lo que gana el código con la menor cantidad de bytes.
fuente
5/3
,5/-3
,-5/3
y-5/-3
?Respuestas:
Dyalog APL , 94 bytes
o←{(⊂(1⊃⍵),⍺⍺⊃⍵),2↓⍵}⋄u←{(⊃⍵,⍺⍺1)⍺⍺⍵⍵/1↓⍵}⋄⍎⍕'+/o' '-u+o' '×/o' '÷u×o' '(⊂⍬),'[')]}>'⍳⌽⍞],'⊂⍬'
usos
⎕IO←0
reemplaza
)]}>
con una llamada de función que toma una pila, aplica una operación en su marco superior, la elimina y agrega el resultado a su siguiente marco (el operador monádicoo
se usa para eso; el operador diádicou
maneja los casos más complicados de-
y÷
)reemplaza
([{<
con código que agrega un marco a la pila ((⊂⍬),
)ejecuta la expresión resultante (invertida, para que coincida con el orden de ejecución de APL) con una pila inicial de un marco vacío (
⊂⍬
)fuente
Haskell,
357306277251228224188185180 bytesUn analizador basado en tokens con una pila explícita.
(%)
toma una pila de tokens y un carácter y empuja (código de operación, número predeterminado) o (0, número) para({[<
, o saca los números más altos y un código de operación y empuja la respuesta para)}]>
. Los códigos de operación están codificados por un hack de enumeración ascii.Felicitaciones a @ChristianSievers por su gran respuesta de la que tomé prestadas algunas ideas.
¡Un trazador de líneas!
¡Ahora con menos manejo de errores! Uso:
¡Gracias @ChristianSievers por guardar 14 + 3 bytes!
¡Gracias @Zgarb por guardar algunos + 4 bytes!
fuente
(0,[0,0,1,-1,1]!!o):s
en la quinta línea?!
, para que pueda hacerlo(s:_)!_=d s
como el segundo caso. Además, creo que podrías unirtex<-p$d<$>init a,y<-d$last a
en el último caso de%
.%
puede colocar parens alrededor_:b
yg c
.Python 2,
292265248235223206204 bytesReemplaza todos los corchetes con un lambda que hace lo que hace el corchete, luego evalúa el código Python resultante. Requiere su entrada entre comillas, como
'[<><>([]{})]'
.Este programa almacena el tipo de paréntesis como el primer carácter en cada cadena en el
for
, y todo lo que sigue a la palabra clavelambda
como el resto. Luego usa el primer carácter para sustituir; el resto se combina en una lambda como(lambda*x:sum(x))()
.Pruébalo en Ideone!
fuente
PEG.js (ES6) , 132 bytes
Debería arreglarse ahora.
Explicación
Más legible:
PEG.js es una versión extendida de Javascript específicamente diseñada para el análisis. Es MUY estricto, por eso tuve que usar
var
. Además, parece haber un error con corchetes dentro de las cadenas, que hinchó el código de manera significativa.Para comenzar, definimos una regla
x
que coincida con cualquier paréntesisa
que pueda o no contener múltiples expresiones que coincidan con la reglax
.Para que coincida cada regla
x
, empujamos un 0 a la matriz de la coincidencia internab
sib
la longitud es 1.Si
b
la longitud es> 0, entonces encontramos el índice dea
in([<
y obtenemos un carácter al+-/
usar ese índice. Si el resultado no está definido (lo que significa quea
era{
), entonces convertimos el resultado en*
. Finalmente, añadimos un espacio y nos unimosb
al resultado.Si
b
la longitud es = 0, entonces encontramos el índice dea
in([<
y obtenemos un carácter al10
usar ese índice. Si el resultado no está definido (lo que significa quea
era{
o<
), convertimos el resultado en 2. Finalmente, simplemente disminuimos.Al final, podemos evaluar la expresión y poner el resultado al suelo.
fuente
Perl, 113 + 2 = 115 bytes
Ejecutar con
-lp
(penalización de 2 bytes).Más legible (nota: esta "versión más legible" en realidad no se ejecutará, porque pongo comentarios en lugares que no están permitidos sintácticamente):
La idea básica es que estamos convirtiendo una entrada similar
[()<>]
al programa Perl ab(a(0),d(0),0),
través del procesamiento de texto; Perl está bien con la coma final. Anteriormente, definimos las funcionesa
,b
,c
,d
para tener el mismo efecto que el()
,[]
,{}
,<>
construcciones del lenguaje que estamos implementando; cada uno ignora su último argumento (el 0 al final), que se incluye para garantizar que todas las entradas se analicen correctamente, y trabajan utilizando la implementación comúnmente vista en la programación funcional donde la cabeza y la cola se procesan por separado. Porqueb(e,f,g,0)
significae-f-g
, es decir, trata su primer argumento especialmente, mientras quea
trata sus argumentos simétricamente (a(e,f,g,0)
significae+f+g
), implementamosa
recursivamente y ab
través de llamadasa
.c
yd
tener una relación similar Las cuatro funciones son muy similares, por lo que las generamos en tiempo de ejecución en lugar de implementarlas por separado; almacenamos una plantilla que se aplica a las cuatro funciones en una cadena, luego generamos las funciones sustituyendo caracteres en la plantilla.Como Perl
/
realiza la división de punto flotante, la implementa{}
también lo hace. Supongo que esto no es un problema en sí mismo o que-Minteger
(al seleccionar una variante de idioma donde todas las operaciones aritméticas son operaciones enteras) es gratis, porque de lo contrario tendría que gastar bytes adicionales escribiendo una división entera en Perl, que no parece ser de lo que se trata el problema fundamentalmente. (Creo que tendrías que gastar cuatro bytes(shift)
para cambiarint+(shift)
; no he probado esto).fuente
Octava,
215206198 bytespruébalo en línea
fuente
PHP,
315300285258250244 bytesreemplaza las subexpresiones con guión bajo + valor; el bucle se rompe cuando la iteración no reemplaza.
19 años desde que conocí a C, 17 años trabajando con PHP;
esta es la primera vez que
strtok
tiene sentido ... ¡ayuda a ahorrar 24 bytes!Descompostura
fuente
ES6 (Javascript),
250,171,154,149147 bytesUna versión pura de Javascript.
La "metaprogramación" (como la mayoría de las otras respuestas aquí), convierte el texto del programa de entrada en un programa Javascript correspondiente, aplicando una serie de sustituciones de texto directo (es decir, manteniendo la estructura del programa como está).
Probablemente se pueda jugar más al golf.
ACTUALIZACIÓN (v2.1)
ACTUALIZACIÓN (v2)
Me acabo de dar cuenta de que las comas pendientes en las matrices ES son totalmente válidas, por lo que todo el código de normalización de comas podría eliminarse. También siguió un excelente consejo de @Titus sobre la optimización de la búsqueda alfabética.
ACTUALIZACIÓN (v1)
Se eliminó el alias duplicado "reemplazar".
ACTUALIZACIÓN (v1)
Utilice un alfabeto mejor: () => 1+ [] => 0 {} => 2 * <> => 2 / (cada carácter se puede reutilizar directamente como un valor u operador)
Reemplazado reduce () con replace () (mapeo alfabético)
Fusión constante en línea, abrir y cerrar el procesamiento del soporte en un solo paso
Golfizado (v2.1)
Golfizado (v1)
Golfizado (v0)
Explicado (v0)
Prueba
Prueba de salida
fuente
s.reduce((r,c)=>r+="abcdefgh"["()[]{}<>".indexOf(c)],'')
(-5)? Si es así, puede recordarindexOf
en una variable y tomar el operador de un tercer literal de cadena.Haskell,
184 179 172 161 160 159 151 148145 bytesDescenso recursivo, enhebrando la entrada porque Haskell. Como de costumbre, la última línea no es una definición, pero establece la función que resuelve el problema. Entonces, para probar, coloque las líneas excepto la última en un archivo, cárguela y haga algo como esto:
Gracias a @Zgarb por la inspiración y muchos consejos detallados, y a @Angs por la inspiración de su solución y otros consejos.
No se especificó cómo debería comportarse la división con enteros negativos. De todos modos, usar repetidamente
div
parece incorrecto, ya que no es lo mismo que usardiv
una vez con el producto de los valores restantes. Ahora usandoquot
, obtengo los mismos resultados para<{}([][])[]>
y<{}{([][])[]}>
.Para un código agradable, casi legible, mira la primera versión. Las versiones intermedias contienen todo tipo de código agradable e intimidante y ayudan a comprender esta versión.
fuente
(!)=(,)
y utilizando en!
lugar de tuplas explícitas.m x
yd x
como1#x
y0#x
, puede fusionar los casosm[x]
yd[x]
en uno, lo que creo que también guarda algunos bytes.!
truco no paga. Su segunda sugerencia es malvada, ahí va mi código casi legible ... ¡Listo!s%(c:i)=(s?c,i)
ys?')'=sum s
etc. será mucho más corto, ya que puedes deshacerte de los repetidosi
s. ..No espere, eso probablemente no funcionará debido als%(_:i)
caso.elem
ydiv
eso debería ahorrar algunos bytes más.JavaScript (ES6), no
eval
, 156 bytesExplicación: La expresión regular encuentra el primer corchete de cierre no procesado y coincide con el corchete de apertura correspondiente (presumiblemente) y cualquier argumento intermedio. Los argumentos se dividen y se reducen de acuerdo con la operación (lamentablemente '(' y '[' no son el par óptimo para
+
y-
), o si no hay argumentos, se calcula el valor apropiado (una vez más, la coincidencia de caracteres con los valores es subóptima desde mi punto de vista). El resultado se sustituye con un espacio inicial para separarlo de otros resultados. La función se llama a sí misma recursivamente hasta que no haya más cambios que realizar, en cuyo caso devuelve el valor resultante. Ejemplo:fuente