Un verificador básico de sintaxis similar a Pyth


25

Pyth es un lenguaje de golf basado en Python. Utiliza la notación de prefijo, y cada comando tiene una aridad diferente (número de argumentos que acepta).

Su tarea es escribir un verificador de sintaxis para un lenguaje similar a Pyth (inexistente), Pith.

Sintaxis de médula

Pith solo tiene 8 comandos de un solo carácter:

01234()"

01234cada uno tiene una aridad del número correspondiente y, por lo tanto, esperan muchos argumentos después. Por ejemplo,

400010

es un programa Pith correcto porque 4está seguido por cuatro argumentos 0 0 0y 10, el último de los cuales es 1seguido por el argumento único 0. Para visualizar esto, podemos mirar el siguiente árbol:

      R
      |
      4
      |
-------------
|   |   |   |
0   0   0   1
            |
            0

donde Restá el nodo raíz Una forma alternativa de pensar sobre esto es que cada número se refiere al número de hijos que tiene el nodo correspondiente en el árbol de arriba.

Aquí hay otro programa Pith válido, con más de un comando base:

210010

correspondiente a

           R
           |
     -------------
     |           |
     2           1
     |           |
 ---------       0
 |       |
 1       0
 |
 0

Por otra parte,

3120102100

no es un programa Pith correcto porque la inicial 3solo tiene dos argumentos, que podemos ver mirando el árbol a continuación:

                R
                |
                3
                |
     ------------------------ ??
     |          |
     1          2
     |          |
     2        ------
     |        |    |
   ------     1    0
   |    |     |
   0    1     0
        |
        0

Luego (comienza un sin límite y )termina un sin límite. Un ilimitado toma cualquier número de argumentos (con avidez) y cuenta como un solo argumento para cualquier comando principal. Todos los ilimitados que todavía estén abiertos al final del programa se cerrarán automáticamente. Un )comando no es un error si no hay límites ilimitados abiertos, simplemente no hace nada. *

Por ejemplo, el programa Pith

)31(0)0(201000100

corresponde al árbol

            R
            |
            3
            |
    ------------------------------
    |       |                    |
    1       0                    (
    |                            |
    (              -----------------------------
    |              |      |      |      |      |
    0              2      0      0      1      0
                   |                    |
                -------                 0
                |     |
                0     1
                      |
                      0

Los ilimitados vacíos están bien, también lo ()es un programa Pith válido.

Un programa Pith inválido con un sin límite es

12(010

ya que el 2único recibe un argumento (el ilimitado).

Finalmente, "comienza y termina una cadena, que siempre es 0 aridad y cuenta como un solo argumento, por ejemplo

2"010""44)()4"

que es solo un 2ser pasado dos argumentos de cadena "010"y "44)()4". Al igual que los sin límites, las cadenas también pueden estar vacías, y cualquier cadena no cerrada al final del programa se cierra automáticamente.

* Esta parte es diferente del Pyth original, que en realidad hace algo en un caso como 1)terminar la aridad 1 y generar un error.

De entrada y salida

La entrada será una sola cadena no vacía que consta de solo los caracteres 01234()". Opcionalmente, puede suponer que siempre hay una nueva línea final adicional. Puede escribir una función o un programa completo para este desafío.

Debe generar un valor verdadero si la entrada es Pith sintácticamente válida, o un valor falso de lo contrario. Los valores verdadero y falso deben ser fijos, por lo que no puede generar 1un programa válido y2 otro.

Tanteo

Este es el código de golf, por lo que gana el código en la menor cantidad de bytes.

Casos de prueba

Verdad:

0
)
(
"
()
""
10
400010
210010
("")00
3"""""
(0)))0)1)0
2(2(2(0)0)0)0
2"010""44)()4"
)31(0)0(201000100
())2)1))0"3())"))
3("4321("301(0)21100"4")"123"00)40"121"31000""01010

Falsy

1
1(310
(1)0)
12(010
4"00010"
3120102100
20(2((0)(0)))
2(2(2(0)0)0)01)
4(0102)00)00000
2"00"("00"2(""))

¿No debería ser el árbol para 20100100 (en el primer ejemplo sin límites) [( [2 [0] [1 [0] ] ] [0] [1 [0]] [0] ]? El que tienes tiene ramas de 2, 0, 0, 1 y 0; el segundo no debería estar allí.
bcsb1001

@ bcsb1001 Gracias y corregido. Quería mostrar que los límites pueden ir por encima de 4.
Sp3000

@Ypnypn hay casos de prueba que dicen que es válido tener múltiples raíces
Optimizer

¿Podría agregar el caso de prueba para ())2)1))0"3())"))(que debería ser cierto, creo).
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Agregado: es realmente cierto (ya que es básicamente ()210""con muchas operaciones no
operativas

Respuestas:


12

CJam, 65 bytes

q'"/La+2%{0s*}:Z~_,:L')*+{L{4{)_Z+s/Z}/L{'(\Z')++/Z}/}*')-}2*0s-!

Gosh, desearía que CJam tuviera Regex, esto podría haberse completado en menos de 50 bytes

La idea principal es mantener la reducción de cosas para 0decir 10que 0, 200a 0y así sucesivamente. Una vez hecho esto, reducimos todos los soportes adaptados a 0, es decir, ()a 0, (0)a 0, (00)a 0, y así sucesivamente. Luego repetimos los Ltiempos de ciclo , donde Les la longitud de entrada.

La cadena de entrada inicialmente pasa por un procesamiento adicional donde ajustamos para que no coincida "y agreguemos muchos )para compensar para que no coincida(

Esto asegura que después de todas las iteraciones, solo deberíamos tener 0(y no-op )) en la cadena.

Actualización: se corrigió un error por el cual )las operaciones sin nivel superior se consideran dañinas

Expansión de código

q'"/La+2%{0s*}:Z~_,:L')*      "Part 1 - Preprocessing";
q'"/                          "Read the input and split it on quote";
    La+                       "Add an extra empty array to the split array to compensate";
                              "for unmatched ending quote";
        2%                    "Take every other splitted part, ignoring the contents";
                              "of the strings in the code";
          {0s*}:Z~            "Join the parts by string 0. Also create a function Z";
                              "that does that for future use. We are now done with";
                              "reducing "XYZ" to 0 ";
                  _,:L        "Store the length of the remaining code in L";
                      ')*     "Append L ) to the string to compensate for unmatched (";

{L{4{)_Z+s/Z}/L{'(\Z')++/Z}/}*')-}2*   "Part 2 - the reducing loop";
 L{                         }*         "Run the reduction logic L times";
   4{)_Z+s/Z}/                         "Part 2a - reducing arities";
   4{       }/                         "Run the iteration for 0, 1, 2 and 3";
     )_                                "Increment the iteration number and make a copy";
       Z+s                             "Get that many 0 and append it to the number";
          /Z                           "Split the code onto this number and convert it";
                                       "to 0. This successfully reduces 10, 200, ";
                                       "3000 and 4000 to 0";
              L{'(\Z')++/Z}/           "Part 2b - reducing groups";
              L{          }/           "Run the iteration for 0 through L - 1";
                '(\Z')++               "Get the string '(<iteration number of 0>)'";
                        /Z             "split on it and join by 0. This successfully";
                                       "reduces (), (0), (00) and so on .. to 0";
                              ')-      "After running the part 2 loop L times, all";
                                       "reducible arities and brackets should be reduced";
                                       "except for cases like '30)00' where the no-op )";
                                       "breaks the flow. So we remove ) from the code";
                                       "and run Part 2 L times again";

0s-!                          "Now, if the code was valid, we should only have 0 in the";
                              "remaining code. If not, the code was invalid";

Pruébelo en línea aquí o ejecute toda la suite


11

Regex, sabor PCRE, 83 bytes

^(?3)*\)*$(()((?(2)|\)*)(\((?1)*(\)|$)|0|"[^"]*.?|(1|(2|(3|4(?3))(?3))(?3))(?3))))?

Pruébalo aquí.

Regex, sabor PCRE, 85 bytes

^((?(3)|\)*)(?>\((?2)*(()(?1))?(\)|$)|0|"[^"]*.?|(1|(2|(3|4(?1))(?1))(?1))(?1)))*\)*$

Pruébalo aquí.

Usé algunas ideas en la respuesta de este dan1111 .

Algunas explicaciones sobre(?2)*(()(?1))? .


(?2)*(()(?1))?es la pieza final del rompecabezas que estaba buscando. Buen hallazgo! ;)
Martin Ender

Si entiendo la (?2)*(()(?1))?parte correctamente, la (()(?1))?parte nunca coincide con nada, ya que (?2)*ya se come todo lo que (()(?1))?puede coincidir, y esta construcción se usa para establecer el grupo de captura 3 cuando ingresamos (y desarmar el grupo de captura 3 cuando estamos fuera de la ()construcción (para permitir la coincidencia sin emparejar )).
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

4

lex, 182 bytes (157 con pila de tamaño fijo)

Estos programas requieren que la entrada sea una única cadena terminada de nueva línea de caracteres válidos.

%%
 int n=0,s=0,*t=0;
[0-4] n+=*yytext-48-!!n;
\( (t=realloc(t,(s+1)*sizeof n))[s++]=n-!!n;n=0;
\) if(s&&n)exit(1);s&&(n=t[--s]);
\"[^"]*.? n-=!!n;
\n while(s)t[--s]&&n++;exit(!!n);

El programa anterior se segfault si se queda sin memoria, lo que en teoría podría suceder si le das suficiente ( . Pero dado que una falla predeterminada cuenta como falla, lo estoy tomando como "falsey", aunque la descripción del problema no dice qué hacer si los recursos no son suficientes.

Lo reduje 157 bytes simplemente usando una pila de tamaño fijo, pero eso parecía una trampa.

%%
 int n=0,s=0,t[9999];
[0-4] n+=*yytext-48-!!n;
\( t[s++]=n-!!n;n=0;
\) if(s&&n)exit(1);s&&(n=t[--s]);
\"[^"]*.? n-=!!n;
\n while(s)t[--s]&&n++;exit(!!n);

Compilar:

flex -o pith.c pith.l    # pith.l is the above file
c99 -o pith pith.c -lfl

Prueba:

while IFS= read -r test; do
  printf %-78s "$test"
  if ./pith <<<"$test"; then echo "OK"; else echo "NO"; fi
done <<EOT
0
)
(
"
()
""
10
400010
210010
("")00
3"""""
2(2(2(0)0)0)0
2"010""44)()4"
)31(0)0(201000100
3("4321("301(0)21100"4")"123"00)40"121"31000""01010
1
1(310
12(010
4"00010"
3120102100
20(2((0)(0)))
2(2(2(0)0)0)01)
4(0102)00)00000
2"00"("00"2(""))
EOT

Prueba de salida:

0                                                                             OK
)                                                                             OK
(                                                                             OK
"                                                                             OK
()                                                                            OK
""                                                                            OK
10                                                                            OK
400010                                                                        OK
210010                                                                        OK
("")00                                                                        OK
3"""""                                                                        OK
2(2(2(0)0)0)0                                                                 OK
2"010""44)()4"                                                                OK
)31(0)0(201000100                                                             OK
3("4321("301(0)21100"4")"123"00)40"121"31000""01010                           OK
1                                                                             NO
1(310                                                                         NO
12(010                                                                        NO
4"00010"                                                                      NO
3120102100                                                                    NO
20(2((0)(0)))                                                                 NO
2(2(2(0)0)0)01)                                                               NO
4(0102)00)00000                                                               NO
2"00"("00"2(""))                                                              NO

Supongo que debería haber sido un poco más claro: puede suponer que la nueva línea nunca está allí o siempre está allí. ¿Eso ayuda?
Sp3000

¿Sería posible usar el programa de pila de tamaño fijo, pero establecer el tamaño de la pila a la longitud de la entrada?
isaacg

@isaacg Dado que la entrada es estándar, no tenemos idea hasta que se lea. Podría haber escrito fácilmente un controlador que utiliza una línea de comando arg o cadena pero el golf tiene otras prioridades. La pila dinámica en 25 caracteres no es mala para los estándares c, pero estoy seguro de que todavía se puede jugar al golf.
rici

4

80386 Ensamblador, 97 bytes

Volcado hexadecimal:

0000000: 8b54 2404 5589 e531 c96a ff8a 022c 303c  .T$.U..1.j...,0<
0000010: f275 04f6 d530 c084 ed75 263c f875 0141  .u...0...u&<.u.A
0000020: 3cf9 750f 84c9 7419 4958 3c00 7c03 50eb  <.u...t.IX<.|.P.
0000030: 2430 c084 c075 0958 483c ff7f 0140 ebf3  $0...u.XH<...@..
0000040: 5042 8a02 84c0 75c5 4a84 edb0 2275 be84  PB....u.J..."u..
0000050: c9b0 2975 b85a 31c0 39e5 7501 4089 ec5d  ..)u.Z1.9.u.@..]
0000060: c3                                       .

Esto se ejecuta a través de la entrada una vez, empujando números mayores que cero en la pila y decrementándolos cuando se procesa un cero. Los ilimitados se procesan como -1.

Prototipo de función (en C) (la función devuelve 0 si no es válido y 1 si es válido):

int __cdecl test(char *in);

Ensamblaje equivalente (NASM):

bits 32
; get input pointer into edx
mov edx, [esp+4]                ; 8B 54 24 04

; save ebp; set ebp = esp
push ebp                        ; 55
mov ebp, esp                    ; 89 E5

; clear ecx
xor ecx, ecx                    ; 31 C9

; push base -1
push byte(-1)                   ; 6A FF

; get top char
mov al, [edx]                   ; 8A 02

    sub al, 0x30                ; 2C 30

    ; if al == quote
    cmp al, 0xF2                ; 3C F2
    jne $+6                     ; 75 04
        ; set ch (in quote?) to opposite
        not ch                  ; F6 D5
        ; set value to 0
        xor al, al              ; 30 C0

    ; if in quote, continue
    test ch, ch                 ; 84 ED
    jnz $+40                    ; 75 26

    cmp al, 0xF8                ; 3C F8
    jne $+3                     ; 75 01
        ; increment cl=depth
        inc ecx                 ; 41

    cmp al, 0xF9                ; 3C F9
    jne $+17                    ; 75 0F
        ; check depth = 0
        test cl, cl             ; 84 C9
        jz $+27                 ; 74 19
        ; decrement cl=depth
        dec ecx                 ; 49
        ; pop and check -1
        pop eax                 ; 58
        cmp al, 0               ; 3C 00
        jl $+5                  ; 7C 03
            push eax            ; 50
            jmp $+38            ; EB 24
        xor al, al              ; 30 C0

    test al, al                 ; 84 C0
    jnz $+11                    ; 75 09
        pop eax                 ; 58
        dec eax                 ; 48
        cmp al, -1              ; 3C FF
        jg $+3                  ; 7F 01
            inc eax             ; 40
        jmp $-11                ; EB F3
    push eax                    ; 50

    inc edx                     ; 42
    mov al, [edx]               ; 8A 02
    test al, al                 ; 84 C0
    jnz $-57                    ; 75 C5

    dec edx                     ; 4A

    ; in quote?
    test ch, ch                 ; 84 ED
    mov al, 0x22                ; B0 22
    jnz $-64                    ; 75 BE

    ; depth not zero?
    test cl, cl                 ; 84 C9
    mov al, 0x29                ; B0 29
    jnz $-70                    ; 75 B8

; pop base -1
pop edx                         ; 5A

; set return value based on ebp/esp comparison
xor eax, eax                    ; 31 C0
cmp ebp, esp                    ; 39 E5
jne $+3                         ; 75 01
inc eax                         ; 40
; restore esp
mov esp, ebp                    ; 89 EC
; restore ebp
pop ebp                         ; 5D
; return
ret                             ; C3

El siguiente código en C se puede usar con GCC en un sistema POSIX para probar:

#include <sys/mman.h>
#include <stdio.h>
#include <string.h>

int main(){
    char code[] = {
        0x8b, 0x54, 0x24, 0x04, 0x55, 0x89, 0xe5, 0x31, 0xc9, 0x6a, 0xff,
        0x8a, 0x02, 0x2c, 0x30, 0x3c, 0xf2, 0x75, 0x04, 0xf6, 0xd5, 0x30, 
        0xc0, 0x84, 0xed, 0x75, 0x26, 0x3c, 0xf8, 0x75, 0x01, 0x41, 0x3c, 
        0xf9, 0x75, 0x0f, 0x84, 0xc9, 0x74, 0x19, 0x49, 0x58, 0x3c, 0x00, 
        0x7c, 0x03, 0x50, 0xeb, 0x24, 0x30, 0xc0, 0x84, 0xc0, 0x75, 0x09, 
        0x58, 0x48, 0x3c, 0xff, 0x7f, 0x01, 0x40, 0xeb, 0xf3, 0x50, 0x42, 
        0x8a, 0x02, 0x84, 0xc0, 0x75, 0xc5, 0x4a, 0x84, 0xed, 0xb0, 0x22, 
        0x75, 0xbe, 0x84, 0xc9, 0xb0, 0x29, 0x75, 0xb8, 0x5a, 0x31, 0xc0, 
        0x39, 0xe5, 0x75, 0x01, 0x40, 0x89, 0xec, 0x5d, 0xc3,
    };
    void *mem = mmap(0, sizeof(code), PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
    memcpy(mem, code, sizeof(code));
    int __cdecl (*test)(char *) = (int __cdecl (*)(char *)) mem;

    #define TRY(s) printf(s ": %d\n", test(s))

    printf("Truthy tests:\n");
    TRY("0");
    TRY(")");
    TRY("(");
    TRY("\"");
    TRY("()");
    TRY("\"\"");
    TRY("10");
    TRY("400010");
    TRY("210010");
    TRY("(\"\")00");
    TRY("3\"\"\"\"\"");
    TRY("(0)))0)1)0");
    TRY("2(2(2(0)0)0)0");
    TRY("2\"010\"\"44)()4\"");
    TRY(")31(0)0(201000100");
    TRY("())2)1))0\"3())\"))");
    TRY("3(\"4321(\"301(0)21100\"4\")\"123\"00)40\"121\"31000\"\"01010");

    printf("\nFalsy tests:\n");
    TRY("1");
    TRY("1(310");
    TRY("(1)0)");
    TRY("12(010");
    TRY("4\"00010\"");
    TRY("3120102100");
    TRY("20(2((0)(0)))");
    TRY("2(2(2(0)0)0)01)");
    TRY("4(0102)00)00000");
    TRY("2\"00\"(\"00\"2(\"\"))");

    munmap(mem, sizeof(code));
    return 0;
}

3

Python 2, 353 bytes

La función de análisis recorre los tokens de uno en uno y crea un árbol de la estructura del programa. Los programas no válidos desencadenan una excepción que hace que se imprima un cero (Falsy), de lo contrario, el análisis exitoso da como resultado uno.

def h(f,k=0):
 b=[]
 if k:
  while f:b+=[h(f)]
  return b
 q=f.pop(0)
 if q==')':return[]
 elif q=='"':
  while f:
   q+=f.pop(0)
   if q[-1]=='"':break
 elif q=='(':
  while f:
   if f and f[0]==')':f.pop(0);break
   b+=h(f)
 else:
  for i in range(int(q)):b+=h(f)
  assert len(b)==int(q)
 return[[q,b]]
try:h(list(raw_input()));r=1
except:r=0
print r

La salida de las pruebas que muestran la salida del analizador:

------------------------------------------------------------
True: 0
    0

------------------------------------------------------------
True: )

------------------------------------------------------------
True: (
    (

------------------------------------------------------------
True: "
    "

------------------------------------------------------------
True: ()
    (

------------------------------------------------------------
True: ""
    ""

------------------------------------------------------------
True: 10
    1
        0

------------------------------------------------------------
True: 400010
    4
        0
        0
        0
        1
            0

------------------------------------------------------------
True: 210010
    2
        1
            0
        0
    1
        0

------------------------------------------------------------
True: ("")00
    (
        ""
    0
    0

------------------------------------------------------------
True: 3"""""
    3
        ""
        ""
        "

------------------------------------------------------------
True: 2(2(2(0)0)0)0
    2
        (
            2
                (
                    2
                        (
                            0
                        0
                0
        0

------------------------------------------------------------
True: 2"010""44)()4"
    2
        "010"
        "44)()4"

------------------------------------------------------------
True: )31(0)0(201000100
    3
        1
            (
                0
        0
        (
            2
                0
                1
                    0
            0
            0
            1
                0
            0

------------------------------------------------------------
True: 3("4321("301(0)21100"4")"123"00)40"121"31000""01010
    3
        (
            "4321("
            3
                0
                1
                    (
                        0
                2
                    1
                        1
                            0
                    0
            "4"
        "123"
        0
    0
    4
        0
        "121"
        3
            1
                0
            0
            0
        ""
    0
    1
        0
    1
        0

------------------------------------------------------------
False: 1
0
------------------------------------------------------------
False: 1(310
0
------------------------------------------------------------
False: 12(010
0
------------------------------------------------------------
False: 4"00010"
0
------------------------------------------------------------
False: 3120102100
0
------------------------------------------------------------
False: 20(2((0)(0)))
0
------------------------------------------------------------
False: 2(2(2(0)0)0)01)
0
------------------------------------------------------------
False: 4(0102)00)00000
0
------------------------------------------------------------
False: 2"00"("00"2(""))
0

El código antes del minificador:

def parse(tokens, first=False):
    toklist = []
    if first:
        while tokens :
            toklist += [parse(tokens)]
        return toklist
    tok = tokens.pop(0)
    if tok == ')' :
        return []
    elif tok == '"':
        while tokens:
            tok += tokens.pop(0)
            if tok[-1] == '"' :
                break
    elif tok == '(':
        while tokens:
            if tokens and tokens[0] == ')' :
                tokens.pop(0);
                break
            toklist += parse(tokens)
    else:
        for i in range(int(tok)) :
            toklist += parse(tokens)
        assert len(toklist) == int(tok)
    return [[tok, toklist]]

try :
    parse(list(raw_input()));
    r = 1
except :
    r = 0
print r

¡Buen uso (ab) de excepciones! Puede guardar algunos espacios intercambiando el orden de los operandos ==en las pruebas; poner las cadenas primero significa que puede hacerlo if')'==q. Creo que una de las breakdeclaraciones podría reemplazarse f=0, ya que eso también lo sacará del while fcírculo. Finalmente, en lugar de assert x==yque pueda usar 1/(x==y)para a ZeroDivisionError. ;)
DLosc

@DLosc, gracias por algunos consejos de golf muy útiles. Si estuviera entre los líderes en la competencia de golf, usaría sus ideas para competir. Como mi entrada está lejos de ser competitiva (en cuanto al golf), preferiría dejarla como un ejemplo en su mayoría legible. Sin embargo, he notado sus ingeniosas técnicas para uso futuro ;-)
Logic Knight

1

Pip , 88 72 bytes

Idea tomada de Optimizer's CJam . Mi puñalada original sobre el problema con un analizador de descenso recursivo fue ... bastante más larga.

Qpz:,5.iX,5AL'(.0X,#p.')p^:'"Fj,#pIj%2p@j:0p:Jpp.:')X#pL#ppR:z0!pRM')Rz0

Formateado, con explicación:

Qp                Query user for p
z:                Store the following list in z:
  ,5 . 0X,5         For x in range(5), concatenate x zeros to it
  AL                (append list)
  '(. 0X,#p .')     For x in range(len(p)), concatenate x zeros inside parens
p^: '"            Split p on " and assign result back to p
Fi,#p             Loop over the indices of the resulting list:
 Ii%2               If index is odd:
  p@i:0               Replace that item with 0
p: Jp             Concatenate the results and assign back to p
p.: ')X#p         Append len(p) closing parens to p
L#p               Loop len(p) times:
 pR:z0              Replace every occurrence in p of items of z with 0
! pRM')Rz0        Remove ) from result and replace z with 0 one more time; then
                  take logical negation, which will be true iff string is empty OR
                  consists only of zeros

Trucos interesantes:

  • Muchos operadores trabajan por elementos en listas y rangos. Entonces 0X,5, por ejemplo, es 0 X [0 1 2 3 4] == ["" "0" "00" "000" "0000"].
  • A partir de hace unos días, el Roperador ternario eplace puede tomar una lista de cualquiera de sus argumentos: "abracadabra" R ["br" "ca"] 'bda ababdaba, por ejemplo. Hago un buen uso de esta función conz aquí.
  • Los valores de falsa en Pip incluyen la cadena ""vacía [], la lista vacía y cualquier escalar que sea cero. Por lo tanto, 0es falso, pero también 0.0y "0000000". Esta característica es inconveniente a veces (para probar si una cadena está vacía, uno debe probar su longitud porque también "0"es falsa), pero para este problema es perfecta.

1

Javascript (ES6), 289 288 285 282 278 244 241 230 bytes

c=prompt(k="0"),j=c[l="length"];if((c.match(/"/g)||[])[l]%2)c+='"';c=c[R="replace"](/".*?"/g,k);c+=")".repeat(j);while(j--)c=c[R](/\(0*\)/,k)[R](/10/g,k)[R](/200/g,k)[R](/3000/g,k)[R](/40000/g,k);alert(!c[R](/0/g,"")[R](/\)/g,""))
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.