Una cadena equilibrada es una cadena de paréntesis ()
para que cada paréntesis se pueda combinar con otro. Más rigurosamente son las cadenas que abarca esta gramática:
S → (S)S | ε
Podemos convertir una cadena "de adentro hacia afuera" de la siguiente manera:
Cambio de todas las apariciones de
(
y)
con los demásMover caracteres desde el frente de la cadena hacia atrás hasta que la cadena se equilibre nuevamente.
Hagamos un ejemplo.
Comenzamos con la cadena equilibrada:
(()(())())
Luego cambiamos los parens para hacer
))())(()((
Luego mueva los caracteres desde el frente de la cadena hasta la parte posterior de la cadena hasta que la cadena esté equilibrada.
))())(()((
)())(()(()
())(()(())
))(()(())(
)(()(())()
(()(())())
Ese es nuestro resultado!
Tenga en cuenta que algunas cadenas pueden invertirse de varias maneras, por ejemplo, la cadena
(()())
Cuando se da la vuelta al revés puede ser:
()(())
o
(())()
Sin embargo, cada cadena tiene al menos una solución .
Tarea
Escriba un programa para tomar una cadena equilibrada como entrada y salida de esa cadena al revés. En los casos en que puede haber múltiples salidas válidas, solo necesita una de ellas. Puede usar un tipo de llave diferente ( <>
, []
o {}
) si lo desea.
Esta es una competencia de código de golf , por lo que debe intentar minimizar el tamaño de su código fuente, medido por bytes.
Casos de prueba
(()()) -> ()(()), (())()
(()(())()) -> (()(())())
((())())() -> (()(()()))
fuente
Respuestas:
Haskell ,
12412011911711311010910610510410198 bytes¡4 bytes guardados gracias a bartavelle!
3 bytes guardados gracias a Zgarb
1 byte guardado gracias a Peter Taylor
Aquí hay una solución que resolví en Haskell. Está
bien en este momentobastante bien gracias a la ayuda que recibí, pero estoy tratando de acortar esto, por lo que agradecemos sus comentarios / sugerencias.Pruébalo en línea!
Explicación
Este programa define 4 funciones, la primera
(!)
determina si una cadena está equilibrada. Se define de la siguiente manera:Esta verificación asume que la entrada tiene el mismo número de pares abiertos y cerrados gracias a una sugerencia de Peter Taylor.
El siguiente
g
rotará la cadena una vez.Luego tenemos
d
que simplemente toma un par y lo reflejaFinalmente tenemos la función que nos preocupa. Aquí usamos una representación de
until(!0)g
compuesto con punto libremap d
, que se asignad
a la entrada y se aplicag
hasta que el resultado esté equilibrado. Este es el proceso exacto descrito en la pregunta.fuente
g x@(a:b)|x!0=x|1>0=g$b++[a]
y eliminando los parens parad '('=')'
.d
causa un error de compilación, créeme que lo he intentado. Pero la primera sugerencia es bienvenida. ¡Gracias!!
porque no necesita manejar casos en los que la cadena tiene un número desigual de paréntesis abiertos y cerrados, por lo que puede intercambiar los dos primeros casos y tener_!1=1<0
[]!_=0<1
until
para acortarg
: TIOd
mapa'('
de(-1)
y cualquier otra cosa a1
, y luego los dos casos más largos de!
se pueden combinar para(i:a)!x=a!(x+i)
. Luego, la estructura de nivel superior necesita ser modificada paramap d
entrar en launtil
condición, y tengo que correr para no tener tiempo en este momento para averiguar qué combinadores se requieren para unirlo todo.SOGL V0.12 ,
1211 bytesPruébalo aquí!
Explicación:
Nota:
l{
podría reemplazarse por ( para 10 bytes, pero, lamentablemente, no está implementado.fuente
CJam (20 caracteres)
Demostración en línea
o por el mismo recuento de char
Demostración en línea
Disección
Las dos versiones tienen un encabezado y pie de página en común.
Luego, el bit en el medio obviamente calcula qué tan lejos es necesario rotar. Ambos utilizan la evaluación y confían en
(
ser el operador de decremento CJam y)
ser el operador de incremento.vs
fuente
JavaScript (ES6),
111bytes(Ahorró 2 bytes gracias a @CraigAyre, 2 bytes gracias a @PeterTaylor, 2 bytes gracias a @Shaggy.)
Sin golf:
Casos de prueba:
Mostrar fragmento de código
fuente
Retina ,
4638 bytesPruébalo en línea! El enlace incluye casos de prueba. Editar: guardado 8 bytes con ayuda de @MartinEnder. La primera etapa simplemente transpone los paréntesis, mientras que la segunda etapa busca el sufijo más largo que es un prefijo equilibrado válido, que aparentemente es una condición suficiente para que la rotación esté completamente equilibrada. El equilibrio se detecta mediante grupos de equilibrio. La construcción
((\()|(?<-4>\)))+
coincide con cualquier número de(
s más cualquier número de)
s siempre que ya hayamos (<-4>
) visto tantos(
s. Como solo estamos buscando un prefijo válido, no tenemos que coincidir con los)
s restantes .fuente
((\()|(?<-2>\)))
. Sin embargo, su intento sólo me inspiró para encontrar un enfoque completamente nuevo que guarda otros dos:(?<-1>(\()*\))+
. Esto sin duda será útil en el futuro, así que gracias. :)(?<-1>(\()*\))+
funciona, ya que parece querer salir de la1
pila antes de haber emparejado algo ...\(*
sin embargo.PHP,
110108 bytesEjecutar como tubería con
-nR
o probarlo en línea .Descompostura
fuente
Python 3 ,
112103101 bytes-2 bytes gracias a @ Mr.Xcoder
Pruébalo en línea!
fuente
Octava, 62 bytes
Pruébalo en línea!
Una función que toma la cadena como entrada e imprime todos los resultados.
Explicación:
fuente
Mathematica, 78 bytes
fuente
JavaScript (ES6), 97 bytes
Funciona girando recursivamente la cadena de entrada hasta que su transposición esté equilibrada y luego transponiéndola.
fuente
APL (Dyalog Unicode) ,
3530 bytesGolfed un nuevo enfoque gracias a @ Adám
Pruébalo en línea!
El golf está en progreso.
Explicación
fuente
Python 2 , 99 bytes
Pruébalo en línea!
En forma de función para casos de prueba fáciles:
Python 2 , 108 bytes
Pruébalo en línea!
Esto utiliza un enfoque ligeramente diferente: en lugar de rotar recursivamente la cadena, si consideramos que los elementos parentales aumentan y disminuyen algún contador de equilibrio, una cadena equilibrada nunca debe tener una suma total de incrementos, decrementos que son menores que 0.
Entonces tomamos
invertir los parens:
y conviértalo en una lista de sumas de incrementos / decrementos:
-3 es el mínimo en el índice 4 (basado en cero); entonces queremos cambiar por ese índice + 1. Esto garantiza que el incremento / decremento acumulativo nunca será menor que 0; y sumará a 0.
fuente
r=0,
lugar der=[0]
?r+=[r[-1]+2*b-1]
conr+=r[-1]+2*b-1,
asíClojure, 118 bytes
Devuelve una secuencia de caracteres, así que lo llamaría así:
Primero voltea los corchetes, luego realiza un bucle siempre que la suma acumulada del recuento de corchetes sea negativa en algún punto de la secuencia.
fuente
brainfuck , 82 bytes
Pruébalo en línea!
Explicación
Con cada carácter leído, un contador se modifica de la siguiente manera:
)
, el contador aumenta en 1.(
, el contador disminuye en 1, a menos que el contador fuera 0, en cuyo caso el contador no cambia.Cada prefijo es un sufijo válido de una cadena equilibrada (después de la inversión) si y solo si este contador es 0. Este código usa el prefijo más largo para formar la salida.
fuente