Ein grundlegender Pyth-ähnlicher Syntax Checker

25

Pyth ist eine auf Python basierende Golfsprache . Es wird die Präfixnotation verwendet, wobei jeder Befehl eine andere Arität hat (Anzahl der akzeptierten Argumente).

Ihre Aufgabe ist es, einen Syntax-Checker für eine (nicht existierende) Pyth-ähnliche Sprache, Pith, zu schreiben.

Markensyntax

Pith hat nur 8 Single-Char-Befehle:

01234()"

01234Jeder hat die Arität der entsprechenden Zahl und erwartet daher viele Argumente danach. Beispielsweise,

400010

ist ein korrektes Pith-Programm, da 4auf dieses vier Argumente folgen 0 0 0und auf 10das letzte ein 1einzelnes Argument folgt 0. Um dies zu veranschaulichen, können wir uns den folgenden Baum ansehen:

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

wo Rist der Wurzelknoten. Eine alternative Möglichkeit, dies zu überdenken, besteht darin, dass sich jede Zahl auf die Anzahl der untergeordneten Knoten im obigen Baum bezieht.

Hier ist ein weiteres gültiges Pith-Programm mit mehr als einem Basisbefehl:

210010

korrespondierend zu

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

Auf der anderen Seite,

3120102100

ist kein korrektes Pith-Programm, da die Initiale 3nur zwei Argumente enthält, die wir anhand des folgenden Baums erkennen können:

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

Als nächstes (beginnt eine unbegrenzte und )endet eine unbegrenzte. Ein unbegrenztes Argument akzeptiert eine beliebige Anzahl von Argumenten (gierig) und zählt als ein einziges Argument für jeden übergeordneten Befehl. Am Ende des Programms noch offene unbegrenzte Karten werden automatisch geschlossen. Ein )Befehl ist kein Fehler, wenn keine unbegrenzten Möglichkeiten offen sind - er führt einfach nichts aus. *

Zum Beispiel das Mark-Programm

)31(0)0(201000100

entspricht dem Baum

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

Leere unbegrenzte Felder sind in Ordnung, ebenso ()ein gültiges Pith-Programm.

Ein ungültiges Pith-Programm mit einem unbegrenzten ist

12(010

da 2bekommt der nur ein argument (das unbegrenzte).

Schließlich "beginnt und endet ein String, der immer 0 ist und als einzelnes Argument zählt, z

2"010""44)()4"

Das ist nur ein 2Wesen, dem zwei String-Argumente übergeben werden "010"und "44)()4". Wie unbegrenzte Zeichenfolgen können auch Zeichenfolgen leer sein, und nicht geschlossene Zeichenfolgen am Ende des Programms werden automatisch geschlossen.

* Dieser Teil unterscheidet sich von dem ursprünglichen Pyth, der in einem Fall wie dem Beenden der 1-Arität und dem Auslösen eines Fehlers tatsächlich etwas tut1) .

Input-Output

Die Eingabe ist eine einzelne nicht leere Zeichenfolge, die nur aus den Zeichen besteht 01234()". Optional können Sie davon ausgehen, dass immer eine zusätzliche nachgestellte Zeile vorhanden ist. Sie können eine Funktion oder ein vollständiges Programm für diese Herausforderung schreiben.

Sie sollten einen Wahrheitswert ausgeben, wenn die Eingabe syntaktisch gültig ist, oder einen falschen Wert, wenn dies nicht der Fall ist. Die Wahrheits- und Falschheitswerte müssen festgelegt werden, damit Sie nicht 1für ein gültiges Programm und 2für ein anderes ausgeben können .

Wertung

Das ist Code-Golf, also gewinnt der Code mit den wenigsten Bytes.

Testfälle

Wahrheit:

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

Falsch:

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
quelle
Sollte der Baum für 20100100 (im ersten unbegrenzten Beispiel) nicht sein [( [2 [0] [1 [0] ] ] [0] [1 [0]] [0] ]? Der eine hat Zweige von 2, 0, 0, 1 und 0 - der zweite sollte nicht da sein.
bcsb1001
@ bcsb1001 Danke und korrigiert. Ich wollte zeigen, dass unbegrenzt über 4 gehen kann.
Sp3000
@Ypnypn Es gibt Testfälle, die besagen, dass es gültig ist, mehrere Wurzeln zu haben
Optimizer
Würden Sie bitte den Testfall für hinzufügen ())2)1))0"3())"))(was meiner Meinung nach zutreffen sollte).
n̴̖̋h̴̖̋a̷̭̿h̷̭̿d̸̡̅ẗ̵̨́
@ n̴̖̋h̷͉̃a̷̭̿h̷̭̿d̷̰̀ĥ̷̳ Hinzugefügt - es ist in der Tat wahr (da es im Grunde ()210""mit vielen No-Ops ist)
Sp3000

Antworten:

12

CJam, 65 Bytes

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

Meine Güte, ich wünschte, CJam hätte Regex, dies hätte dann in weniger als 50 Bytes abgeschlossen werden können

Die Hauptidee ist zu halten Sachen zu reduzieren , 0dh 10auf 0, 200um 0und so weiter. Sobald dies geschehen ist, reduzieren wir alle aufeinander abgestimmt Klammern 0, also ()zu 0, (0)zu 0, (00)zu 0und so weiter. Das wiederholen wir die Zykluszeiten L, wobei Ldie Eingangslänge ist.

Die Eingabezeichenfolge durchläuft anfangs eine zusätzliche Verarbeitung, bei der wir die Nichtübereinstimmung korrigieren "und viel hinzufügen, um die Nichtübereinstimmung )zu kompensieren(

Dies stellt sicher, dass nach all den Iterationen nur 0(und kein-op )) in der Zeichenfolge übrig bleibt.

Update - Fehler behoben, durch den )No- Ops der obersten Ebene als schädlich eingestuft wurden

Code-Erweiterung

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

Probieren Sie es hier online aus oder führen Sie die gesamte Suite aus

Optimierer
quelle
11

Regex, PCRE-Geschmack, 83 Bytes

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

Probieren Sie es hier aus.

Regex, PCRE-Geschmack, 85 Bytes

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

Probieren Sie es hier aus.

Habe einige Ideen in der Antwort von dan1111 verwendet .

Einige Erklärungen zu(?2)*(()(?1))? .

jimmy23013
quelle
(?2)*(()(?1))?ist das letzte Puzzleteil, das ich gesucht habe. Nizza zu finden! ;)
Martin Ender
Wenn ich das (?2)*(()(?1))?Teil richtig verstehe , (()(?1))?stimmt das Teil nie mit etwas überein, da es (?2)*bereits alles auffrisst, was (()(?1))?passen kann, und dieses Konstrukt wird verwendet, um die Erfassungsgruppe 3 (festzulegen, wenn wir die Erfassungsgruppe 3 betreten, und ()um die Übereinstimmung zu ermöglichen ungepaart )).
n̴̖̋h̷͉̃a̷̭̿h̷̭̿d̸̡̅ẗ̵̨́
4

Lex, 182 Bytes (157 w / Stapel fester Größe)

Für diese Programme muss die Eingabe eine einzelne Zeichenfolge mit Zeilenende und gültigen Zeichen sein.

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

Das obige Programm schlägt fehl, wenn nicht genügend Speicher vorhanden ist. Dies könnte theoretisch passieren, wenn Sie genügend Speicher zur Verfügung stellen (. Aber da ein Segfehler als Fehlschlag gilt, nehme ich das als "Fehlschlag", obwohl die Problembeschreibung nicht sagt, was zu tun ist, wenn die Ressourcen nicht ausreichen.

Ich habe es auf 157 Bytes reduziert, indem ich nur einen Stapel mit fester Größe verwendet habe, aber das schien zu schummeln.

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

Kompilieren:

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

Prüfung:

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

Testausgang:

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
quelle
Ich denke, ich hätte ein bisschen klarer sein sollen - man kann davon ausgehen, dass entweder die Newline nie da ist oder immer da ist. Hilft das?
Sp3000,
Wäre es möglich, das Stapelprogramm mit fester Größe zu verwenden, aber die Größe des Stapels an die Länge der Eingabe anzupassen?
Isaacg
@isaacg Da die Eingabe stdin ist, haben wir keine Ahnung, bis es gelesen wird. Ich hätte leicht einen Treiber schreiben können, der ein Kommandozeilenargument oder eine Zeichenkette verwendet, aber Golf hat andere Prioritäten. Der dynamische Stack mit 25 Zeichen ist für C-Standards nicht schlecht, aber ich bin mir sicher, dass er trotzdem gespielt werden kann.
Rici
4

80386 Assembler, 97 Bytes

Hex-Dump:

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                                       .

Dies durchläuft die Eingabe einmal, wobei Zahlen größer als Null auf den Stapel geschrieben und dekrementiert werden, wenn eine Null verarbeitet wird. Ungebundene werden als -1 verarbeitet.

Funktionsprototyp (in C) (Funktion gibt 0 zurück, wenn ungültig und 1, wenn gültig):

int __cdecl test(char *in);

Äquivalente Baugruppe (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

Der folgende Code in C kann mit GCC auf einem POSIX-System zum Testen verwendet werden:

#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
quelle
3

Python 2, 353 Bytes

Die Analysefunktion durchläuft die Token nacheinander und erstellt einen Baum der Programmstruktur. Ungültige Programme lösen eine Ausnahme aus, durch die eine Null (Falsy) gedruckt wird. Andernfalls führt eine erfolgreiche Analyse zu einer Eins.

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

Die Ausgabe der Tests zeigt die Parser-Ausgabe:

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

Der Code vor dem Minifier:

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
Logik-Ritter
quelle
Nizza (ab) Verwendung von Ausnahmen! Sie können einige Leerzeichen einsparen, indem Sie die Reihenfolge der Operanden ==in den Tests vertauschen. Wenn Sie die Zeichenfolgen an die erste Stelle setzen, können Sie dies tun if')'==q. Ich glaube, eine der breakAussagen könnte durch eine ersetzt werden f=0, da Sie dadurch while fgenauso gut aus der Schleife geraten . Schließlich statt assert x==ykönnen Sie verwenden 1/(x==y)für eine ZeroDivisionError. ;)
DLosc
@ DLosc, vielen Dank für einige sehr nützliche Golftipps. Wenn ich zu den führenden Golfspielern gehören würde, würde ich Ihre Ideen für den Wettbewerb nutzen. Da mein Eintrag nicht konkurrenzfähig ist (golfmäßig), lasse ich ihn lieber als meist lesbares Beispiel. Ich habe Ihre cleveren Techniken für die zukünftige Verwendung notiert ;-)
Logic Knight
1

Pip , 88-72 Bytes

Idee aus Optimizers CJam . Mein ursprünglicher Versuch, das Problem mit einem rekursiven Abstiegsparser zu lösen, war ... etwas länger.

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

Formatiert mit Erklärung:

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

Interessante Tricks:

  • Viele Operatoren bearbeiten Listen und Bereiche in Bezug auf Elemente. So0X,5 ist es zum Beispiel 0 X [0 1 2 3 4] == ["" "0" "00" "000" "0000"].
  • Seit einigen Tagen kann der RTernary-Eplace-Operator eine Liste aller seiner Argumente erstellen: "abracadabra" R ["br" "ca"] 'bgivesababdaba , zum Beispiel. Ich nutze dieses Feature zhier gut aus.
  • Zu den falschen Werten in Pip gehören die leere Zeichenfolge "", die leere Liste []und jeder Skalar, der Null ist. Also 0ist falsch, aber auch 0.0und "0000000". Diese Funktion ist manchmal unpraktisch (um zu testen, ob eine Zeichenfolge leer ist, muss ihre Länge getestet werden, da sie ebenfalls "0"falsch ist), aber für dieses Problem ist sie perfekt.
DLosc
quelle
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,""))
SuperJedi224
quelle