เขียนล่ามคลาสสิคสุดมันส์!


18

Brain-Flak (ข้ามระหว่าง Brainf ** k และ Flak-Overstow) เป็นภาษาลึกลับแบบกองซ้อน เนื่องจากความท้าทายนี้ถูกโพสต์ภาษาได้พัฒนาและปรับปรุง แต่การแก้ไขครั้งแรกของภาษานี้เป็นที่รู้จักกันในชื่อ "brain-flak classic"

คุณต้องเขียนโปรแกรมหรือฟังก์ชั่นที่ใช้สตริงของรหัสคลาสสิกของ Brain-Flak และประเมินผล นอกจากนี้ยังจะใช้รายการจำนวนเต็ม (เป็นไปได้ที่ว่างเปล่า) มีอินพุตสำหรับโปรแกรม Brain-Flak classic

ภาษา

Brain-Flak มีสองกองเรียกว่า 'left' และ 'right' สแต็คที่ใช้งานเริ่มต้นที่ด้านซ้าย หากสแต็กที่ว่างเปล่าถูกตอกหรือแอบดูมันจะส่งคืน 0 ไม่มีตัวแปร เมื่อโปรแกรมเริ่มขึ้นแต่ละอินพุตจะถูกพุชไปยังสแต็กที่แอ็คทีฟตามลำดับ (เพื่อให้อินพุตล่าสุดอยู่ด้านบนของสแต็ก)

อักขระที่ใช้ได้ในโปรแกรม Brain-Flak ()[]{}<>เท่านั้นและต้องมีความสมดุลเสมอ หากมีอักขระที่ไม่ถูกต้องหรือวงเล็บไม่ตรงกันคุณจะได้รับพฤติกรรมที่ไม่ได้กำหนด ทุกอย่างถูกต้อง

: มีสองประเภทของฟังก์ชั่นNiladsและMonads niladเป็นฟังก์ชั่นที่ใช้เวลา 0 ขัดแย้ง นี่คือทั้งหมดของ nilads:

  • () +1
  • [] -1
  • {} ป็อปสแต็คที่ใช้งานอยู่
  • <> สลับสแตกที่ใช้งานอยู่

สิ่งเหล่านี้จะถูกรวมเข้าด้วยกันเมื่อถูกประเมิน ดังนั้นหากเรามี '3' อยู่ด้านบนของกองซ้อนที่ใช้งานอยู่ตัวอย่างนี้:

()(){}

จะประเมิน1 + 1 + active.pop()ว่าจะประเมินค่าใด 5. <>ประเมินเป็น 0

พระใช้เวลาหนึ่งอาร์กิวเมนต์ชิ้นหนึ่งของรหัส Brain-Flak นี่คือพระทั้งหมด:

  • (n) กด 'n' บนสแต็กที่ใช้งานอยู่
  • [n] พิมพ์ 'n' เป็น int และ newline
  • {foo}ในขณะที่ active.peek ()! = 0 ให้ทำ foo หาค่าเป็น0¹
  • <foo> ดำเนินการ foo แต่ประเมินเป็น 0

ฟังก์ชั่นเหล่านี้จะส่งกลับค่าภายในของพวกเขาดังนั้น

(()()())

จะกด 3 และ

[()()()]

จะพิมพ์ 3 แต่

[(()()())]

จะพิมพ์และดัน 3

เมื่อโปรแกรมเสร็จสิ้นการดำเนินการแต่ละค่าที่เหลืออยู่ในสแต็คที่ใช้งานจะถูกพิมพ์เป็นจำนวนเต็มโดยมีการขึ้นบรรทัดใหม่ระหว่าง ค่าในกองอื่น ๆ จะถูกละเว้น

กฎ:

  • โปรแกรมของคุณจะต้องรองรับตัวเลขในช่วง (-128, 127) และขนาดสแต็กอย่างน้อย 255 หากคุณรองรับขนาดใหญ่จะยิ่งดี

  • Underflow / overflow ไม่ได้ถูกกำหนดไว้

ตัวอย่าง IO:

โปรแกรมเปล่า:

อินพุต: ไม่มี

เอาท์พุท: ไม่มี

ส่วนที่เพิ่มเข้าไป. ที่มา:

({}{})

การป้อนข้อมูล:

2, 3

เอาท์พุท:

5

การลบ ที่มา:

({}<>){({}[])<>({}[])<>}<>

การป้อนข้อมูล:

2, 3

เอาท์พุท:

-1

การคูณ ที่มา:

({}<>)<>({}[]){({}[])<>(({}))<>}<>{({}<>{})<>}<>

การป้อนข้อมูล:

7, 8

เอาท์พุท:

56

fibonacci ที่มา:

<>((()))<>{({}[])<>({}<>)<>(({})<>({}<>))<>}<>

การป้อนข้อมูล:

5

เอาท์พุท:

13
8
5
3
2
1
1

เครื่องจักรความจริง

{[({})]}

ช่องโหว่มาตรฐานใช้และคำตอบที่สั้นที่สุดเป็นไบต์ชนะ


  • ¹: นี่เป็นข้อผิดพลาดจริง ๆ ในส่วนของฉัน {...} ควรประเมินผลรวมของการวิ่งทั้งหมดซึ่งเป็น IMO หนึ่งในคุณสมบัติที่ยอดเยี่ยมที่สุดของการสะเก็ดสมอง อย่างไรก็ตามสำหรับจุดประสงค์ของการท้าทายนี้ให้ถือว่าการ ประเมินนั้น{...} เป็น 0

มีกฎเกี่ยวกับค่าจำนวนเต็มต่ำสุดที่โปรแกรมต้องการจัดการหรือไม่
0 '

Monad {...}ประเมินอะไร?
Neil

อาร์กิวเมนต์การลบในลำดับใด ฉันได้รับการปฏิเสธในสิ่งที่ฉันคาดหวัง
Neil

@ Neil ขออภัยเกี่ยวกับเรื่องนั้น Monad {...}ประเมินผลเป็น 0 นอกจากนี้ยังมีการส่งอาร์กิวเมนต์ตามลำดับดังนั้น2จะถูกผลักจากนั้น3จะถูกผลักดังนั้นเมื่อโปรแกรมเริ่มทำงานอินพุตที่สอง ( 3) จะอยู่ด้านบนสุดของสแต็ก ฉันจะอธิบายทั้งสองอย่างในโพสต์
DJMcMayhem

คำตอบ:


6

Pip -n , 151 148 101 98 ไบต์

YRVg;VqR^"{}()<>[]";,8R J,8<>2AL,8("POy|i o0Syl1v0W@y{ }1yPU$+[ ]&@y0 1P$+[ ]"R0" (V{"R1"i}) "^s)y

รับรายการอินพุตเป็นอาร์กิวเมนต์บรรทัดรับคำสั่งและโค้ด Brain-Flak จาก (บรรทัด) stdin ลองออนไลน์!

แก้ไข:บันทึกจำนวนมากทั้งทางวิธีการเดิมของฉันโดยเปลี่ยนไปใช้กลยุทธ์การแปลและ eval

Ungolfed และแสดงความคิดเห็น

รุ่นนี้ยังรวมถึงการแก้ไขข้อบกพร่องบางอย่างที่แสดงรหัส Pip ที่เป็นผลมาจากการแปลเช่นเดียวกับเนื้อหาสแต็คหลังจากการดำเนินการ

;;; Setup ;;;

; y is the active stack, l is the off-stack
; y is initialized from command-line arguments
y:RVg   (reversed to put the last input at the top)
; l is preset to empty list by default

; p is the program (read from stdin)
p:q

; Translate from braces to numbers 0-7 (we do this so that the
; later replacement step won't try to replace the braces in the
; Pip code)
p R: ^"()[]{}<>" 0,8

;;; Replace nilads with the appropriate code ;;;

; () => o (variable preset to 1)
p R: 01 "o"

; [] => v (variable preset to -1)
p R: 23 "v"

; {} => POy|i
; Pop y; return that value OR i (variable preset to 0)
p R: 45 "POy|i"

; <> => (V{Syli})
; Eval the code Syl to swap stacks y and l, then return i (i.e. 0)
p R: 67 "(V{Syli})"

;;; Replace monads with the appropriate code ;;;

; ( ) => yPU$+[ ]&@y
; Sum ($+) the inside and push (PU) the sum onto y; return
; the just-pushed value, which is the first element of y (@y)
; y will always be truthy (nonempty), since we just pushed a value onto it
p R: 0 "yPU$+["
p R: 1 "]&@y"

; [ ] => P$+[ ]
; Sum ($+) the inside, print (P) the sum, and return it
p R: 2 "P$+["
p R: 3 "]"

; { } => (V{W@y{ }i})
; Eval the code W@y{ }, which wraps the inside in curly braces
; and runs it while (W) the first element of y (@y) is truthy
; (i.e. not zero, and not nil from an empty stack)
; Then return i (i.e. 0)
p R: 4 "(V{W@y{"
p R: 5 "}i})"

; < > => (V{ i})
; Eval the inside, then return i (i.e. 0)
p R: 6 "(V{"
p R: 7 "i})"

; Debug: print the resulting translated code and a blank line
Pp.n

;;; Run the code ;;;

; Eval the translated code
(Vp)

; Output the active stack, newline-separated
PyJn

; Debug: print the active stack and the off-stack
P"Active stack: ".RPy
"Off-stack: ".RPl

pip ใหม่กว่าความท้าทายนี้หรือไม่?
DJMcMayhem

@DJMcMayhem Nope ! ฉันไม่ได้ใช้คุณสมบัติใด ๆ ที่ใหม่กว่าความท้าทาย
DLosc

59

Brain-Flak Classic , 1271 1247 1239 ไบต์

<>(()){<>((([][][][][])<(((({}){})(({})({}))[])({}(({})({}({})({}{}(<>)))))[])>{()<{}>}{})<{{}}{}>())}{}<>(<(({()(((<>))<>)}{}{<({}(([][][])((({})({}))[]{})){})>((){[]<({}{})((){[]<({}{}<>((({})({})){}{}){})(<>)>}{}){{}{}<>(<({}{}())>)(<>)}>}{}){(<{}{}{}((<>))<>>)}{}}<>)<{({}[]<({}<>)<>{(<{}>)<>{<>({}[])}{}<>({}<>)(<>)}{}>)}{}<>>)>)<>{(({}[])(){(<{}>)<><(({})[])>[][][][]{()()()()(<{}>)}{}<>}{}<>)<>}<>{}{(({})<({()<<>({}<>)>}{})>([]))((){[](<(({}()()(<>))()()()){(<{}>)<>}>)}{}<>){{}((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[](<{}<>{({}<>)<>}{}(({}))({<{}({}<>)<>>{}(<<>({}[]<>)>)}<><{({}<>)<>}>{})>)}{}){{}{}(<([])>)}>}{}){{}<>{({}<>)<>}{}((({})())<{({}[]<({}<>)<>>)}>{}){({}[]<><({}<><({()<({}[]<({}<>)<>>)>}{}<>)><>)<>({()<({}[]<({}<>)<>>)>}{}<>)>)}<>(<{({}<>)<>}>)}>}{}){{}{}(<(())>)}>}{}){(<{}{}>)<>{({}<>)<>}{}(({}))({<{}({}<>)<>>({})(<<>({}<>)>)}<><{({}<>)<>}>){{}([][][])<>(((<{}>)<>))}}>}{}){{}(<([{}])>)}>}{}){{}((<{}>))}>}{}){{}(({})(<()>)<<>{({}<>)<>}{}({}()<>)<>>)<>(<({}<>)>)<>{({}<>)<>}}{}(<({}<({}<>)<>>{})<>({}<>)>)<>(<({}())>)}{}({}<{({}[]<({}<>)<>>)}{}>){((({}[]<>){(<{}({}<>)>)}{}())<{({}()<({}<>)<>(({})[])>{[][](<{}>)}{})}{}>()){{}(<>)}}{}}{}{({}[]<[{}]>)}{}{({}[]<{}>)}{}

ลองออนไลน์!

+4 ไบต์จากการแก้ไขข้อบกพร่องด้วยเงื่อนไขใน{...}monad และ -36 ไบต์จากสนามกอล์ฟต่างๆ

รหัส 1238 ไบต์, +1 ไบต์สำหรับการ-aตั้งค่าสถานะ (ซึ่งสามารถรวมกับการตั้งค่าภาษา)

ตอนนี้ประเมิน{...}ว่าเป็นศูนย์ตามข้อกำหนดของความท้าทาย โปรดทราบว่า Brain-Flak นั้นได้ประเมิน{...}ว่าผลรวมของการวิ่งทั้งหมดตั้งแต่วันที่ 7 พฤษภาคม 2559 การแก้ไขข้อผิดพลาดสองวันก่อนการลงแข่งขันครั้งนี้

รหัสต่อไปนี้ตีความ Brain-Flak Classic อย่างถูกต้องพร้อมกับ{...}ผลรวมของการทำงานทั้งหมด ข้อแตกต่างระหว่างล่ามสองคนคือการจัดวางของหนึ่ง{}nilad

<>(()){<>((([][][][][])<(((({}){})(({})({}))[])({}(({})({}({})({}{}(<>)))))[])>{()<{}>}{})<{{}}{}>())}{}<>(<(({()(((<>))<>)}{}{<({}(([][][])((({})({}))[]{})){})>((){[]<({}{})((){[]<({}{}<>((({})({})){}{}){})(<>)>}{}){{}{}<>(<({}{}())>)(<>)}>}{}){(<{}{}{}((<>))<>>)}{}}<>)<{({}[]<({}<>)<>{(<{}>)<>{<>({}[])}{}<>({}<>)(<>)}{}>)}{}<>>)>)<>{(({}[])(){(<{}>)<><(({})[])>[][][][]{()()()()(<{}>)}{}<>}{}<>)<>}<>{}{(({})<({()<<>({}<>)>}{})>([]))((){[](<(({}()()(<>))()()()){(<{}>)<>}>)}{}<>){{}((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[]<({}())((){[](<{}<>{({}<>)<>}{}(({}))({<{}({}<>)<>>{}(<<>({}[]<>)>)}<><{({}<>)<>}>{})>)}{}){{}{}(<([])>)}>}{}){{}<>{({}<>)<>}{}((({})())<{({}[]<({}<>)<>>)}>{}){({}[]<><({}<><({()<({}[]<({}<>)<>>)>}{}<>)><>)<>({()<({}[]<({}<>)<>>)>}{}<>)>)}<>(<{({}<>)<>}>)}>}{}){{}{}(<(())>)}>}{}){(<{}>)<>{({}<>)<>}{}(({}))({<{}({}<>)<>>({})(<<>({}<>)>)}<><{({}<>)<>}>{}){{}([][][])<>(((<{}>)<>))}}>}{}){{}(<([{}])>)}>}{}){{}((<{}>))}>}{}){{}(({})(<()>)<<>{({}<>)<>}{}({}()<>)<>>)<>(<({}<>)>)<>{({}<>)<>}}{}(<({}<({}<>)<>>{})<>({}<>)>)<>(<({}())>)}{}({}<{({}[]<({}<>)<>>)}{}>){((({}[]<>){(<{}({}<>)>)}{}())<{({}()<({}<>)<>(({})[])>{[][](<{}>)}{})}{}>()){{}(<>)}}{}}{}{({}[]<[{}]>)}{}{({}[]<{}>)}{}

ลองออนไลน์!

อินพุต (ไปยังตัวแปลทั้งสองตัว) เป็นโปรแกรม Brain-Flak Classic เพื่อแปลความหมายจากนั้นขึ้นบรรทัดใหม่จากนั้นเป็นรายการจำนวนเต็มที่คั่นด้วยช่องว่าง ไม่มีการตรวจสอบความถูกต้องในอินพุต จำเป็นต้องขึ้นบรรทัดใหม่แม้ว่าโปรแกรมหรืออินพุตจะว่างเปล่า

ขั้นตอนแรกคือการแยกวิเคราะห์อินพุตทั้งหมดเริ่มต้นด้วยวงเล็บเหลี่ยม:

# Move to right stack, and push 1 to allow loop to start
<>(())
{
   # While keeping -5 on third stack:
   <>((([][][][][])<

       # Pop bracket or newline k from left stack, and push 0, k-10, k-40, k-60, k-91, k-123 on right stack
       (((({}){})(({})({}))[])({}(({})({}({})({}{}(<>)))))[])

   # Search this list for a zero, and push the number of nonzero entries popped minus 5 
   # (thus replacing the 0 if it was destroyed)
   >{()<{}>}{})

   # Remove rest of list, and push the same number plus 1
   # Result is -4 for {, -3 for [, -2 for <, -1 for (, 0 for newline, or 1 for everything else (assumed closing bracket)
   <{{}}{}>())

# Repeat until newline found
}{}<>

จากนั้นจำนวนเต็มจะถูกแยกวิเคราะห์ โดยปกติไม่จำเป็นต้องใช้สิ่งนี้ แต่อินพุตถูกใช้เป็น ASCII สิ่งนี้มีซับในสีเงิน: การป้อนข้อความช่วยให้เราสามารถกำหนดความสูงของสแต็กซึ่งทำให้สิ่งต่าง ๆ ง่ายขึ้นเมื่อเราไม่สามารถเข้าถึงความสูงของสแต็กที่ไม่มี

จำนวนเต็มถูกแยกวิเคราะห์เป็นตัวเลขสองตัวในสแต็กที่สอง: หนึ่งค่าสำหรับค่าสัมบูรณ์และอีกหนึ่งสำหรับเครื่องหมาย สิ่งเหล่านี้จะถูกย้ายกลับไปที่สแต็กแรก

สแต็คที่แปลจะถูกเก็บไว้ด้านล่างรหัสในสแต็กแรกตามลำดับต่อไปนี้: ความสูงสแต็กปัจจุบัน, สแต็กปัจจุบัน, ความสูงสแต็กอื่น, สแต็กอื่น ๆ 0 สำหรับความสูงของสแต็กอื่นไม่จำเป็นต้องถูกผลักไปที่จุดนี้เนื่องจากมันจะเป็นศูนย์โดยปริยายในครั้งแรกที่อ่าน

(<((

    # If stack nonempty, register first stack entry.
    {()(((<>))<>)}{}

    # For each byte k of input:
    {

        # Push -3, -13, and k-32
        <({}(([][][])((({})({}))[]{})){})>

        # Evaluate to 1 if space
        # If not space (32):
        ((){[]<

            # If not minus (45):
            ({}{})((){[]<

                # Replace top of right stack (n) with 10*n + (k-48)
                ({}{}<>((({})({})){}{}){})(<>)

            # Else (i.e., if minus):
            >}{}){

                # Remove excess "else" entry and -3
                {}{}

                # Set sign to negative (and destroy magnitude that shouldn't even be there yet)
                <>(<({}{}())>)(<>)}

        # Else (i.e., if space):
        >}{}){

            # Remove working data for byte, and push two more 0s onto right stack
            (<{}{}{}((<>))<>>)

    # Push number of integers found
    }{}}<>)

    # For each integer:
    <{({}[]<

        # Move magnitude back to left stack
        ({}<>)<>

        # If sign is negative, negate
        {(<{}>)<>{<>({}[])}{}<>({}<>)(<>)}{}

    >)}{}

    # Push stack height onto stack
    <>>)

# Push 0
>)

การเป็นตัวแทนของรหัสจะถูกย้ายกลับไปที่กองซ้าย เพื่อให้ง่ายขึ้นในภายหลังเราจะลบ 4 จากวงเล็บเปิดของ nilads เพื่อให้แต่ละการดำเนินการมีจำนวนเต็มเฉพาะจาก -1 ถึง -8

# For each bracket in the code:
<>{

    # Push k-1 and evaluate to k
    (({}[])()

    # If not closing bracket:
    {

        # Check next bracket (previously checked, since we started at the end here)
        (<{}>)<><(({})[])>

        # Subtract 4 if next bracket is closing bracket
        # Inverting this condition would save 8 bytes here, but cost 12 bytes later.
        [][][][]{()()()()(<{}>)}{}

    <>}{}

    # Push result onto left stack
    <>)

<>}<>{}

ส่วนหลักของโปรแกรมแปลความหมายของคำแนะนำเป็นจริง ในตอนเริ่มต้นของการวนซ้ำแต่ละครั้งของลูปหลักคำสั่งปัจจุบันจะอยู่ที่ด้านบนของสแต็กซ้ายทุกอย่างหลังจากที่มันอยู่ต่ำกว่าในสแต็กเดียวกันและทุกอย่างก่อนที่มันจะอยู่ในสแต็กขวา ฉันมักจะเห็นภาพนี้ว่ามีหนังสือเปิดหน้าหนึ่ง

{

    (

        # Get current instruction
        ({})

        # Move all code to left stack, and track the current position in code
        <({()<<>({}<>)>}{})>

        # Push -1, signifying that the code will move forward to just before a matching }.
        # In most cases, this will become 0 (do nothing special) before it is acted upon
        ([])

    # Push instruction minus 1
    )

    # If opening bracket:
    ((){[](<

        # Push instruction+1 and instruction+4
        (({}()()(<>))()()())

        # If instruction+4 is nonzero (not loop monad), replace the earlier -1 with 0 to cancel forward seek
        # This would be clearer as {(<{}>)<>(<{}>)<>}, but that would be unnecessarily verbose
        {(<{}>)<>}

    # Else (i.e., if closing bracket):
    >)}{}<>){

# If closing bracket, parse command
# Post-condition for all: if not moving to {, pop two and push evaluation, 0.
# (For nilads, can assume second from top is 0.)
# If moving to {, pop one, push -3, 0, 0.

        # Seven nested if/else statements, corresponding to eight possible instruction.
        # The "else" statements end with 0 already on the stack, so no need to push a 0 except in the innermost if.
        # Each one beyond the first increments the instruction by 1 to compare the result with 0
        # Each instruction will pop the instruction, leaving only its evaluation (with a 0 on top).
        {}((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[]<
        ({}())((){[](<

            # -7: pop
            # Pop instruction to reveal existing 0 evaluation
            {}

            # Move code out of the way to access stack
            <>{({}<>)<>}{}

            # Duplicate stack height (only useful if stack height is zero)
            (({}))

            (

                # If stack height nonzero
                {

                    # Save stack height on second stack
                    <{}({}<>)<>>

                    # Pop stack
                    {}

                    # Move stack height back and subtract 1
                    (<<>({}[]<>)>)

                }

                # Move code back to normal position
                <><{({}<>)<>}>{}

            # Evaluate as popped entry (0 if nothing popped)
            )

        # (else)
        >)}{}){

            # -6: -1 nilad
            # Just evaluate as -1
            {}{}(<([])>)

        # (else)
        }>}{}){

            # -5: swap nilad
            # Move code out of the way to access stack
            {}<>{({}<>)<>}{}

            # Number of integers to move: stack height + 1 (namely, the stack height and every entry in the stack)
            ((({})())

            # Move to second stack
            <{({}[]<({}<>)<>>)}>{}

            # Do (stack height + 1) times again
            ){({}[]<><

                # Get stack element
                ({}<><

                    # Move alternate (interpreted) stack to second (real) stack, and push length on top of it
                    ({()<({}[]<({}<>)<>>)>}{}<>)

                # Push current stack element below alternate stack
                ><>)

                # Move alternate stack back above newly pushed element
                <>({()<({}[]<({}<>)<>>)>}{}<>)

            >)}

            # Move code back to normal position
            <>(<{({}<>)<>}>)

        # (else)
        }>}{}){

            # -4: 1
            # Just evaluate to 1
            {}{}(<(())>)

        # (else)
        }>}{}){

            # -3: loop
            # Create zero on stack while keeping existing evaluation
            # This becomes (<{}{}>) in the version that meets the challenge spec
            (<{}>)

            # Move code out of the way to access stack
            <>{({}<>)<>}{}

            # Duplicate stack height
            (({}))

            (

                # If stack height nonzero
                {

                    # Save stack height on second stack
                    <{}({}<>)<>>

                    # Peek at top of stack
                    ({})

                    # Move stack height back
                    (<<>({}<>)>)

                }

                # Move code back to normal position
                <><{({}<>)<>}>

            # Look at peeked entry
            # Remove the {} in the version meeting the challenge spec
            {})

            # If peeked entry is nonzero
            {

                # Replace -3 instruction on third stack
                {}([][][])

                # Replace loop indicator to 0 (to be incremented later to 1)
                <>(((<{}>)

                # Create dummy third stack entry to pop
                <>))

            }

        # (else)
        }>}{}){

            # -2: print
            # Just print evaluation without modifying it
            {}(<([{}])>)

        # (else)
        }>}{}){

            # -1: evaluate as zero
            # Just change evaluation to 0
            {}((<{}>))

        # else
        }>}{}){

            # 0: push
            # Get current evaluation (without modifying it)
            {}(({})

                # Create zero on stack as barrier
                (<()>)

                # Move code out of the way to access stack
                <<>{({}<>)<>}{}

                # Increment stack height and save on other stack
                ({}()<>)<>

            # Push evaluation
            >)

            # Move stack height back (and push zero)
            <>(<({}<>)>)

            # Move code back to normal position
            <>{({}<>)<>}

        }{}

        # Update third stack by adding evaluation to previous entry's evaluation
        # Previous entry's instruction is saved temporarily on left stack
        (<({}<({}<>)<>>{})<>({}<>)>)

        # Increment loop indicator
        # If instruction was loop monad and top of stack was nonzero, this increments 0 to 1 (search backward)
        # Otherwise, this increments -1 to 0 (do nothing)
        <>(<({}())>)

    }{}

    # While holding onto loop indicator
    ({}<

        # Go to immediately after executed symbol
        {({}[]<({}<>)<>>)}{}

    >)

    # If looping behavior:
    {

        # Switch stack and check if searching forward
        ((({}[]<>)

        # If so:
        {

            # Move just-executed { back to left stack, and move with it
            (<{}({}<>)>)

        }{}

        # Either way, we are currently looking at the just-executed bracket.
        # In addition, the position we wish to move to is on the current stack.

        # Push unmodified loop indicator as initial value in search
        ())

        # While value is nonzero:
        <{

            # Add 1
            ({}()

                # Move current instruction to other stack
                <({}<>)<>

                # Check whether next instruction is closing bracket
                (({})[])>

                # If opening bracket, subtract 2 from value
                {[][](<{}>)}{}

            )

        }{}>

        # If searching backward, move back to left stack
        ()){{}(<>)}

    }{}

}

หลังจากออกจากลูปหลักโค้ดทั้งหมดจะอยู่ในสแต็กด้านขวา สิ่งเดียวที่อยู่บนสแต็กด้านซ้ายคือศูนย์และสแต็คทั้งสองตีความ การสร้างผลลัพธ์ที่ถูกต้องเป็นเรื่องง่าย

# Pop the zero
{}

# Output current stack
{({}[]<[{}]>)}{}

# Discard other stack to avoid implicit printing
{({}[]<{}>)}{}

12
: โออะไร ... โอเคการโอบกอดทันที งานที่ดี! : D
DJMcMayhem

4
ให้ฉันได้ตรงนี้ ... คุณสร้างล่ามสำหรับภาษาที่จะตีความ YoDawg
tisaconundrum

ตกลงทำไมมันมีเพียงตัวเลข upvote 2 หลักเท่านั้น
NieDzejkob

งานที่ดีในการใช้งานตัวสะสมอย่างถูกต้อง{...}ซึ่งเป็นพฤติกรรมที่ถูกต้องสำหรับสมองที่ทันสมัยและ (ฉันคิดว่า) สมองแบบคลาสสิกอย่างไรก็ตามฉันเขียนในความท้าทายที่{...}ประเมินว่าเป็น 0 คุณอาจเล่นกอล์ฟจำนวนไบต์ที่สำคัญ โดยการลบฟังก์ชั่นนั้นออกไปแม้ว่ามันจะเป็นการดีที่จะเก็บต้นฉบับไว้รอบ ๆ เพราะมันถูกต้องมากกว่าในทางเทคนิค (ผิดกับความท้าทายนี้)
DJMcMayhem

@DJMcMayhem แก้ไขแล้ว อย่าทำให้ฉันแปลพอร์ตล่ามทั้งหมดให้เป็นเวอร์ชั่นสมมุติของ Brain-Flak
Nitrodon

8

APL, 255 257 ไบต์

b←{S←(⌽⍺)⍬
e←{0=⍴⍵:0
v+∇⊃_ v←∇{r←⊂2↓⍵
'()'≡n←2↑⍵:r,1
'[]'≡n:r,¯1
'{}'≡n:r,{i←⊃⊃⊃S⋄S[1]↓⍨←1⋄i}⍬
'<>'≡n:r,0⊣S⌽⍨←1
r←⊂⍵↓⍨i←0⍳⍨(+\c=⍵)-+\')]>}'['([<{'⍳c←⊃⍵]=⍵
i←1↓¯1↓c←i↑⍵
'('=c←⊃c:r,S[1],⍨←⍺⍺i
'['=c:r,+⎕←⍺⍺i
'{'=c:r,{0≠⊃⊃⊃S:∇e i⋄0}⍬
'<'=c:r,0⊣⍺⍺i}⍵}
⎕←⍪⊃S⊣e⍵}

นี่ใช้โปรแกรมเป็นอาร์กิวเมนต์ที่ถูกต้องและอินพุตโปรแกรมเป็นอาร์กิวเมนต์ซ้ายเช่น:

      2 3 b '({}{})'
5
      2 3 b '({}<>){({}[])<>({}[])<>}<>'
¯1
      7 8 b '({}<>)<>({}[]){({}[])<>(({}))<>}<>{({}<>{})<>}<>'
56
      5 b '<>((()))<>{({}[])<>({}<>)<>(({})<>({}<>))<>}<>'
13
 8
 5
 3
 2
 1
 1

รุ่น Ungolfed: ที่นี่


7

APL (Dyalog Classic) , 146 ไบต์

↑⍕¨s⊣{⍎⍕1 ¯1'(s↓⍨←1)⊢⊃s' '0⊣s t←t s' 's,⍨←+/∇¨a' '⎕←+/∇¨a' '∇{×⊃s:∇⍺⍺¨a⋄0}0' '0⊣+/∇¨a'[(⊃⍵)+4×⍬≢a1↓⍵]}¨⍎∊(')',⍨'(',¨⍕¨⍳4)[0,4,⍨'([{<'⍳⍞]⊣s←⌽⎕⊣t←⍬

ลองออนไลน์!

คลาสสิกหนึ่งตีความอีก :)


6

Python 3, 429 ไบต์

import re
S='s+=[v];v=0';T='v+=s.pop()';i=0
d={'()':'v+=1','(':S,')':'a+=[v];'+T,'[]':'v-=1','[':S,']':'print(v);'+T,'<>':'a.reverse()','<':S,'>':T,'{}':'v+=0if a[-1]==""else a.pop()','{':S+';while a[-1]:','}':T}
def r(m):global i;t=m.group();i-=(t=='}');s=' '*i;i+=(t=='{');return''.join(s+r+'\n'for r in d[t].split(';'))
def g(c,*a):
 a,s,v=['']+list(a),[],0;exec(re.sub(r'[<({[]?[]})>]?',r,c));
 while a[-1]!="":print(a.pop())

ใช้เหมือน g('[{}{}]', 2, 3)

มันใช้re.subในการ "คอมไพล์" แหล่งที่มาของสมองสะเก็ดเพื่อหลามแล้วดำเนินการหลาม (สำหรับการดีบักให้แทนที่execด้วยprintเพื่อรับรายการรหัสหลาม)

เยื้องอย่างถูกต้องในขณะที่ลูปกินจำนวนมากไบต์ในรหัส


3

Python ขนาด 616 ไบต์

คำแนะนำ:

  1. วิ่งด้วยหลาม
  2. รายการอินพุตใน[1,2,...]รูปแบบจากนั้นกด Enter
  3. วาง / เขียนโปรแกรมจากนั้นกด Enter อีกครั้ง
  4. เสร็จสิ้น

โดยพื้นฐานแล้วสิ่งที่โปรแกรมนี้ทำคือ "คอมไพล์" แบบเรียกซ้ำรหัส Brain-flak ไปยังรายการที่ซ้อนกันและตีความรายการนั้นซ้ำ ๆ อาจมีวิธีรวมทั้งสอง ...

ฉันจะพยายามทำตรรกะในภายหลัง

y="([{<)]}>"
w,z,g=print,len,input
def c(s):
 if z(s)<1:return[]
 t,i,o=[],1,0
 t.append(y.index(s[0]))
 while z(t)>0:
  x=y.index(s[i])
  if x<4:t.append(x)
  else:o=t.pop()
  i+=1
 r=[[o,c(s[1:i-1])]]
 r.extend(c(s[i:]))
 return r
p=lambda t:t.pop()if z(t)>0 else 0
k=lambda t:t[z(t)-1]if z(t)>0 else 0
r,l=[],eval(g())
a=l
def i(u):
 v=0
 global a
 for t,n in u:
  if t<1:
   if n:o=i(n);v+=o;a.append(o)
   else:v+=1
  if t==1:
   if n:o=i(n);v+=o;w(o)
   else:v-=1
  if t==2:
   if n:
    while k(a)!=0:i(n)
   else:v+=p(a)
  if t>2:
   if n:i(n)
   elif a==l:a=r
   else:a=l
 return v
i(c(g()))
for n in a:w(n)

3

Perl 5.6, 419 414 ไบต์

ฉันเล่นกอล์ฟนิดหน่อย แต่อาจมีขอบเขตที่ต้องปรับปรุง เพิ่มบรรทัดใหม่และแท็บที่นี่เพื่อประโยชน์ในการอ่านเล็กน้อย:

use Text::Balanced extract_bracketed;
$s=shift;
@a=reverse@ARGV;
sub p
{
    my($c)=@_;
    my$s=0;
    while(my$n=extract_bracketed($c)){
        $s+='()'eq$n||'{}'eq$n&&shift@a;
        $s-='[]'eq$n;
        @t=@a,@a=@i,@i=@t if'<>'eq$n;
        my$m=chop($n);
        $n=substr($n,1);
        if($n){
            p($n)while'}'eq$m&&$a[0];
            p($n)if'}'ne$m;
            $s+=$v,unshift@a,$v if')'eq$m;
            $s+=$v,print"n=$n m=$m v=$v\n"if']'eq$m;
        }
    }
    $v=$s;
}
p($s);
foreach(@a){
    print"$_\n";
}

1

Python 2 , 361 , 348 ไบต์

c,s=input();s=s,[]
a=s[0]
def w():global a,s;s=s[::-1];a=s[0];return 0
def p(c):a.append(c);return c
def n(c):print c;return c
z=lambda c:0
def l(f):
 global a
 while a and a[-1]:f()
 return 0
for x,y in zip("() ( [] {} <> [ < { } ] >".split(),"+1 +p( -1 +(len(a)and(a.pop())) +w() +n( +z( +l(lambda: ) ) )".split()):c=c.replace(x,y)
exec c
print a

ลองออนไลน์!

บันทึก -13 ไบต์ขอบคุณ @Mr Xcoder!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.