เครื่องมือตรวจสอบไวยากรณ์ที่คล้ายกับ Pyth


25

Pythเป็นภาษากอล์ฟที่ใช้ Python มันใช้สัญกรณ์คำนำหน้ากับแต่ละคำสั่งที่มี arity ที่แตกต่างกัน (จำนวนอาร์กิวเมนต์ที่ยอมรับ)

งานของคุณคือการเขียนตัวตรวจสอบไวยากรณ์สำหรับภาษา Pyth ที่เหมือนกัน (ไม่มีอยู่) Pith

ไวยากรณ์ของ Pith

Pith มีเพียง 8 คำสั่งถ่านเดียว:

01234()"

01234แต่ละอันมี arity ของจำนวนที่สอดคล้องกันและด้วยเหตุนี้จึงคาดว่าข้อโต้แย้งมากมายหลังจากนั้น ตัวอย่างเช่น,

400010

เป็นที่ถูกต้องโปรแกรมแก่นเพราะ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

คือไม่ได้เป็นโปรแกรมที่ถูกต้องเพราะแก่นเริ่มต้น3มีเพียงสองข้อโต้แย้งซึ่งเราสามารถดูได้โดยดูที่ต้นไม้ดังต่อไปนี้:

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

ถัดไป(เริ่มต้นไม่ จำกัด และ)สิ้นสุดไม่ จำกัด การไม่ จำกัด จำนวนอาร์กิวเมนต์ใด ๆ (อย่างตะกละตะกลาม) และนับเป็นอาร์กิวเมนต์เดียวกับคำสั่งหลักใด ๆ unboundeds ใด ๆ ที่ยังคงเปิดอยู่ในตอนท้ายของโปรแกรมจะถูกปิดโดยอัตโนมัติ )คำสั่งไม่ได้เป็นข้อผิดพลาดหากไม่มี unboundeds มีการเปิด - มันก็ไม่ทำอะไรเลย *.

ตัวอย่างเช่นโปรแกรม Pith

)31(0)0(201000100

สอดคล้องกับต้นไม้

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

ว่างเปล่า unboundeds ก็โอเคดังนั้น()โปรแกรม Pith ที่ถูกต้อง

โปรแกรม Pith ที่ไม่ถูกต้องพร้อมกับไม่มีข้อ จำกัด คือ

12(010

ตั้งแต่ที่2ได้รับเพียงหนึ่งอาร์กิวเมนต์ (ไม่ จำกัด )

ในที่สุด"เริ่มต้นและสิ้นสุดสตริงซึ่งเสมอ 0 arity และนับเป็นอาร์กิวเมนต์เดียวเช่น

2"010""44)()4"

ซึ่งเป็นเพียงแค่2ถูกส่งผ่านไปสองอาร์กิวเมนต์สตริงและ"010" "44)()4"เช่นเดียวกับ unboundeds สตริงอาจว่างเปล่าและสตริงที่ไม่มีการปิดผนึกใด ๆ ในตอนท้ายของโปรแกรมจะถูกปิดโดยอัตโนมัติ

* ส่วนนี้จะแตกต่างจากเดิม Pyth ซึ่งอันที่จริงไม่ทำอะไรบางอย่างในกรณีเช่น1)สิ้นสุด 1 arity และการสร้างข้อผิดพลาด

อินพุต / เอาต์พุต

ข้อมูลที่ป้อนจะเป็นสตริงที่ไม่ว่างหนึ่งบรรทัดซึ่งประกอบด้วยอักขระ01234()"เท่านั้น คุณอาจเลือกที่จะสันนิษฐานว่ามีการขึ้นบรรทัดใหม่ที่ต่อท้ายเสมอ คุณสามารถเขียนฟังก์ชั่นหรือโปรแกรมเต็มรูปแบบสำหรับความท้าทายนี้

คุณควรส่งออกค่าความจริงหากอินพุตเป็น Pith ที่ถูกต้องทาง syntactically หรือค่าที่ผิดพลาดเป็นอย่างอื่น ค่าความจริงและเท็จจะต้องได้รับการแก้ไขดังนั้นคุณจึงไม่สามารถส่งออก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 ขอบคุณและแก้ไข ฉันต้องการแสดงให้เห็นว่าผู้ที่ไม่ได้ถูก
ผูกมัด

@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)))*\)*$

ลองที่นี่

ใช้แนวคิดบางอย่างในคำตอบของ dan1111นี้

(?2)*(()(?1))?คำอธิบายบางอย่างเกี่ยวกับ


(?2)*(()(?1))?เป็นชิ้นส่วนจิ๊กซอว์สุดท้ายที่ฉันกำลังมองหา ยินดีที่ได้พบ! ;)
Martin Ender

ถ้าฉันเข้าใจ(?2)*(()(?1))?ส่วนนั้นอย่างถูกต้อง(()(?1))?ส่วนนั้นจะไม่ตรงกับสิ่งใดเลยเนื่องจาก(?2)*กินทุกอย่างที่(()(?1))?สามารถจับคู่ได้แล้วและโครงสร้างนี้ใช้เพื่อตั้งค่าการจับภาพกลุ่ม 3 เมื่อเราเข้า(และยกเลิกการจับภาพกลุ่ม 3 เมื่อเราอยู่ข้างนอก()โครงสร้าง ไม่ได้จับคู่))
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

4

lex, 182 ไบต์ (157 w / สแต็กขนาดคงที่)

โปรแกรมเหล่านี้ต้องการอินพุตเป็นสตริงอักขระบรรทัดใหม่ที่ถูกยกเลิก

%%
 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 bytes โดยใช้ stack ที่มีขนาดคงที่ แต่นั่นดูเหมือนว่าเป็นการโกง

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

@isaacg เนื่องจากอินพุตเป็น stdin เราจึงไม่ทราบจนกว่าจะอ่าน ฉันสามารถเขียนไดรเวอร์ที่ใช้ ARG หรือ command line ได้อย่างง่ายดาย แต่กอล์ฟมีลำดับความสำคัญอื่น ๆ สแต็คแบบไดนามิกใน 25 ตัวอักษรไม่ได้แย่ตามมาตรฐาน c แต่ฉันแน่ใจว่ามันยังสามารถเล่นกอล์ฟได้
rici

4

80386 แอสเซมเบลอร์ 97 ไบต์

การถ่ายโอนข้อมูล Hex:

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                                       .

สิ่งนี้จะวิ่งผ่านอินพุตหนึ่งครั้งผลักตัวเลขที่มากกว่าศูนย์ลงบนสแต็กและลดลงเมื่อมีการประมวลผลเป็นศูนย์ Unboundeds จะถูกประมวลผลเป็น -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

เอาต์พุตของการทดสอบแสดงเอาต์พุต parser:

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

รหัสก่อน 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

การใช้ข้อยกเว้นที่ดี (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,50 X [0 1 2 3 4] == ["" "0" "00" "000" "0000"]สำหรับตัวอย่างเช่น
  • เมื่อไม่กี่วันที่ผ่านมาRผู้ประกอบการสถานที่ที่สามสามารถรับรายการข้อโต้แย้งใด ๆ ของมัน: "abracadabra" R ["br" "ca"] 'bให้ababdabaยกตัวอย่างเช่น ฉันใช้ประโยชน์จากคุณลักษณะนี้ด้วยzที่นี่
  • ค่า Falsy ใน 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,""))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.