Базовая Pyth-подобная проверка синтаксиса


25

Pyth - язык игры в гольф, основанный на Python. Он использует префиксную нотацию, каждая команда имеет разную арность (количество аргументов, которые она принимает).

Ваша задача - написать средство проверки синтаксиса для (несуществующего) языка, подобного Pyth, Pith.

Синтаксис Pith

У Pith есть только 8 команд с одним символом:

01234()"

01234у каждого есть арность соответствующего числа, и, следовательно, ожидайте, что после него будет много аргументов. Например,

400010

является правильной программой Pith, потому что 4за ней следуют четыре аргумента, 0 0 0а 10за последним 1следует единственный аргумент 0. Чтобы визуализировать это, мы можем взглянуть на следующее дерево:

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

где Rкорневой узел Альтернативный способ думать об этом состоит в том, что каждое число относится к числу дочерних элементов, которые соответствующий узел имеет в дереве выше.

Вот еще одна действительная программа Pith с более чем одной базовой командой:

210010

соответствует

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

С другой стороны,

3120102100

это не правильная программа Pith , поскольку исходный 3имеет только два аргумента, которые мы можем увидеть, посмотрев на дерево ниже:

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

Далее (начинается неограниченное, и )заканчивается неограниченное. Неограниченный принимает любое количество аргументов (жадно) и считается одним аргументом для любой родительской команды. Любые неограниченные, все еще открытые к концу программы, автоматически закрываются. )Команда не является ошибкой , если нет unboundeds открыты - это просто ничего не делает *.

Например, программа Pith

)31(0)0(201000100

соответствует дереву

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

Пустые неограниченные в порядке, так ()что действительная программа Pith.

Недопустимая программа Pith с неограниченной

12(010

так как 2только получает один аргумент (неограниченный).

Наконец, "начинается и заканчивается строка, которая всегда равна 0 арности и считается как один аргумент, например

2"010""44)()4"

которому просто 2передают два строковых аргумента "010"и "44)()4". Как и неограниченные, строки также могут быть пустыми, и любые незакрытые строки к концу программы автоматически закрываются.

* Эта часть отличается от оригинального Pyth, который на самом деле делает что-то в случае, например 1), завершает 1-арность и вызывает ошибку.

Ввод, вывод

Ввод будет единственной непустой строкой, состоящей только из символов 01234()". При желании вы можете предположить, что дополнительный трейлинг-перевод строки всегда присутствует. Вы можете написать функцию или полную программу для этой задачи.

Вы должны вывести истинное значение, если входной синтаксически правильный Pith, или ложное значение в противном случае. Значения true и false должны быть фиксированными, чтобы вы не могли выводить данные 1для одной действительной программы и 2для другой.

счет

Это код-гольф, поэтому выигрывает код в наименьшем количестве байтов.

Контрольные примеры

Truthy:

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(""))

Разве не должно быть дерева для 20100100 (в первом неограниченном примере) [( [2 [0] [1 [0] ] ] [0] [1 [0]] [0] ]? У того, который у вас есть, есть ветви 2, 0, 0, 1 и 0 - второго не должно быть.
bcsb1001

@ bcsb1001 Спасибо и исправлено. Я хотел показать, что неограниченные могут идти выше 4.
Sp3000

@Ypnypn есть тестовые случаи, говорящие, что допустимо иметь несколько корней
Оптимизатор

Не могли бы вы добавить контрольный пример для ())2)1))0"3())"))(который должен быть правдой, я думаю).
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Добавлено - это действительно так (так как в основном ()210""это происходит из-за отсутствия операций)
Sp3000

Ответы:


12

CJam, 65 байт

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

Черт возьми, я бы хотел, чтобы у CJam было Regex, тогда это могло быть выполнено менее чем за 50 байтов.

Основная идея состоит в том, чтобы продолжать сокращать материал до 0 т.е. 10к 0, 200к 0и так далее. Как только это будет сделано, мы уменьшаем все соответствующие кронштейны к 0, т.е. ()к 0, (0)к 0, (00)к 0и так далее. Мы повторяем время цикла L, где Lдлина ввода.

Входная строка изначально проходит дополнительную обработку, где мы подстраиваемся под несоответствие "и добавляем много, )чтобы компенсировать несоответствие(

Это гарантирует, что после всех итераций у нас останется 0(и не будет )) в строке.

Обновление - исправлена ​​ошибка, из-за которой неактивные игры верхнего уровня )считались вредными.

Расширение кода

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";

Попробуйте онлайн здесь или запустите весь пакет


11

Regex, PCRE аромат, 83 байта

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

Попробуй это здесь.

Regex, PCRE аромат, 85 байт

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

Попробуй это здесь.

Использовал некоторые идеи в ответе этого дан1111 .

Некоторые пояснения по поводу(?2)*(()(?1))? .


(?2)*(()(?1))?последний кусок головоломки, который я искал. Хорошая находка! ;)
Мартин Эндер

Если я (?2)*(()(?1))?правильно понимаю часть, эта (()(?1))?часть никогда не совпадает с чем-либо, поскольку (?2)*уже съедает все, что (()(?1))?может соответствовать, и эта конструкция используется для установки группы захвата 3, когда мы входим, (и отмены захвата группы 3, когда мы находимся за пределами ()конструкции (чтобы обеспечить соответствие непарный )).
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

4

lex, 182 байта (157 Вт / стек фиксированного размера)

Эти программы требуют, чтобы ввод был отдельной строкой допустимых символов с новой строкой в ​​конце.

%%
 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);

Приведенная выше программа будет segfault, если ей не хватит памяти, что теоретически может произойти, если вы дадите ей достаточно ( . Но поскольку segfault считается неудачей, я воспринимаю это как «ложь», хотя в описании проблемы не сказано, что делать, если ресурсов недостаточно.

Я сократил его на 157 байт, просто используя стек фиксированного размера, но это казалось обманом.

%%
 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);

Скомпилировать:

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

Тест:

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

Тестовый вывод:

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

Думаю, мне следовало бы прояснить ситуацию: вы можете предположить, что либо новая строка никогда не существует, либо всегда есть. Это помогает?
Sp3000

Можно ли использовать программу стека фиксированного размера, но установить размер стека равным длине ввода?
Исаак

@isaacg Так как ввод является стандартным, мы не имеем понятия, пока он не будет прочитан. Я мог бы легко написать драйвер, который использует командную строку arg или string, но у гольфа есть другие приоритеты. Динамический стек в 25 символов не плох по стандартам c, но я уверен, что он все еще может быть в гольфе.
Ричи

4

80386 Ассемблер, 97 байт

Шестнадцатеричный дамп:

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                                       .

Он проходит через вход один раз, помещая числа больше нуля в стек и уменьшая их при обработке нуля. Неограниченные обрабатываются как -1.

Прототип функции (в C) (функция возвращает 0, если недействительно, и 1, если допустимо):

int __cdecl test(char *in);

Эквивалентная сборка (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

Следующий код на C может использоваться с GCC в системе POSIX для тестирования:

#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 байта

Функция синтаксического анализа проходит по токенам по одному и строит дерево структуры программы. Недопустимые программы вызывают исключение, которое приводит к печати нуля (Falsy), в противном случае успешный анализ приводит к одному.

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

Вывод тестов, показывающих вывод парсера:

------------------------------------------------------------
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

Код перед минификатором:

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

Хорошее (ab) использование исключений! Вы можете сэкономить некоторые пробелы, поменяв местами порядок операндов ==в тестах - сначала указав строки, вы можете это сделать if')'==q. Я полагаю, что одно из breakутверждений может быть заменено f=0, так как это также выведет вас из while fцикла. Наконец, вместо assert x==yвы можете использовать 1/(x==y)для ZeroDivisionError. ;)
DLosc

@DLosc, спасибо за несколько очень полезных советов по игре в гольф. Если бы я был одним из лидеров в соревнованиях по гольфу, я бы использовал ваши идеи для участия в соревнованиях. Поскольку моя запись далека от конкурентной (в отношении гольфа), я бы предпочел оставить ее в качестве наиболее читабельного примера. Я отметил ваши умные методы, хотя для будущего использования ;-)
Logic Knight

1

Пип , 88 72 байта

Идея взята из CJam Оптимизатора . Мой первоначальный удар по проблеме с парсером рекурсивного спуска был ... довольно длинным.

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

Отформатировано с объяснением:

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

Интересные трюки:

  • Многие операторы работают поэтапно в списках и диапазонах. Так 0X,5, например, есть 0 X [0 1 2 3 4] == ["" "0" "00" "000" "0000"].
  • На несколько дней назад, тройная Rоператор eplace может взять список для любого из его аргументов: "abracadabra" R ["br" "ca"] 'bдает ababdaba, например. Я хорошо использую эту функцию zздесь.
  • Ложные значения в Pip включают пустую строку "", пустой список []и любой скаляр, который равен нулю. Таким образом, 0ложно, но также 0.0и "0000000". Эта функция иногда неудобна (чтобы проверить, пуста ли строка, нужно проверить ее длину, потому что "0"она тоже ложна), но для этой проблемы она идеальна.

1

Javascript (ES6), 289 288 285 282 278 244 241 230 байт

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,""))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.