Mini-Flak Quine ที่เร็วที่สุด


26

Mini-Flak เป็นส่วนหนึ่งของสมอง Flakภาษาที่<>, <...>และ[]การดำเนินงานจะไม่ได้รับอนุญาต พูดอย่างเคร่งครัดจะต้องไม่ตรงกับ regex ต่อไปนี้:

.*(<|>|\[])

Mini-Flak เป็นชุดย่อยที่สมบูรณ์ที่สุดของ Brain-Flak


เมื่อไม่นานมานี้ฉันสามารถสร้างQuineในMini-Flakได้ แต่มันช้าเกินไปที่จะวิ่งในช่วงชีวิตของจักรวาล

ดังนั้นความท้าทายของฉันต่อคุณคือทำให้ Quine เร็วขึ้น


เกณฑ์การให้คะแนน

ในการให้คะแนนรหัสของคุณให้@cyตั้งค่าสถานะที่ท้ายรหัสของคุณและเรียกใช้ในล่าม Ruby ( ลองใช้ออนไลน์ใช้ล่ามทับทิม) โดยใช้-dธง คะแนนของคุณควรพิมพ์ไปที่ STDERR ดังต่อไปนี้:

@cy <score>

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

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

การคำนวณจำนวนรอบนั้นไม่ยากมาก จำนวนรอบเท่ากับ 2 เท่าของจำนวนของการเรียกใช้ monads บวกกับจำนวนของการทำงานของ nilads นี่เหมือนกับการแทนที่ nilad ทุกตัวด้วยอักขระตัวเดียวและนับจำนวนตัวอักษรทั้งหมด

ตัวอย่างการให้คะแนน

  • (()()()) คะแนน 5 เพราะมันมี 1 monad และ 3 nilads

  • (()()()){({}[()])} คะแนน 29 เพราะส่วนแรกเหมือนก่อนและคะแนน 5 ในขณะที่วงมี 6 monads และ 2 nilads ให้คะแนน 8 วนรอบจะทำงาน 3 ครั้งดังนั้นเราจึงนับคะแนน 3 ครั้ง 1*5 + 3*8 = 29


ความต้องการ

โปรแกรมของคุณจะต้อง ...

  • มีอย่างน้อย 2 ไบต์

  • พิมพ์รหัสที่มาเมื่อดำเนินการใน Brain-Flak โดยใช้-Aธง

  • ไม่ตรงกับ regex .*(<|>|\[])


เคล็ดลับ

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

  • [(...)]{}และ(...)[{}]ทำงานเหมือนกับ<...>แต่ไม่ทำลายข้อกำหนดแหล่งที่มาที่ จำกัด

  • คุณสามารถตรวจสอบBrain-FlakและMini-Flak Quines หากคุณต้องการทราบวิธีจัดการกับความท้าทายนี้


1
"ปัจจุบันดีที่สุด" -> "เฉพาะกระแส"
HyperNeutrino

คำตอบ:


33

Mini-Flak 6851113 รอบ

โปรแกรม (ตัวอักษร)

ฉันรู้ว่าคนส่วนใหญ่ไม่ได้คาดหวังว่า Mini-Flak quine จะใช้อักขระที่ไม่สามารถพิมพ์ได้และแม้กระทั่งอักขระแบบหลายไบต์ (ทำให้การเข้ารหัสมีความเกี่ยวข้อง) อย่างไรก็ตาม quine นี้ทำและ unprintables รวมกับขนาดของ quine (93919 ตัวอักษรที่เข้ารหัสเป็น 1,02646 ไบต์ของ UTF-8) ทำให้มันยากที่จะวางโปรแกรมลงในโพสต์นี้

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

(ใช่มันซ้ำไปซ้ำมาจนคุณสามารถเห็นซ้ำหลังจากที่ถูกบีบอัด)

คำถามกล่าวว่า "ฉันขอแนะนำอย่างสูงว่าไม่ควรเรียกใช้โปรแกรมของคุณใน TIO ไม่เพียง แต่ TIO จะช้ากว่าล่ามบนเดสก์ท็อป แต่จะหมดเวลาในอีกประมาณหนึ่งนาทีมันน่าประทับใจมากถ้ามีคนจัดการคะแนนต่ำพอ โปรแกรมของพวกเขาก่อนที่ TIO จะหมดเวลา " ฉันสามารถทำมันได้! ใช้เวลาประมาณ 20 วินาทีในการทำงานกับ TIO โดยใช้ Ruby interpreter: ลองออนไลน์!

โปรแกรม (อ่านง่าย)

ตอนนี้ฉันได้รับโปรแกรมรุ่นที่คอมพิวเตอร์สามารถอ่านได้แล้วลองรุ่นที่มนุษย์สามารถอ่านได้ ฉันได้แปลงไบต์ที่ประกอบ quine เป็น codepage 437 (ถ้าพวกเขามีชุดบิตสูง) หรือภาพควบคุม Unicode (ถ้าพวกเขาเป็นรหัสควบคุม ASCII) เพิ่มช่องว่าง (ช่องว่างก่อนที่มีอยู่ใด ๆ ถูกแปลงเป็นภาพควบคุม ) ใช้การเข้ารหัสความยาวโดยใช้ไวยากรณ์«string×length»และบิตข้อมูลหนักบางส่วนถูกลบออก:

␠
(((()()()()){}))
{{}
    (({})[(()()()())])
    (({})(
        {{}{}((()[()]))}{}
        (((((((({})){}){}{})){}{}){}){}())
        {
            ({}(
                (␀␀!S␠su! … many more comment characters … oq␝qoqoq)
                («()×35» («()×44» («()×44» («()×44» («()×44» («()×45»
                … much more data encoded the same way …
                («()×117»(«()×115»(«()×117»
                «000010101011┬â┬ … many more comment characters … ┬â0┬â┬à00␈␈
                )[({})(
                    ([({})]({}{}))
                    {
                        ((()[()]))
                    }{}
                    {
                        {
                            ({}(((({}())[()])))[{}()])
                        }{}
                        (({}))
                        ((()[()]))
                    }{}
                )]{}
                %Wwy$%Y%ywywy$wy$%%%WwyY%$$wy%$$%$%$%$%%wy%ywywy'×almost 241»
                ,444454545455┬ç┬ … many more comment characters … -a--┬ü␡┬ü-a␡┬ü
            )[{}()])
        }{}
        {}({}())
    )[{}])
    (({})(()()()()){})
}{}{}␊

("เกือบ 241" เป็นเพราะสำเนา 241 ขาดการติดตาม'แต่อย่างอื่น 240 อื่น ๆ )

คำอธิบาย

เกี่ยวกับความคิดเห็น

สิ่งแรกที่ต้องอธิบายคือมีอะไรเกิดขึ้นกับตัวละครที่ไม่สามารถพิมพ์ได้และขยะอื่น ๆ ที่ไม่ใช่คำสั่ง Mini-Flak? คุณอาจคิดว่าการเพิ่มความคิดเห็นในควินทำให้สิ่งต่าง ๆ ยากขึ้น แต่นี่เป็นการแข่งขันความเร็ว (ไม่ใช่การแข่งขันขนาด) หมายความว่าความคิดเห็นจะไม่ส่งผลกระทบต่อความเร็วของโปรแกรม ในขณะเดียวกัน Brain-Flak และ Mini-Flak เพียงแค่ถ่ายโอนเนื้อหาของสแต็คไปยังเอาต์พุตมาตรฐาน หากคุณต้องตรวจสอบให้แน่ใจว่าสแต็กมีอยู่เท่านั้นอักขระที่ประกอบขึ้นเป็นคำสั่งของโปรแกรมของคุณคุณจะต้องใช้รอบทำความสะอาดสแต็ค ตามที่เป็นอยู่ Brain-Flak จะละเว้นอักขระส่วนใหญ่ดังนั้นตราบใดที่เรามั่นใจว่าองค์ประกอบสแต็คขยะไม่ถูกต้องคำสั่ง Brain-Flak (ทำให้นี่เป็น Brain-Flak / Mini-Flak polyglot) และไม่ใช่เชิงลบหรือภายนอก ช่วง Unicode เราสามารถวางมันลงบนสแต็กอนุญาตให้เอาท์พุทและใส่ตัวอักษรเดียวกันในโปรแกรมของเราในที่เดียวกันเพื่อรักษาคุณสมบัติ quine

มีวิธีหนึ่งที่สำคัญอย่างยิ่งที่เราสามารถใช้ประโยชน์จากสิ่งนี้ Quine ทำงานโดยใช้สตริงข้อมูลที่มีความยาวและโดยทั่วไปแล้วเอาต์พุตทั้งหมดจาก Quine จะถูกสร้างขึ้นโดยการจัดรูปแบบสตริงข้อมูลในรูปแบบต่างๆ มีสตริงข้อมูลเดียวเท่านั้นแม้ว่าโปรแกรมจะมีหลายชิ้นก็ตาม ดังนั้นเราต้องสามารถใช้สายข้อมูลเดียวกันเพื่อพิมพ์ส่วนต่างๆของโปรแกรม เคล็ดลับ "ข้อมูลขยะไม่สำคัญ" ช่วยให้เราทำสิ่งนี้ได้ในวิธีที่ง่ายมาก เราจัดเก็บอักขระที่ประกอบขึ้นเป็นโปรแกรมในสายข้อมูลโดยการเพิ่มหรือลบค่าไปยังหรือจากรหัส ASCII ของพวกเขา โดยเฉพาะอย่างยิ่งตัวละครที่ประกอบขึ้นเป็นจุดเริ่มต้นของโปรแกรมจะถูกเก็บไว้เป็นรหัส ASCII + 4 ตัวละครที่ทำขึ้นในส่วนที่ทำซ้ำเกือบ 241 เท่าของรหัส ASCII - 4อักขระทุกตัวของสตริงข้อมูลที่มีอ็อฟเซ็ต; ตัวอย่างเช่นถ้าเราพิมพ์ด้วย 4 เพิ่มไปยังรหัสตัวละครทุกตัวเราจะได้รับซ้ำส่วนหนึ่งซ้ำพร้อมความคิดเห็นบางส่วนก่อนและหลัง (ความคิดเห็นเหล่านั้นเป็นเพียงส่วนอื่น ๆ ของโปรแกรมโดยเปลี่ยนรหัสตัวอักษรเพื่อให้พวกเขาไม่ได้ใช้คำสั่ง Brain-Flak ที่ถูกต้องเนื่องจากมีการเพิ่มออฟเซ็ตผิดเราต้องหลบคำสั่ง Brain-Flak ไม่ใช่เพียงแค่ Mini- คำสั่ง Flak เพื่อหลีกเลี่ยงการละเมิดส่วนที่ของคำถามตัวเลือกออฟเซ็ตได้รับการออกแบบเพื่อให้แน่ใจในเรื่องนี้)

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

โครงสร้างโปรแกรม

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

แต่ละส่วนของโปรแกรมสามารถสร้างผ่าน data string และ formatter ได้ดังนี้

  • ในการสร้าง Outro ให้จัดรูปแบบสตริงข้อมูลด้วย offset +8
  • หากต้องการสร้างตัวจัดรูปแบบสตริงข้อมูลให้จัดรูปแบบสตริงข้อมูลด้วยออฟเซ็ต +4, 241 ครั้ง
  • ในการสร้างสตริงข้อมูลให้จัดรูปแบบสตริงข้อมูลผ่านการเข้ารหัสลงในรูปแบบของแหล่งที่มา
  • ในการผลิตบทนำให้จัดรูปแบบสตริงข้อมูลด้วย offset -4

ดังนั้นสิ่งที่เราต้องทำคือดูว่าส่วนต่าง ๆ ของโปรแกรมทำงานอย่างไร

สตริงข้อมูล

(«()×35» («()×44» («()×44» («()×44» («()×44» («()×45» …

เราต้องการการเข้ารหัสอย่างง่ายสำหรับสตริงข้อมูลเนื่องจากเราต้องสามารถย้อนกลับการเข้ารหัสในรหัส Mini-Flak คุณจะไม่ง่ายกว่านี้อีกมาก!

แนวคิดหลักที่อยู่เบื้องหลัง quine นี้ (นอกเหนือจากเคล็ดลับความคิดเห็น) คือการสังเกตว่ามีเพียงที่เดียวที่เราสามารถเก็บข้อมูลจำนวนมากได้: "ผลรวมของค่าคำสั่งคืน" ภายในระดับการซ้อนของแหล่งโปรแกรม (ซึ่งเป็นที่รู้จักกันทั่วไปว่าเป็นกองซ้อนที่สามแม้ว่า Mini-Flak จะไม่มีสแต็กที่สองดังนั้น "stack stack" น่าจะเป็นชื่อที่ดีกว่าในบริบท Mini-Flak) ความเป็นไปได้อื่น ๆ สำหรับการจัดเก็บข้อมูลจะเป็นสแต็กหลัก / แรก เพราะนั่นคือสิ่งที่เอาท์พุทของเราไปและเราไม่สามารถย้ายเอาท์พุทที่ผ่านมาเก็บข้อมูลด้วยวิธีที่มีประสิทธิภาพจากระยะไกล) และเข้ารหัสลงใน Bignum ในองค์ประกอบสแต็คเดียว (ซึ่งไม่เหมาะสมสำหรับปัญหานี้เพราะใช้เวลา ดึงข้อมูลจากมัน); เมื่อคุณกำจัดสิ่งเหล่านี้สแต็กการทำงานเป็นตำแหน่งเดียวที่เหลืออยู่

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

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

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

ตัวจัดรูปแบบสตริงข้อมูล

)[({})(
    ([({})]({}{}))
    {
        ((()[()]))
    }{}
    {
        {
            ({}(((({}())[()])))[{}()])
        }{}
        (({}))
        ((()[()]))
    }{}
)]{}

ตัวจัดรูปแบบของสายข้อมูลทำจาก 241 ส่วนซึ่งแต่ละส่วนมีรหัสเหมือนกัน (ส่วนหนึ่งมีความคิดเห็นที่แตกต่างกันเล็กน้อย) ซึ่งแต่ละรูปแบบจะจัดรูปแบบอักขระหนึ่งตัวของสตริงข้อมูล (เราไม่สามารถใช้ลูปที่นี่: เราต้องการความไม่สมดุล)ในการอ่านสตริงข้อมูลผ่านการจับคู่ที่ไม่สมดุลของมัน(และเราไม่สามารถใส่หนึ่งใน{…}วงในนั้นเป็นรูปแบบของลูปเดียวที่มีอยู่ดังนั้นเรา " คลี่ "ฟอร์แมตเตอร์และรับอินโทร / เอาท์พุทเพื่อเอาท์พุทสตริงข้อมูลด้วยออฟเซ็ตของตัวจัดรูปแบบ 241 ครั้ง)

)[({})( … )]{}

ส่วนนอกสุดขององค์ประกอบตัวจัดรูปแบบอ่านองค์ประกอบหนึ่งของสายอักขระข้อมูล ความเรียบง่ายของการเข้ารหัสสตริงข้อมูลนำไปสู่ความซับซ้อนเล็กน้อยในการอ่านมัน เราเริ่มต้นด้วยการปิดข้อมูลที่ไม่ตรงกัน(…)ในสตริงข้อมูลแล้วลบ[…]ค่าสองค่าคือข้อมูลที่เราเพิ่งอ่านจากสตริงข้อมูล ( ({})) และค่าส่งคืนของโปรแกรมที่เหลือ เราคัดลอกค่าตอบแทนของส่วนที่เหลือขององค์ประกอบการจัดรูปแบบที่มีและเพิ่มสำเนาให้เป็นเวอร์ชั่นเมื่อตะกี้กับ(…) {}ผลลัพธ์ที่ได้คือค่าส่งคืนขององค์ประกอบสตริงข้อมูลและองค์ประกอบตัวจัดรูปแบบร่วมกันคือตัวเลขลบกับตัวเลขลบค่าตอบแทนบวกค่าตอบแทนหรือ 0; นี่เป็นสิ่งจำเป็นในการทำให้องค์ประกอบสตริงข้อมูลถัดไปสร้างค่าที่ถูกต้อง

([({})]({}{}))

ตัวจัดรูปแบบใช้องค์ประกอบสแต็คด้านบนเพื่อทราบโหมดที่อยู่ใน (0 = รูปแบบในการจัดรูปแบบสตริงข้อมูลค่าอื่น ๆ = ออฟเซ็ตไปยังเอาต์พุตด้วย) อย่างไรก็ตามเพียงแค่อ่านสตริงข้อมูลดาต้าอยู่ด้านบนของรูปแบบบนสแต็กและเราต้องการให้มันอยู่ในรูปแบบอื่น รหัสนี้เป็นตัวแปรสั้นรหัสแลกเปลี่ยน Brain-Flak การข้างต้นเพื่อข้างต้น +  ; ไม่เพียง แต่จะสั้นกว่าเท่านั้น แต่ยังมีประโยชน์มากขึ้น (ในกรณีนี้) เนื่องจากผลข้างเคียงของการเพิ่มbไปยังaนั้นไม่เป็นปัญหาเมื่อbคือ 0 และเมื่อbไม่ใช่ 0 จะเป็นการคำนวณออฟเซ็ตสำหรับเรา

{
    ((()[()]))
}{}
{
    …
    ((()[()]))
}{}

Brain-Flak มีโครงสร้างการควบคุมเพียงหนึ่งโครงสร้างเท่านั้นดังนั้นหากเราต้องการสิ่งอื่นนอกเหนือจากwhileลูปมันจะใช้งานได้เล็กน้อย นี่คือโครงสร้าง "ลบล้าง"; หากมี 0 อยู่ด้านบนของสแต็กมันจะลบออกมิฉะนั้นจะวาง 0 ไว้บนสุดของสแต็ก (มันใช้งานได้ง่าย: ตราบใดที่ไม่มี 0 อยู่ด้านบนของสแต็กให้กด 1 - 1 ไปที่สแต็กสองครั้งเมื่อเสร็จแล้วให้เปิดองค์ประกอบสแต็กด้านบน)

เป็นไปได้ที่จะวางโค้ดไว้ในโครงสร้างลบล้างอย่างที่เห็นที่นี่ รหัสจะทำงานถ้าด้านบนสุดของสแต็กไม่ใช่ศูนย์ ดังนั้นถ้าเรามีสองโครงสร้างที่ขัดแย้งกันสมมติว่าองค์ประกอบสแต็คสองอันดับแรกไม่ใช่ทั้งศูนย์พวกเขาจะยกเลิกซึ่งกันและกัน แต่โค้ดใด ๆ ในโครงสร้างแรกจะทำงานเฉพาะในกรณีที่องค์ประกอบสแต็คด้านบนไม่ใช่ศูนย์และโค้ดภายใน โครงสร้างที่สองจะทำงานเฉพาะในกรณีที่องค์ประกอบสแต็คด้านบนเป็นศูนย์ กล่าวอีกนัยหนึ่งสิ่งนี้เทียบเท่ากับคำสั่ง if-then-else

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

{
    ({}(((({}())[()])))[{}()])
}{}
(({}))

นี่คือวิธีที่เราทำ {({}( … )[{}()])}{}โครงสร้างควรจะคุ้นเคยเป็นห่วงที่มีหมายเลขเฉพาะของการทำซ้ำ (ซึ่งทำงานโดยการย้ายเคาน์เตอร์ห่วงการกองการทำงานและถือมันมีมันจะปลอดภัยจากรหัสอื่น ๆ เพราะการเข้าถึงกองการทำงานจะเชื่อมโยงกับ ระดับการซ้อนของโปรแกรม) เนื้อความของลูปคือ((({}())[()]))ซึ่งสร้างสำเนาสามชุดขององค์ประกอบสแต็กด้านบนและเพิ่ม 1 ถึงต่ำสุด กล่าวอีกนัยหนึ่งมันแปลง 40 ที่ด้านบนของสแต็กเป็น 40 สูงกว่า 40 สูงกว่า 41 หรือดูเป็น ASCII (เป็น((); ทำงานนี้ซ้ำ ๆ จะทำให้(เข้า(()เข้า(()()เข้า(()()()และอื่น ๆ จึงเป็นวิธีที่ง่ายในการสร้างสตริงข้อมูลของเรา (สมมติว่ามี(อยู่ด้านบนของสแต็คที่มีอยู่แล้ว)

เมื่อเราวนลูปเสร็จแล้วให้ทำ(({}))ซ้ำส่วนบนสุดของสแต็ก (ดังนั้นตอนนี้((()…จะเริ่มแทน(()…การ(ใช้ลีดเดอร์ตัวถัดไปจะใช้การคัดลอกต่อไปของฟอร์แมตสตริงข้อมูลเพื่อจัดรูปแบบอักขระถัดไป(()(()…จากนั้น(()()(()…เป็นต้นไปดังนั้นสิ่งนี้จะสร้างการแยก(ในสตริงข้อมูล)

%Wwy$%Y%ywywy$wy$%%%WwyY%$$wy%$$%$%$%$%%wy%ywywy'

มีบิตสุดท้ายที่น่าสนใจในตัวจัดรูปแบบสตริงข้อมูล ตกลงดังนั้นส่วนใหญ่นี่เป็นเพียง outro เลื่อน 4 codepoints ลง; อย่างไรก็ตามเครื่องหมายอะโพสโทรฟีในตอนท้ายอาจมองออกไปนอกสถานที่ '(codepoint 39) จะเปลี่ยนเป็น+(codepoint 43) ซึ่งไม่ใช่คำสั่ง Brain-Flak ดังนั้นคุณอาจเดาได้ว่ามันอยู่ที่นั่นเพื่อจุดประสงค์อื่น

เหตุผลที่นี่คือเนื่องจากตัวจัดรูปแบบของสตริงข้อมูลคาดว่าจะมี(บนสแต็กอยู่แล้ว (มันไม่มีตัวอักษร 40 ที่ใดก็ได้) 'จริง ๆ แล้วที่จุดเริ่มต้นของบล็อกที่ถูกทำซ้ำเพื่อสร้างตัวจัดรูปแบบสายอักขระข้อมูลไม่ใช่จุดสิ้นสุดดังนั้นหลังจากตัวอักขระของตัวจัดรูปแบบสายอักขระข้อมูลถูกผลักลงบนสแต็ก (และรหัสกำลังจะย้ายไปพิมพ์สตริงข้อมูล ตัวมันเอง) ตัวนอกปรับ 39 ที่ด้านบนของสแต็กเป็น 40 พร้อมสำหรับตัวจัดรูปแบบ (ตัวจัดรูปแบบที่รันอยู่ในขณะนี้ไม่ใช่ตัวแสดงในแหล่งที่มา) เพื่อใช้งาน นั่นเป็นเหตุผลที่เรามีสำเนาของตัวจัดรูปแบบ "เกือบ 241" สำเนาแรกไม่มีอักขระตัวแรก และอักขระนั้นอะพอสโทรฟีเป็นหนึ่งในสามตัวอักษรในสตริงข้อมูลที่ไม่ตรงกับรหัส Mini-Flak บางแห่งในโปรแกรม มันมีวิธีการให้ค่าคงที่อย่างหมดจด

คำนำและนอกเขต

(((()()()()){}))
{{}
    (({})[(()()()())])
    (({})(
        {{}{}((()[()]))}{}
        (((((((({})){}){}{})){}{}){}){}())
        {
            ({}(
                (␀␀!S␠su! … many more comment characters … oq␝qoqoq)
                …
            )[{}()])
        }{}
        {}({}())
    )[{}])
    (({})(()()()()){})
}{}{}␊

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

(((()()()()){}))

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

มีตัวแทนจำนวนอื่น ๆ ของหมายเลข 8 ที่ไม่ยาวไปกว่านี้ อย่างไรก็ตามเมื่อไปเพื่อรหัสที่เร็วที่สุดนี้เป็นตัวเลือกที่ดีที่สุดแน่นอน สำหรับสิ่งหนึ่งการใช้()()()()นั้นเร็วกว่าพูด(()()){}เพราะทั้งคู่มีความยาว 8 ตัวอักษร แต่ก่อนคือรอบเร็วกว่าเนื่องจาก(…)นับเป็น 2 รอบ แต่()เป็นเพียงหนึ่งรอบเท่านั้น การบันทึกหนึ่งรอบจะน้อยมากเมื่อเทียบกับการพิจารณาที่ใหญ่กว่าสำหรับแม้ว่า: (และ)มี codepoints ที่ต่ำกว่า{และ}ดังนั้นการสร้างส่วนข้อมูลสำหรับพวกเขาจะเร็วขึ้นมาก (และส่วนของข้อมูลจะใช้พื้นที่น้อยลงในรหัส เกินไป).

{{} … }{}{}

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

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

(({})[(()()()())])

รหัสนี้จะผลัก 4 และf  - 4 เหนือองค์ประกอบสแต็กfในขณะที่ปล่อยองค์ประกอบนั้นไว้ เรากำลังคำนวณรูปแบบสำหรับการคำนวณซ้ำครั้งถัดไปล่วงหน้า (ในขณะที่เรามีค่าคงที่ 4 ที่มีประโยชน์) และพร้อมรับสแต็กในลำดับที่ถูกต้องสำหรับส่วนต่อไปของโปรแกรม: เราจะใช้fเป็นรูปแบบสำหรับ การวนซ้ำนี้และ 4 จำเป็นก่อนหน้านั้น

(({})( … )[{}])

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

{{}{}((()[()]))}{}

การทดสอบเพื่อดูว่าออฟเซ็ตเป็น 4 (เช่นf  - 4 คือ 0) ถ้าเป็นเช่นนั้นเรากำลังพิมพ์ตัวจัดรูปแบบสตริงข้อมูลดังนั้นเราจึงจำเป็นต้องเรียกใช้ตัวจัดรูปแบบข้อมูลและตัวจัดรูปแบบของ 241 ครั้งแทนที่จะเป็นเพียงครั้งเดียวที่ออฟเซ็ตนี้ รหัสนั้นค่อนข้างง่าย: ถ้าf  - 4 ไม่ใช่ศูนย์ให้แทนที่f  - 4 และ 4 เองด้วยศูนย์ จากนั้นในกรณีใดกรณีหนึ่งให้เปิดองค์ประกอบสแต็กด้านบน ตอนนี้เรามีตัวเลขด้านบนfบนสแต็กทั้ง 4 (ถ้าเราต้องการพิมพ์การวนซ้ำนี้ 241 ครั้ง) หรือ 0 (ถ้าเราต้องการพิมพ์เพียงครั้งเดียว)

(
    ((((((({})){}){}{})){}{}){}){}
    ()
)

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

ในฐานะที่เป็นบันทึกด้านข้างคุณสามารถใช้ตัวค้นหาตัวเลข Underloadซึ่งสร้างตัวเลข Church ในรูปแบบ Underload เพื่อค้นหาหมายเลขที่เหมาะสมใน Mini-Flak เช่นกัน Underload numerals (นอกเหนือจากศูนย์) ใช้การดำเนินการ "องค์ประกอบสแต็คด้านบนที่ซ้ำกัน" :และ "รวมองค์ประกอบสแต็กสองอันดับแรก" *; การดำเนินงานทั้งผู้ที่อยู่ในสมอง Flak ดังนั้นคุณก็แปล:ไป), *เพื่อ{}, ย่อหน้า{}, และเพิ่มพอ(ที่เริ่มต้นเพื่อความสมดุลของ (นี่คือการผสมผสานการใช้แปลกของกองหลักและสแต็คการทำงาน แต่การทำงาน)

ส่วนรหัสเฉพาะนี้ใช้คริสตจักรตัวเลข 60 (อย่างมีประสิทธิภาพ "คูณด้วย 60" ตัวอย่าง) พร้อมกับการเพิ่มเพื่อสร้างการแสดงออก 60 x  + 1 ดังนั้นถ้าเรามี 4 จากขั้นตอนก่อนหน้านี้ให้เรามีค่า เป็น 241 หรือถ้าเรามี 0 เราเพิ่งได้ค่า 1 นั่นคือนี่จะคำนวณจำนวนการวนซ้ำที่เราต้องการอย่างถูกต้อง

ทางเลือกของ 241 ไม่ใช่เรื่องบังเอิญ มันเป็นค่าที่เลือกให้เป็น) ความยาวโดยประมาณที่โปรแกรมจะสิ้นสุดลงและ b) 1 มากกว่า 4 ครั้งต่อจำนวนรอบ ในกรณีนี้จำนวนรอบที่ 60 มีแนวโน้มที่จะเป็นตัวแทนที่สั้นกว่าเนื่องจากตัวเลขศาสนจักรมีความยืดหยุ่นในการคัดลอกมากกว่า โปรแกรมประกอบด้วย padding ในภายหลังเพื่อให้ความยาวสูงสุดถึง 241

{
    ({}(
        …
    )[{}()])
}{}

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

(␀␀!S␠su! … many more comment characters … oq␝qoqoq)

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

ยิ่งกว่านั้นอักขระ NUL เหล่านั้นในตอนเริ่มต้นของความคิดเห็นที่เห็นได้ชัดไม่ได้ชดเชยจากสิ่งใด (แม้ความแตกต่างระหว่าง +8 และ -4 ไม่เพียงพอที่จะเปลี่ยน(เป็น NUL) สิ่งเหล่านี้เป็นช่องว่างที่บริสุทธิ์เพื่อให้สายอักขระข้อมูล 239 องค์ประกอบถึง 241 องค์ประกอบ (ซึ่งจ่ายเองง่าย ๆ : มันต้องใช้เวลามากกว่าสองไบต์ในการสร้าง 1 กับ 239 มากกว่า 1 กับ 241 เมื่อคำนวณจำนวนการทำซ้ำที่ต้องการ ) NUL ถูกใช้เป็นอักขระ padding เนื่องจากมี codepoint ที่ต่ำที่สุดที่เป็นไปได้ (ทำให้ซอร์สโค้ดสำหรับสตริงข้อมูลสั้นลงและทำให้เอาต์พุตเร็วขึ้น)

{}({}())

วางองค์ประกอบสแต็คด้านบน (รูปแบบที่เราใช้) เพิ่ม 1 ถึงถัดไป (อักขระตัวสุดท้ายที่จะออกเช่นตัวอักษรตัวแรกที่จะพิมพ์ของส่วนโปรแกรมที่เราเพิ่งจัดรูปแบบ) เราไม่ต้องการรูปแบบเก่าอีกต่อไป (รูปแบบใหม่ซ่อนอยู่ในสแต็กทำงาน); และเพิ่มขึ้นเป็นอันตรายในกรณีส่วนใหญ่และการเปลี่ยนแปลง'ที่ปลายด้านหนึ่งของการแสดงแหล่งที่มาของการจัดรูปแบบสตริงข้อมูลลง((ซึ่งเป็นสิ่งจำเป็นใน stack สำหรับครั้งต่อไปเราจะดำเนินการจัดรูปแบบในการจัดรูปแบบสตริงข้อมูลที่ตัวเอง) เราต้องการการแปลงเช่นนั้นใน outro หรืออินโทรเพราะบังคับให้องค์ประกอบตัวจัดรูปแบบสตริงข้อมูลเริ่มต้นด้วย(จะทำให้มันค่อนข้างซับซ้อน (ตามที่เราต้องการปิด(แล้วยกเลิกผลในภายหลัง) และเราต้องการสร้างอะไรพิเศษ(เพราะเรามีตัวจัดรูปแบบเกือบ 241 ชุดเท่านั้นไม่ใช่ทั้งหมด 241 (ดังนั้นจึงเป็นเรื่องที่ดีที่สุดที่ตัวละครที่ไม่เป็นอันตรายเช่น'นั้นจะหายไป)

(({})(()()()()){})

ในที่สุดการทดสอบการออกจากวง ด้านบนปัจจุบันของสแต็กหลักคือรูปแบบที่เราต้องการสำหรับการทำซ้ำครั้งถัดไป (ซึ่งเพิ่งกลับมาจากสแต็กทำงาน) สำเนานี้และเพิ่ม 8 ลงในสำเนา; ค่าที่ได้จะถูกยกเลิกในครั้งถัดไปรอบวง อย่างไรก็ตามหากเราเพิ่งพิมพ์คำนำ, ค่าชดเชยคือ -4 ดังนั้นค่าชดเชยสำหรับ "การคำนวณซ้ำครั้งถัดไป" จะเป็น -8; -8 + 8 คือ 0 ดังนั้นลูปจะออกแทนที่จะไปต่อที่การวนซ้ำในภายหลัง


16

128,673,515 รอบ

ลองออนไลน์

คำอธิบาย

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


บล็อกของรหัสนี้มีสองข้อกำหนด

  • จะต้องใช้ตัวเลขและส่งออกเฉพาะรหัสตัวอักษรสำหรับตัวละครนั้น

  • มันจะต้องง่ายในการสร้างตารางการค้นหาซ้ำ ๆ ใน Brain-Flak

ในการสร้างบล็อกนี้ฉันใช้วิธีการพิสูจน์ซ้ำว่า Miniflak สมบูรณ์ในทัวริง สำหรับแต่ละตัวเลขมีบล็อกของรหัสที่มีลักษณะเช่นนี้:

(({}[()])[(())]()){(([({}{})]{}))}{}{(([({}{}(%s))]{}))}{}

วิธีนี้จะลบหนึ่งตัวจากตัวเลขที่อยู่ด้านบนสุดของสแต็กและถ้าศูนย์%sส่งตัวเลขที่อยู่ข้างใต้ เนื่องจากแต่ละชิ้นมีขนาดลดลงทีละหนึ่งถ้าคุณเริ่มต้นด้วย n บนสแต็คคุณจะได้รับข้อมูลคืนที่ n

นี่เป็นสิ่งที่ดีและเป็นโมดูลดังนั้นจึงสามารถเขียนได้โดยโปรแกรมได้อย่างง่ายดาย


ต่อไปเราต้องตั้งค่าเครื่องที่แปลหน่วยความจำนี้เป็นแหล่งที่มา ประกอบด้วย 3 ส่วนดังนี้

(([()]())())
{({}[(
  -Look up table-
 )]{})
 1. (({}[()])[(())]()){(([({}{})]{}))}{}{([({}{}(([{}]))(()()()()()))]{})}{}

 2. (({}[()])[(())]()){(([({}{})]{}))}{}{([({}{}
      (({}[(
      ({}[()(((((()()()()()){}){}){}))]{}){({}[()(({}()))]{}){({}[()(({}((((()()()){}){}){}()){}))]{}){({}[()(({}()()))]{}){({}[()(({}(((()()()()())){}{}){}))]{}){([(({}{}()))]{})}}}}}{}
      (({}({}))[({}[{}])])
     )]{}({})[()]))
      ({[()]([({}({}[({})]))]{})}{}()()()()()[(({}({})))]{})
    )]{})}{}

 3. (({}[()])[(())]()){(([({}{})]{}))}{}{([({}{}
     (({}(({}({}))[({}[{}])][(
     ({}[()(
      ([()](((()()[(((((((()()()){})())){}{}){}){})]((((()()()()())){}{}){})([{}]([()()](({})(([{}](()()([()()](((((({}){}){}())){}){}{}))))))))))))
     )]{})
     {({}[()(((({})())[()]))]{})}{}
     (([(((((()()()()){}){}()))){}{}([({})]((({})){}{}))]()()([()()]({}(({})([()]([({}())](({})([({}[()])]()(({})(([()](([({}()())]()({}([()](([((((((()()()())()){}){}){}()){})]({}()(([(((((({})){}){}())){}{})]({}([((((({}())){}){}){}()){}()](([()()])(()()({}(((((({}())())){}{}){}){}([((((({}))){}()){}){}]([((({}[()])){}{}){}]([()()](((((({}())){}{}){}){})(([{}](()()([()()](()()(((((()()()()()){}){}){}()){}()(([((((((()()()())){}){}())){}{})]({}([((((({})()){}){}){}()){}()](([()()])(()()({}(((((({}){}){}())){}){}{}(({})))))))))))))))))))))))))))))))))))))))))))))))
     )]{})[()]))({()()()([({})]{})}{}())
    )]{})}{}

   ({}[()])
}{}{}{}
(([(((((()()()()){}){}())){}{})]((({}))([()]([({}())]({}()([()]((()([()]((()([({})((((()()()()){}){}()){})]()())([({})]({}([()()]({}({}((((()()()()()){}){}){}))))))))))))))))))

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

1

ส่วนที่ 1 เป็นส่วนตั้งค่าที่เรียบง่าย

โปรแกรมจะบอกแบบสอบถามแรกส่วนที่ 1 และตัวเลข 0 ไม่มีข้อมูล 0 อยู่ดังนั้นแทนที่จะส่งคืนค่านั้นจะเป็นการลดแบบสอบถามเพียงครั้งเดียวสำหรับแต่ละข้อมูล สิ่งนี้มีประโยชน์เพราะเราสามารถใช้ผลลัพธ์เพื่อกำหนดจำนวนข้อมูลซึ่งจะมีความสำคัญในส่วนของอนาคต ส่วนที่ 1 บันทึกจำนวนข้อมูลโดยการปฏิเสธผลลัพธ์และแบบสอบถามส่วนที่ 2 และตัวเลขสุดท้าย ปัญหาเดียวคือเราไม่สามารถสืบค้นส่วนที่ 2 ได้โดยตรง เนื่องจากมีการลดลงเหลืออีกเราจำเป็นต้องค้นหาส่วนที่ไม่มีอยู่จริง 5 ในความเป็นจริงนี้จะเป็นกรณีที่ทุกครั้งที่เราสอบถามส่วนในส่วนอื่น ฉันจะเพิกเฉยต่อสิ่งนี้ในคำอธิบายของฉันอย่างไรก็ตามหากคุณกำลังมองหารหัสแค่จำไว้ 5 หมายถึงกลับไปส่วนและ 4 หมายถึงเรียกใช้ส่วนเดียวกันอีกครั้ง

2

ส่วนที่ 2 ถอดรหัสข้อมูลเป็นอักขระที่ประกอบขึ้นเป็นรหัสหลังจากบล็อกข้อมูล แต่ละครั้งที่คาดว่าสแต็กจะปรากฏดังนี้:

Previous query
Result of query
Number of data
Junk we shouldn't touch...

มันแมปผลลัพธ์ที่เป็นไปได้แต่ละรายการ (ตัวเลขจาก 1 ถึง 6) เป็นหนึ่งในหกตัวอักษร Miniflak ที่ถูกต้อง ( (){}[]) และวางไว้ใต้จำนวนข้อมูลด้วย "ขยะที่เราไม่ควรแตะ" สิ่งนี้ทำให้เราได้สแต็คเช่น:

Previous query
Number of data
Junk we shouldn't touch...

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

Next query
Number of data
Junk we shouldn't touch...

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

3

ส่วนที่ 3 สร้างบล็อกข้อมูลโดยการสอบถาม RAM ของเราเช่นเดียวกับส่วนที่ 3

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


([()]())(()()()()){({}[(หลังจากที่วงได้รับการเรียกใช้โปรแกรมเพียงแค่ต้องการที่จะผลักดันบิตแรกของควิน ฉันทำสิ่งนี้ด้วยรหัสต่อไปนี้ที่ใช้เทคนิค Kolmogorov มาตรฐานที่ซับซ้อน

(([(((((()()()()){}){}())){}{})]((({}))([()]([({}())]({}()([()]((()([()]((()([({})((((()()()()){}){}()){})]()())([({})]({}([()()]({}({}((((()()()()()){}){}){}))))))))))))))))))

ฉันหวังว่านี่ชัดเจน โปรดแสดงความคิดเห็นหากคุณกำลังสับสนเกี่ยวกับอะไร


ใช้เวลาในการรันนานเท่าไหร่? มันถึงเวลาแล้วที่ TIO
Pavel

@Pavel ฉันไม่ได้เรียกใช้บน TIO เพราะนั่นจะช้าอย่างไม่น่าเชื่อฉันใช้ล่ามแบบเดียวกับที่ TIO ใช้ ( ทับทิมหนึ่งตัว ) ใช้เวลาประมาณ 20 นาทีในการรันบนแร็คเซิร์ฟเวอร์เก่าที่ฉันเข้าถึงได้ ใช้เวลาประมาณ 15 นาทีใน Crain-Flak แต่ Crain-Flak ไม่มีการดีบักแฟล็กดังนั้นฉันไม่สามารถให้คะแนนได้หากไม่ใช้ในล่าม Ruby
ข้าวสาลีตัวช่วยสร้าง

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