Prueba si una cadena está entre paréntesis equilibrada

15

Llamamos a un grupo de padres el par abierto (, su par cercano )y todo lo que hay dentro de ellos.

Un grupo o cadena parenteral se llama entre paréntesis equilibrados si no contiene nada o solo 2 grupos parentales entre paréntesis.

Por ejemplo:

The string   "(()())()"      is parenthesly balanced
              (    )()       Because it contains exactly 2 parenthesly balanced parens groups
               ()()          The left one is parenthesly balanced because it contains 2 parenthesly balanced parens groups (balanced because they are empty). The right one is parenthesly balanced because it contains nothing.

Igualmente:

The string   "(()(()))()"    is not parenthesly balanced
              (      )()     Because it contains a parens group that is not parenthesly balanced: the left one
               ()(  )        The left one is not balanced because it contains a parens group that is not balanced: the right one
                  ()         The right one is not balanced because it only contains one balanced group.

Por lo tanto, una cadena entre paréntesis equilibrada o un grupo parens debería:

  • No contienen nada en absoluto.
  • O contenga solo y exactamente 2 grupos parensos equilibrados entre paréntesis. No debe contener nada más.

Tarea:

Su tarea es escribir una función o programa que verifique si una cadena dada es paréntesis balanceada o no.

Entrada:

La entrada será una cadena o lista de caracteres o algo similar. Puede suponer que la cadena solo constará de los caracteres '('y ')'. También puede suponer que cada par abierto (tendrá su par cercano ), así que no se preocupe por cadenas como "((("o ")("o "(())("...

Nota: Como se ha mencionado por @DigitalTrauma en su comentario abajo, que está bien subtitute el ()combo por otros caracteres (tales como <>, [], ...), si es que causa un trabajo adicional como escapar en algunos idiomas

Salida:

Cualquier cosa para indicar si la cadena está entre paréntesis equilibrada o no (verdadero o falso, 1 o 0, ...). Incluya en su respuesta lo que se espera que produzca su función / programa.

Ejemplos:

""                                        => True
"()()"                                    => True
"()(()())"                                => True
"(()(()(()())))(()())"                    => True
"(((((((()())())())())())())())()"        => True
"()"                                      => False
"()()()"                                  => False
"(())()"                                  => False
"()(()(())())"                            => False
"(()())(((((()())()))())())"              => False
"()(()()()())"                            => False
"()(()(()())()())"                        => False

¡Los dos últimos ejemplos realmente marcaron la diferencia!

¡La mejor de las suertes!

ibrahim mahrir
fuente
Cualquier cosa para indicar si la cadena está entre paréntesis balanceada o no ¿Se requiere una salida consistente, es decir, solo dos valores?
Luis Mendo
@LuisMendo Podrían ser categorías. es decir, valores de verdad para señalar la veracidad y valores de falsedad para indicar lo contrario. Por lo tanto, podría haber más, pero debería ser consistente de todos modos.
ibrahim mahrir
1
¿Está bien si tomo una lista binaria como entrada? Por ejemplo, "(()())()"se representaría como [0, 0, 1, 0, 1, 1, 0, 1]. Esto eliminaría la necesidad de convertir la entrada al código de caracteres y luego restar.
JungHwan Min
Pregunta relacionada: codegolf.stackexchange.com/questions/166457/…
Windmill Cookies el
1
@WindmillCookies No veo cómo se relaciona esto con este. Cosas totalmente diferentes. Incluso el concepto es diferente.
ibrahim mahrir

Respuestas:

8

Japt v2, 20 bytes

V="()"V¥iU1 eViV²1 V

¡Pruébalo en línea!

Al principio, todos entendieron mal el desafío y, aunque cada par de paréntesis tenía que contener un número par de subpares, cuando en realidad el desafío realmente pide 0 o 2 subpares. Así que aquí está mi respuesta revisada, usando la misma técnica que antes.

Todavía podemos resolver el desafío con un reemplazo recursivo. La cuestión es que, en lugar de simplemente eliminar todas las ocurrencias de ()(), debemos asegurarnos de que no haya nada más en el mismo contenedor además de ()()(en otras palabras, no ()()()()o nada por el estilo). Podemos hacer esto reemplazando recursivamente (()())con ().

El nuevo problema es que la entrada en sí no tiene un par de paréntesis externos (ya que eso no lo haría una cadena equilibrada entre paréntesis), lo que nos obliga a envolverlo en un par adicional para reducirlo por completo. Finalmente, el resultado final para las cadenas balanceadas es ahora en ()lugar de la cadena vacía, por lo que verificamos la igualdad en lugar de simplemente tomar el NOT lógico de la salida.

ETHproductions
fuente
7

sed 4.2.2, 30

:
s/(()())/()/
t
/^()()$\|^$/q1

Pruébalo en línea .

Esto devuelve un código de salida de shell de 1 para True y 0 para False.

:               # label
s/(()())/()/    # replace "(()())" with "()"
t               # jump back to label if above replacement matched
/^()()$\|^$/q1  # exit code 1 if remaining buffer is exactly "()()" or empty
                # otherwise exit with code 0
Trauma digital
fuente
7

Perl 5 -lp, 24 22 bytes

$_=/^((<(?1)?>){2})?$/

Pruébalo en línea! El enlace incluye casos de prueba. Editar: Guardado 2 bytes gracias a @JoKing. Explicación: solo una expresión regular recursiva. El grupo de captura externo representa una cadena equilibrada <seguida de una cadena equilibrada opcional seguida de un >, dos veces. Tenga en cuenta que la mayoría de las otras respuestas pueden usar ()s, pero esto cuesta dos bytes adicionales:

$_=/^((\((?1)?\)){2})?$/

Pruébalo en línea! El enlace incluye casos de prueba.

Neil
fuente
3
Dado que puede usar otros pares de paréntesis, puede guardar dos bytes usando<>
Jo King
1
@JoKing Casi todas las otras respuestas pudieron usar ()s, así que no pensé que fuera una comparación justa, sin embargo, veo que la respuesta APL de @ ngn también usa <>s, así que actualicé esta.
Neil
6

6502 rutina de código de máquina , 48 bytes

A0 00 84 FD A2 00 B1 FB F0 0E C8 C9 29 18 F0 06 8A 48 E6 FD 90 EE B0 0A E0 01
90 06 E0 02 38 D0 01 18 A5 FD F0 09 C6 FD 68 AA E8 B0 F5 90 D7 60

Espera un puntero a una cadena en $fb/ $fcque se espera que solo contenga (y ). Borra el indicador C (Carry) si la cadena está "paranthesely balanceada", la establece de otra manera (lo cual es un idioma típico en el 6502, establece carry "en caso de error"). No hace nada sensato en la entrada inválida.

Aunque el algoritmo es recursivo, no se llama a sí mismo (lo que necesitaría más bytes y haría que la posición del código dependiera), sino que mantiene una profundidad de recursión y utiliza ramificaciones "simples".

Desmontaje comentado

; function to determine a string is "paranthesly balanced"
;
; input:
;   $fb/$fc: address of the string
; output:
;   C flag set if not balanced
; clobbers:
;   $fd:     recursion depth
;   A,X,Y

 .isparbal:
A0 00       LDY #$00            ; string index
84 FD       STY $FD             ; and recursion depth
 .isparbal_r:
A2 00       LDX #$00            ; set counter for parantheses pairs
 .next:
B1 FB       LDA ($FB),Y         ; load next character
F0 0E       BEQ .done           ; end of string -> to final checks
C8          INY                 ; increment string index
C9 29       CMP #$29            ; compare with ')'
18          CLC                 ; and reset carry
F0 06       BEQ .cont           ; if ')' do checks and unwind stack
8A          TXA                 ; save counter ...
48          PHA                 ; ... on stack
E6 FD       INC $FD             ; increment recursion depth
90 EE       BCC .isparbal_r     ; and recurse
 .cont:
B0 0A       BCS .unwind         ; on previous error, unwind directly
 .done:
E0 01       CPX #$01            ; less than one parantheses pair
90 06       BCC .unwind         ; -> ok and unwind
E0 02       CPX #$02            ; test for 2 parantheses pairs
38          SEC                 ; set error flag
D0 01       BNE .unwind         ; if not 2 -> is error and unwind
18          CLC                 ; clear error flag
 .unwind:
A5 FD       LDA $FD             ; check recursion depth
F0 09       BEQ .exit           ; 0 -> we're done
C6 FD       DEC $FD             ; otherwise decrement
68          PLA                 ; get "pair counter" ...
AA          TAX                 ; ... from stack
E8          INX                 ; and increment
B0 F5       BCS .unwind         ; continue unwinding on error
90 D7       BCC .next           ; otherwise continue reading string
 .exit:
60          RTS

Ejemplo de programa ensamblador C64 usando la rutina:

Demostración en línea

captura de pantalla

Código en sintaxis ca65 :

.import isparbal   ; link with routine above

.segment "BHDR" ; BASIC header
                .word   $0801           ; load address
                .word   $080b           ; pointer next BASIC line
                .word   2018            ; line number
                .byte   $9e             ; BASIC token "SYS"
                .byte   "2061",$0,$0,$0 ; 2061 ($080d) and terminating 0 bytes

.bss
linebuf:        .res    256

.data
prompt:         .byte   "> ", $0
truestr:        .byte   "true", $0
falsestr:       .byte   "false", $0

.code
inputloop:
                lda     #<prompt        ; display prompt
                ldy     #>prompt
                jsr     $ab1e

                lda     #<linebuf       ; read string into buffer
                ldy     #>linebuf
                ldx     #0              ; effectively 256
                jsr     readline

                lda     #<linebuf       ; address of string to $fb/fc
                sta     $fb
                lda     #>linebuf
                sta     $fc
                jsr     isparbal        ; call function

                bcs     isfalse
                lda     #<truestr
                ldy     #>truestr
                bne     printresult
isfalse:        lda     #<falsestr
                ldy     #>falsestr
printresult:    jmp     $ab1e           ; output true/false and exit

; read a line of input from keyboard, terminate it with 0
; expects pointer to input buffer in A/Y, buffer length in X
.proc readline
                dex
                stx     $fb
                sta     $fc
                sty     $fd
                ldy     #$0
                sty     $cc             ; enable cursor blinking
                sty     $fe             ; temporary for loop variable
getkey:         jsr     $f142           ; get character from keyboard
                beq     getkey
                sta     $2              ; save to temporary
                and     #$7f
                cmp     #$20            ; check for control character
                bcs     checkout        ; no -> check buffer size
                cmp     #$d             ; was it enter/return?
                beq     prepout         ; -> normal flow
                cmp     #$14            ; was it backspace/delete?
                bne     getkey          ; if not, get next char
                lda     $fe             ; check current index
                beq     getkey          ; zero -> backspace not possible
                bne     prepout         ; skip checking buffer size for bs
checkout:       lda     $fe             ; buffer index
                cmp     $fb             ; check against buffer size
                beq     getkey          ; if it would overflow, loop again
prepout:        sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
output:         lda     $2              ; load character
                jsr     $e716           ;   and output
                ldx     $cf             ; check cursor phase
                beq     store           ; invisible -> to store
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and show
                ora     #$80            ;   cursor in
                sta     ($d1),y         ;   current row
                lda     $2              ; load character
store:          cli                     ; enable interrupts
                cmp     #$14            ; was it backspace/delete?
                beq     backspace       ; to backspace handling code
                cmp     #$d             ; was it enter/return?
                beq     done            ; then we're done.
                ldy     $fe             ; load buffer index
                sta     ($fc),y         ; store character in buffer
                iny                     ; advance buffer index
                sty     $fe
                bne     getkey          ; not zero -> ok
done:           lda     #$0             ; terminate string in buffer with zero
                ldy     $fe             ; get buffer index
                sta     ($fc),y         ; store terminator in buffer
                sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
                inc     $cc             ; disable cursor blinking
                cli                     ; enable interrupts
                rts                     ; return
backspace:      dec     $fe             ; decrement buffer index
                bcs     getkey          ; and get next key
.endproc
Felix Palmen
fuente
5

V , 21 , 20 bytes

é(Á)òÓ(“()()…)òø^()$

Pruébalo en línea! o Verifique todos los casos de prueba!

é(                      " Insert '(' at the beginning of the line
  Á)                    " Append ')' at the end
    ò         ò         " Recursively...
     Ó                  "   Remove...
      (                 "     '('
       “    …           "     (Limit the part that is removed to this section of the match)
        ()()            "     '()()'
             )          "     ')'
                        " (effectively, this replaces '(()())' with '()', but it's one byte shorter than the straightforward approach
               ø        " Count...
                ^()$    "   Lines containing exactly '()' and nothing more

Hexdump:

00000000: e928 c129 f2d3 2893 2829 2829 8529 f2f8  .(.)..(.()().)..
00000010: 5e28 2924                                ^()$
DJMcMayhem
fuente
¿Puede explicar su código para que pueda (con suerte) encontrar un caso de prueba que no funciona, como hice con la respuesta de @ Adàm .
ibrahim mahrir
@ibrahimmahrir Hecho.
DJMcMayhem
5

Brachylog , 28 bytes

Ẹ|~c["(",A,")(",B,")"]∧A;B↰ᵐ

Pruébalo en línea!

Explicación

                                    --  The string perfectly balanced iff
Ẹ                                   --      the string is empty
 |                                  --  or
  ~c["(",A,")(",B,")"]              --      the string can be written id the format of "($A)($B)"
                      ∧             --          where
                       A;B ᵐ        --          both A and B
                          ↰         --          are perfectly balanced
Kroppeb
fuente
4

C (gcc) , 113 bytes

p(a,r,e,n)char*a;{if(*a-40)return 1;for(r=1,e=0;e<2;r&=e++||*a==40)for(r*=n=p(++a);n+=*a++-40?~0:1;);r=r&&*a-40;}

Pruébalo en línea!

Explicación

p(a,r,e,n)char*a;{   // function and variable declaration
 if(*a-40)return 1;  // string does not start with '(', thus is empty
 for(r=1,e=0;e<2;    // r: return value, e: group id (look for exactly two groups)
 r&=e++||*a==40)     // after the first group, a second shall follow
  for(r*=n=p(++a);   // check that the group is itself balanced
  n+=*a++-40?~0:1;); // skip group
 r=r&&*a-40;}        // additionally, after those two groups there shall follow none

Pruébalo en línea!

Jonathan Frech
fuente
3

MATL , 26 25 bytes

oo~`tnw52B5LZttnb<]XB10X-

Pruébalo en línea!

Gracias a la respuesta de @ETHProductions por la idea "reemplazar (() ()) con ()", y al comentario de la pregunta de @JungHwan Min por la idea de ver los corchetes como dígitos binarios.

La salida es una matriz vacía para la verdad, un número positivo para falsey, que creo que está permitido por el comentario de OP: "Podría haber categorías. Es decir, valores de verdad para señalar la verdad y valores falsos para indicar lo contrario". Si no es así, podemos agregar nal final para +1 byte, para tener 0 como salida verdadera y 1 como salida falsey.

Con comentarios:

o         % Convert the parantheses to their ASCII codes
          %  40 for '(', 41 for ')'
o         % Parity - 1 for odd, 0 for even
~         % Not - change 0 to 1 and vice versa, so '(' is now 1 and ')' 0
          % Input char array is now a binary array B
`         % Do-while loop
  tn          % Get the length of the array 
  w           % Bring the array B back on top
  52B         % Push the binary value of 52 on stack
              %  [1 1 0 1 0 0] (equivalent to '(()())')
  5L          % Push the constant [1 0] for '()'
  Zt          % Replace the sequence [1 1 0 1 0 0] in array B
              %  with [1 0]
  tn          % Get the length of the array after replacement 
  b<          % Has it decreased? If so, continue loop
  ]       % end loop
          % Final value for balanced input will be
          %  either [1 0 1 0] for the remaining outer '()()'
          %  or an empty array [] for empty '' input
XB        % Convert the final binary array back to decimal
10X-      % Set difference, remove 10 from that result 
          % Result is [] empty array for balanced input, otherwise 
          %  some decimal number ≠ 10 for unbalanced input
sundar - Restablecer a Monica
fuente
3

Haskell , 82 59 bytes

all(`elem`[0,2]).foldl(#)[0]
b#'('=0:b
(x:y:z)#_=y+1:z++[x]

Pruébalo en línea!

Supongo que se puede jugar mucho más, ya que es la primera vez que juego golf en Haskell, por lo que cualquier truco o comentario es más que bienvenido.

EDITAR - Gracias @nimi por guardar 23 bytes (más del 28% del envío original :)

Vincent
fuente
1
Algunos consejos: no hay necesidad de la ()vuelta y+1. Como se permiten funciones sin nombre, puede descartar f=, r[0]es una función adecuada. Coloque el caso base r b[]al final y cambie a una función infija (digamos #), luego puede usar b#_=. También puede cambiar su algoritmo ligeramente mediante la construcción de la lista para comprobar si hay 0s y 2s paso a paso, en lugar de llevar a su alrededor las llamadas de ren un acumulador r(x:y:z) ... = x : r (...) acon el caso base r b [] = b. Haga la verificación después de la llamada inicial r[0]. En total, 73 bytes.
nimi
1
... o incluso mejor: quédese con el acumulador y cambie a foldl(59 bytes): ¡ Pruébelo en línea! .
nimi
@nimi Muchas gracias, exactamente el tipo de consejos que estaba buscando :)
Vincent
3

JavaScript (ES6), 63 bytes

Toma entrada como una matriz de caracteres. Devuelve falso para paréntesis equilibrado, verdadero para paréntesis no equilibrado.

a=>[...a,k=0].some(c=>c<')'?!(a[k]=-~a[k++]):a[k]=~5>>a[k--]&1)

Pruébalo en línea!

Comentado

a =>                     // a[] = input array of characters; we are going to reuse it to
  [                      // store the number of parenthesis groups at each depth
    ...a,                // append all characters
    k = 0                // initialize k = current depth to 0 and append a value that will
  ]                      // be treated as a final closing parenthesis for the root level
  .some(c =>             // for each character c in this array:
    c < ')' ?            //   if c is an opening parenthesis:
      !(                 //     increment the number of groups at the current depth
        a[k] = -~a[k++]  //     increment the depth
      )                  //     yield false
    :                    //   else:
      a[k] = ~5          //     make sure that the current depth contains either 0 or 2
             >> a[k--]   //     groups, by shifting the 1-complement of 5 (101 in binary)
             & 1         //     and testing the least significant bit
                         //     it resets the number of groups to 0 if the bit is not set
                         //     otherwise, it forces some() to return true
                         //     decrement the depth
  )                      // end of some()

Recursivo, 54 bytes

Usar reemplazos recursivos (como en Sin embargo, el la respuesta Japt de ETHproductions ) es significativamente más corto.

Toma la entrada como una cadena. Devuelve 1 para paréntesis balanceados, 0 para paréntesis no balanceados.

f=s=>s==(s=s.split`(()())`.join`()`)?!s|s=='()()':f(s)

Pruébalo en línea!


Recursivo, 46 ​​bytes

Este arroja un error de recursión para el paréntesis no equilibrado:

f=s=>!s|s=='()()'||f(s.split`(()())`.join`()`)

Pruébalo en línea!

Arnauld
fuente
No soy tan bueno en JavaScript, pero ¿podría x [k] = - ~ x [k ++] ser reemplazado por x [k] ++; k ++ o incluso ++ x [k ++]?
Андрей Ломакин
2
@ АндрейЛомакин No, porque x[k]inicialmente no está definido y x[k]++daría NaN, mientras que -~undefinedda 1.
Arnauld
@ АндрейЛомакин Ahora estoy reutilizando la matriz de entrada, por lo que a[k]inicialmente contiene un carácter. Pero la misma lógica se aplica a las cadenas: al aplicar el ++operador sobre ellas se obtienen rendimientos NaN, pero los operadores bit a bit (como ~) obligan a que se las coarte de 0antemano.
Arnauld
Lleva javascript a un nivel completamente nuevo. : D
ibrahim mahrir
3

Perl 6 ,  43 41  37 bytes

{my rule f{\([<&f>**2]?\)};?/^<&f>**2$|^$/}

Pruébalo

{(my$f)=/\([<$f>**2]?\)/;?/^[<$f>**2]?$/}

Pruébalo

{$!=/\([<$!>**2]?\)/;?/^[<$!>**2]?$/}

Pruébalo

Expandido:

{  # bare block lambda with implicit parameter $_

  $! = # store regex into $! (no need to declare it)
  /
    \(

      [
        <$!> ** 2 # recurse into regex twice
      ]?          # optionally

    \)
  /;


  ?      # boolify (causes it to be run against $_)

    /
      ^         # beginning of string

      <$!> ** 2 # match using regex twice

      $         # end of string

    |           # or

      ^ $       # empty string
    /
}
Brad Gilbert b2gills
fuente
3

R , 71 bytes

f=function(s,r=sub('(()())','()',s,f=T))'if'(r==s,s==''|s=='()()',f(r))

Pruébalo en línea!

  • portabilidad de la solución recursiva Japt de @ETHproductions
  • -2 bytes gracias a @JayCe

Otra solución, más larga, pero interesante para el enfoque diferente.

R , 85 bytes

g=gsub;!sum(eval(parse(t=g('\\)\\(',')-(',g('\\)','-1)',g('\\(','(2+',scan(,'')))))))

Pruébalo en línea!

Explicación

Toma la cadena de entrada y reemplaza:

'('  with '(2+'
')'  with '-1)'
')(' with ')-('

luego evalúa la expresión resultante. Si es igual a cero está equilibrado, de lo contrario no lo está. El uso desum solo es necesario para manejar el caso de cadena vacía, porque su evaluación regresa NULL.

p.ej

()(()()) => (2+-1)-(2+(2+-1)-(2+-1)-1) = 0
(()())   => (2+(2+-1)-(2+-1)-1)        = 1
digEmAll
fuente
Ahorre dos bytes:f=function(s,r=sub('(()())','()',s,f=T))'if'(r==s,s==''|s=='()()',f(r))
JayCe
Primero debe poner la solución más corta
solo ASCII el
@ Solo ASCII: tienes razón, pero dado que es básicamente una portabilidad de otra solución, parecía "robar": P
digEmAll
3
@digEmAll Pues bien, en una gran cantidad de desafíos aquí la mayor parte de los retos hacen solo puerto otra solución
ASCII de sólo
2

05AB1E , 18 16 13 bytes

…(ÿ)…(()∞„()©:®Q

Puerto de @ETHproductions respuesta Japt' s de solucionar el caso de prueba ()(()()(()())(()())).
-2 bytes gracias a @Adnan .

Basado en este comentario de OP , ahora lo uso ()como valor verdadero, y cualquier otra cosa como falsey. Si ambos valores deben ser consistentes en lugar de solo uno, sería la respuesta anterior de 16 bytes en su lugar ( …(ÿ)…(()∞„()©:®Q), regresando 0para verdades y 1para casos de prueba falsey.

Pruébelo en línea o verifique todos los casos de prueba .

Explicación

…(ÿ)             # Take the input (implicitly) and surround it with "(" and ")"
            :    # Infinite replacement of:
    …(()∞        #  "(()())"    ("(()" mirrored)
         „()     #  with "()"
                 # After the infinite replacement: return the result
                 # ("()" for truthy; falsey otherwise)

(Antigua respuesta de 18 bytes que falló para el caso de prueba ()(()()(()())(()()))...):

ΔD„()∞©6∍å_i®õ.:]Ā

Pruébelo en línea o verifique todos los casos de prueba .

Kevin Cruijssen
fuente
Creo que se puede utilizar el método de sustitución infinita: „()∞õ:g_.
Adnan
no, espera No entendí el desafío
Adnan
@Adnan También lo pensé al principio, pero falla para los casos de prueba que contienen los (()()()())que deberían devolver falsey. Cada grupo de paréntesis debe contener exactamente 0 o 2 grupos internos.
Kevin Cruijssen
1
Se puede reemplazar '(®')Jcon …(ÿ).
Adnan el
@Adnan Gracias! Sabía que ÿexistía, pero nunca lo usé antes, así que lo olvidé por completo.
Kevin Cruijssen
2

Prólogo , 46 bytes

a-->p,p.
a-->[].
p-->[l],a,[r].
f(X):-a(X,[]).

Pruébalo en línea! o Verifique todos los casos de prueba!

Utiliza listas de ly rcomo entrada, por ejemplo, "()()"se prueba comof([l,r,l,r]). .

Las primeras tres líneas son la gramática de cadenas válidas en la sintaxis Grammar de Cláusula Definitiva de Prolog . a(A,B).devuelve truecuando Aes una lista que sigue la gramática y Bestá vacía. Por lo tanto, la función principal ftoma algo Xy comprueba si se a(X,[])mantiene.

Laikoni
fuente
1

brainfuck, 50 bytes

,[<+>[-[->>]<[-[--[>->,]]>>]<]<[>>],]<[--[>->]]<+.

Formateado:

,
[
  <+>
  [
    -[->>]
    <
    [
      -
      [
        --
        [
          >->,
        ]
      ]
      >>
    ]
    <
  ]
  <[>>]
  ,
]
<
[
  --
  [
    >->
  ]
]
<+.

Espera una cadena de (y )sin una nueva línea final, y genera \x01true y \x00false. (Para legibilidad, por ejemplo, puede agregar 48 +s antes de la final .para que se imprima 1y en su 0lugar).

Pruébalo en línea

Esto mantiene una pila con el número de grupos en cada profundidad, distinguiendo los caracteres por paridad y verificando si el número de grupos está en {0, 2} después de cada paréntesis; si no se cumple la condición, consume el resto de la entrada y establece un indicador; luego verifica la condición nuevamente al final del programa.

Si se nos permite terminar la secuencia de entrada con un carácter impar, podemos omitir la verificación final <[--[>->]]para guardar 10 bytes. (Si \nno fuera inconveniente incluso, podría haber propuesto esta variante como la respuesta principal).

(También podríamos guardar algunos bytes cambiando el formato de salida a \x00verdadero y no \x00falso, lo que parece estar permitido (tal vez accidentalmente) por la declaración del problema tal como está escrita, pero de todos modos no sería muy interesante, y prefiero no para hacer ese cambio.)

Mitch Schwartz
fuente
1

Python2, 95 94 bytes

f=lambda i:g(eval("(%s)"%i.replace(")","),")))
g=lambda i:len(i)in(0,2)and all(g(j)for j in i)

Pruébalo en línea!

f () transforma la cadena en una tupla anidada, que pasa a g ().

g () navega recursivamente la tupla y devuelve False si algún elemento no tiene exactamente 0 o 2 hijos.

Guardado un byte mediante el formato de cadena.

Triggernometry
fuente
1

Stax , 13 11 bytes

₧aaS▐îî»Å·╢

Ejecutar y depurarlo

Ahorré dos bytes cuando me di cuenta de que las entradas se pueden evaluar de manera implícita como literales de matriz. Al eliminar las comillas dobles, la entrada se simplifica.

La idea general es evaluar la entrada como un literal de matriz y mapear recursivamente los elementos para verificar el equilibrio parental. Si la afirmación final falla alguna vez, habrá un pop posterior en una pila vacía. En stax, aparecer con pilas vacías termina inmediatamente el programa.

Desempaquetado, sin golf y comentado, se ve así.

        input is implicitly treated as array literals
L       wrap entire input stack in an array
G       jump to the trailing '}', and come back when done
}       terminate the program, the rest is a recursive call target
{Gm     map array on top of the stack by using the recursive call target
%       get the length of the mapped array
02\#    is the length one of [0, 2]?
|c      assert value is truthy, pop if not

Ejecute este

recursivo
fuente
1

Java 10, 99 96 95 83 bytes

s->{s="("+s+")";for(var p="";!p.equals(s);s=s.replace("(()())","()"))p=s;return s;}

El puerto de mi respuesta 05AB1E (también regresa ()como verdadero y cualquier otra cosa como falsey).

Pruébalo en línea.

Explicación:

s->{                 // Method with String as both parameter and return-type
  s="("+s+")";       //  Surround the input-String between "(" and ")"
  for(var p="";      //  Previous-String, starting empty
      !p.equals(s)   //  Loop as long as the previous and current Strings differ
      ;              //    After every iteration:
       s=s.replace("(()())","()"))
                     //     Replace all "(()())" with "()"
    p=s;             //   Set the previous String with the current
  return s;}         //  Return the modified input-String
                     //  (if it's now "()" it's truthy; falsey otherwise)

return s;puede ser return"()".equals(s);si se requiere un resultado booleano real.

Kevin Cruijssen
fuente
Puede guardar un byte si solo marca!s.contains("()()(")
Charlie
@Charlie Gracias, pero el código contenía un error de todos modos, así que tuve que cambiarlo. Ahora está arreglado (para el último caso de prueba falsey agregado), y se juega en 4 bytes al mismo tiempo.
Kevin Cruijssen