Podstawowy Pyth-Checker Syntax Checker

25

Pyth jest językiem golfowym opartym na Pythonie. Używa notacji przedrostkowej, przy czym każde polecenie ma inną aranżację (liczbę argumentów, które akceptuje).

Twoim zadaniem jest napisanie kontrolera składni dla (nieistniejącego) języka Pyth-a, Pith.

Składnia Pitha

Pith ma tylko 8 poleceń jednoznakowych:

01234()"

01234każdy ma arity o odpowiedniej liczbie, a zatem oczekują, że za nim pojawi się wiele argumentów. Na przykład,

400010

jest poprawnym programem Pith, ponieważ 4po nim następują cztery argumenty, 0 0 0a 10po ostatnim 1następuje pojedynczy argument 0. Aby to zwizualizować, możemy spojrzeć na następujące drzewo:

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

gdzie Rjest węzeł główny. Alternatywnym sposobem myślenia o tym jest to, że każda liczba odnosi się do liczby dzieci odpowiedniego węzła w powyższym drzewie.

Oto kolejny prawidłowy program Pith, zawierający więcej niż jedno polecenie podstawowe:

210010

odpowiadającej

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

Z drugiej strony,

3120102100

jest nie poprawna Program Pith ponieważ początkowa 3ma tylko dwa argumenty, które widzimy, patrząc na drzewa poniżej:

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

Następnie (rozpoczyna nieograniczony i )kończy nieograniczony. Nieograniczony przyjmuje dowolną liczbę argumentów (zachłannie) i liczy się jako pojedynczy argument do dowolnej komendy nadrzędnej. Wszelkie niezwiązane nadal otwarte do końca programu są automatycznie zamykane. )Polecenie nie jest błąd jeśli nie unboundeds są otwarte - po prostu nic nie robi *.

Na przykład program Pith

)31(0)0(201000100

odpowiada drzewu

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

Puste niezwiązane są w porządku, podobnie ()jak prawidłowy program Pith.

Niepoprawny program Pith z nieograniczonym jest

12(010

ponieważ 2tylko jeden otrzymuje argument (bez ograniczeń).

Wreszcie "rozpoczyna i kończy ciąg znaków, który zawsze ma wartość 0, i liczy się jako pojedynczy argument, np

2"010""44)()4"

który jest po prostu 2przesłaniem dwóch argumentów łańcuchowych "010"i "44)()4". Podobnie jak nieograniczone, łańcuchy mogą być również puste, a wszelkie niezamknięte łańcuchy do końca programu są automatycznie zamykane.

* Ta część różni się od oryginalnego Pytha, który faktycznie robi coś w takim przypadku 1), kończąc 1-arę i zgłaszając błąd.

Wejście wyjście

Dane wejściowe będą pojedynczym niepustym łańcuchem składającym się tylko z znaków 01234()". Opcjonalnie możesz założyć, że zawsze jest obecny dodatkowy znak nowej linii. Możesz napisać funkcję lub pełny program dla tego wyzwania.

Powinieneś wypisać prawdziwą wartość, jeśli dane wejściowe są poprawne pod względem składniowym Pith, lub wartość fałszowania w przeciwnym razie. Wartości prawdy i fałszu muszą być ustalone, aby nie można było generować danych wyjściowych1 dla jednego ważnego programu i 2dla innego.

Punktacja

To jest golf golfowy, więc kod w najmniejszej liczbie bajtów wygrywa.

Przypadki testowe

Prawda:

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(""))
Sp3000
źródło
Czy drzewo dla 20100100 nie powinno być (w pierwszym nieograniczonym przykładzie) [( [2 [0] [1 [0] ] ] [0] [1 [0]] [0] ]? Ten, który masz, ma oddziały 2, 0, 0, 1 i 0 - drugi nie powinien tam być.
bcsb1001
@ bcsb1001 Dzięki i poprawione. Chciałem pokazać, że nieograniczone mogą przekroczyć 4.
Sp3000
@Ypnypn istnieją przypadki testowe stwierdzające, że poprawne jest posiadanie wielu korzeni
Optymalizator
Czy mógłbyś dodać przypadek testowy ())2)1))0"3())"))(co, jak sądzę, powinno być prawdziwe).
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨dd
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Dodano - to jest rzeczywiście prawda (ponieważ jest w zasadzie ()210""z wieloma
brakami operacji

Odpowiedzi:

12

CJam, 65 bajtów

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

Rety, chciałbym, żeby CJam miał Regex, można by to zrobić w mniej niż 50 bajtów

Główną ideą jest dalsze redukowanie rzeczy do 0np. 10Do 0, 200do 0i tak dalej. Po wykonaniu tej czynności zmniejszamy wszystkie dopasowane nawiasy kwadratowe do 0, tj. ()Do 0, (0)do 0, (00)do 0itd. Powtarzamy Lczasy cyklu , gdzie Ljest długość wejściowa.

Łańcuch wejściowy początkowo przechodzi dodatkowe przetwarzanie, w którym dostosowujemy niedopasowane "i dodajemy wiele, )aby zrekompensować niedopasowane(

Zapewnia to, że po wszystkich iteracjach w łańcuchu pozostanie tylko 0(i brak )operacji).

Aktualizacja - naprawiono błąd, w którym )brak działania na najwyższym poziomie jest uważany za szkodliwy

Rozszerzenie kodu

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

Wypróbuj online tutaj lub uruchom cały pakiet

Optymalizator
źródło
11

Regex, smak PCRE, 83 bajty

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

Wypróbuj tutaj.

Regex, smak PCRE, 85 bajtów

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

Wypróbuj tutaj.

Wykorzystałem kilka pomysłów w odpowiedzi tego dan1111 .

Kilka wyjaśnień na temat(?2)*(()(?1))? .

jimmy23013
źródło
(?2)*(()(?1))?jest ostatnim elementem układanki, którego szukałem. Niezłe znalezisko! ;)
Martin Ender
Jeśli dobrze rozumiem (?2)*(()(?1))?część, (()(?1))?część nigdy niczego nie pasuje, ponieważ (?2)*zjada już wszystko, co (()(?1))?może się zgadzać, a ta konstrukcja służy do ustawiania grupy przechwytywania 3, gdy wchodzimy (i rozbrajania grupy przechwytywania 3, gdy jesteśmy poza ()konstrukcją (aby umożliwić dopasowanie niesparowany )).
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
4

Lex, 182 bajty (157 w / stos o stałym rozmiarze)

Programy te wymagają, aby dane wejściowe stanowiły ciąg prawidłowych znaków zakończony znakiem nowej linii.

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

Powyższy program ulegnie awarii, jeśli zabraknie mu pamięci, co teoretycznie może się zdarzyć, jeśli dasz mu wystarczająco dużo ( . Ale ponieważ segfault liczy się jako porażka, traktuję to jako „falsey”, chociaż opis problemu nie mówi, co zrobić, jeśli zasoby nie są wystarczające.

Zmniejszyłem go o 157 bajtów, używając stosu o stałej wielkości, ale wydawało się, że to oszustwo.

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

Kompilować:

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

Test:

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

Wyjście testowe:

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
rici
źródło
Myślę, że powinienem być nieco jaśniejszy - możesz założyć, że albo nowa linia nigdy nie istnieje, albo zawsze tam jest. To pomaga?
Sp3000,
Czy byłoby możliwe użycie programu stosu o stałym rozmiarze, ale ustawienie wielkości stosu na długość danych wejściowych?
isaacg
@isaacg Ponieważ dane wejściowe są standardowe, nie mamy pojęcia, dopóki nie zostaną odczytane. Mógłbym z łatwością napisać sterownik, który używa argumentu lub ciągu wiersza poleceń, ale golf ma inne priorytety. Dynamiczny stos w 25 znakach nie jest zły jak na standardy c, ale jestem pewien, że można go jeszcze zagrać w golfa.
rici
4

80386 Asembler, 97 bajtów

Zrzut szesnastkowy:

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                                       .

Przebiega to raz przez dane wejściowe, wypychając liczby większe niż zero na stos i zmniejszając je, gdy przetwarzane jest zero. Nieograniczone są przetwarzane jako -1.

Prototyp funkcji (w C) (funkcja zwraca 0, jeśli jest niepoprawna i 1, jeśli jest poprawna):

int __cdecl test(char *in);

Równoważny zespół (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

Do testowania GCC w systemie POSIX można użyć następującego kodu w C:

#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;
}
es1024
źródło
3

Python 2, 353 bajtów

Funkcja parsowania krok po kroku przechodzi przez tokeny i buduje drzewo struktury programu. Nieprawidłowe programy wywołują wyjątek, który powoduje wydrukowanie zera (Falsy), w przeciwnym razie pomyślne parsowanie spowoduje powstanie jednego.

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

Wynik testów pokazujących dane wyjściowe analizatora składni:

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

Kod przed minifikatorem:

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
Logic Knight
źródło
Ładne (ab) wykorzystanie wyjątków! Możesz zaoszczędzić trochę miejsca, zamieniając kolejność operandów ==w testach - umieszczenie ciągów na pierwszym miejscu oznacza, że ​​możesz to zrobić if')'==q. Wierzę, że jedno z breakoświadczeń można zastąpić f=0, ponieważ to również wydostanie się z while fpętli. Wreszcie, zamiast assert x==ymożesz użyć 1/(x==y)do ZeroDivisionError. ;)
DLosc
@DLosc, dziękuję za kilka bardzo przydatnych wskazówek golfowych. Gdybym był jednym z liderów zawodów golfowych, wykorzystałbym twoje pomysły do ​​rywalizacji. Ponieważ moje zgłoszenie jest dalekie od rywalizacji (pod względem golfowym), wolę pozostawić to jako czytelny przykład. Zauważyłem jednak twoje sprytne techniki do wykorzystania w przyszłości ;-)
Logic Knight
1

Pip , 88 72 bajtów

Pomysł zaczerpnięty z CJam Optimizera . Mój pierwotny problem z parserem rekurencyjnego zniżania był ... raczej dłuższy.

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

Sformatowane z wyjaśnieniem:

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

Ciekawe sztuczki:

  • Wielu operatorów pracuje pod względem pozycji na listach i zakresach. Tak 0X,5na przykład jest0 X [0 1 2 3 4] == ["" "0" "00" "000" "0000"] .
  • Jeszcze kilka dni temu trójskładnikowy Roperator eplace mógł pobrać listę dla dowolnego z argumentów: na przykład "abracadabra" R ["br" "ca"] 'bdaje ababdaba. zTutaj dobrze wykorzystuję tę funkcję .
  • Wartości Falsy w Pip obejmują pusty ciąg "", pustą listę []i każdy skalar, który jest równy zero. Tak więc 0jest fałszywe, ale także 0.0i "0000000". Ta funkcja jest czasami niewygodna (aby sprawdzić, czy łańcuch jest pusty, należy przetestować jego długość, ponieważ "0"jest również fałszywy), ale w przypadku tego problemu jest idealny.
DLosc
źródło
1

JavaScript (ES6), 289 288 285 282 278 244 241 230 bajtów

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,""))
SuperJedi224
źródło