คุณมีเคล็ดลับทั่วไปอะไรในการเล่นกอล์ฟใน brainfuck? ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะเจาะจงกับ brainfuck (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ) กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ
คุณมีเคล็ดลับทั่วไปอะไรในการเล่นกอล์ฟใน brainfuck? ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะเจาะจงกับ brainfuck (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ) กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ
คำตอบ:
การใส่หนึ่งเคล็ดลับต่อคำตอบจะเป็นคำตอบที่มากเกินไป
เรียนรู้ที่จะคิดใน Brainfuck มันแตกต่างจากสิ่งอื่นมาก อ่านและเขียนและเขียนใหม่และเขียนโปรแกรม brainfuck จำนวนมาก ภาษาไม่ได้ให้อะไรมากมายกับคุณดังนั้นจึงเป็นเรื่องสำคัญที่จะต้องใช้สิ่งที่ทำให้คุณยืดหยุ่นและมีประสิทธิภาพ อย่าปล่อยให้สิ่งที่เป็นนามธรรมอยู่ระหว่างคุณกับภาษา - เข้าไปข้างในและต่อสู้กับมัน
รับความสะดวกสบายมากด้วยการควบคุมการไหลแบบไม่ทำลาย เมื่อต้องการออกจากลูปการตัดสินใจแทนที่จะทำให้เซลล์เริ่มต้นเป็นศูนย์โดยการคัดลอกไปที่อื่นแล้วคัดลอกกลับมาหลังจากออกจากลูปการย้ายตัวชี้ไปยังศูนย์ที่มีอยู่ก่อนจะดีกว่า ใช่นี่หมายถึงตัวชี้จะอยู่ในสถานที่ที่แตกต่างกันขึ้นอยู่กับว่าคุณผ่านลูปหรือไม่ แต่นั่นก็หมายความว่าสถานที่เหล่านั้นอาจมีการจัดเรียงที่แตกต่างกันของศูนย์และศูนย์ที่ไม่ใช่ศูนย์ซึ่งคุณสามารถใช้ เทคนิคนี้เป็นพื้นฐานในการเขียนโปรแกรม Brainfuck ที่ดีและรูปแบบต่าง ๆ ของมันจะพิสูจน์ว่ามีประโยชน์อยู่เสมอ
นั่นและความจริงที่ว่าทุก>
หรือ<
ค่าใช้จ่ายหมายความว่ารายละเอียดของรูปแบบหน่วยความจำมีความสำคัญ ลองใช้เลย์เอาต์ที่หลากหลายในแบบที่คุณมีความอดทน และจำไว้ว่าเลย์เอาต์หน่วยความจำของคุณไม่จำเป็นต้องมีการจับคู่ข้อมูลกับสถานที่อย่างเข้มงวด มันสามารถแปรเปลี่ยนไประหว่างการใช้งานจริง
ในระดับที่ใหญ่ขึ้นให้พิจารณาและลองใช้อัลกอริทึมที่แตกต่างหลากหลาย ตอนแรกมันจะไม่ชัดเจนว่าอัลกอริทึมใดจะดีที่สุด อาจไม่ชัดเจนว่าแนวทางพื้นฐานแบบใดที่ดีที่สุดและอาจเป็นสิ่งที่แตกต่างจากสิ่งที่ดีที่สุดในภาษาปกติ
หากคุณกำลังจัดการกับข้อมูลขนาดใหญ่หรือขนาดตัวแปรดูว่ามีวิธีใดบ้างที่คุณสามารถจัดการกับข้อมูลในพื้นที่ได้โดยไม่ต้องติดตามว่ามันมีขนาดใหญ่หรือตำแหน่งตัวเลขของคุณอยู่ในนั้นหรือไม่
ข้อมูลเดียวกันอาจเป็นสองสิ่งที่แตกต่างกัน (ส่วนใหญ่มักเป็นตัวเลขหรือตัวอักษรและเครื่องหมายตำแหน่งที่ไม่ใช่ศูนย์ แต่ดูrandom.bโดยที่ตัวนับบิตสองเท่าเป็นค่าของเซลล์หนึ่งเซลล์ของหุ่นยนต์อัตโนมัติ)
<+<
รหัสเดียวกันสามารถทำสองสิ่งที่แตกต่างกันและมันง่ายมากที่จะทำให้มันทำเช่นนั้นในภาษาที่เป็นรหัสทั่วไปเป็น ระวังความเป็นไปได้ดังกล่าว ในความเป็นจริงคุณอาจสังเกตเห็นเป็นครั้งคราวแม้ในสิ่งที่ดูเหมือนจะเป็นโปรแกรมที่เขียนดีว่ามีบางส่วนเล็ก ๆ ที่สามารถลบได้ทั้งหมดไม่มีอะไรเพิ่มและสิ่งที่จะเกิดขึ้นโดยยังคงไม่มีที่ติ
ในภาษาส่วนใหญ่คุณใช้คอมไพเลอร์หรือล่ามบ่อยครั้งเพื่อตรวจสอบพฤติกรรมของโปรแกรมของคุณ ภาษา Brainfuck ต้องการการควบคุมแนวคิดที่มากกว่า ถ้าคุณต้องการคอมไพเลอร์เพื่อบอกคุณว่าโปรแกรมของคุณทำอะไรคุณไม่เข้าใจโปรแกรมของคุณมากพอและคุณอาจต้องจ้องมองมันมากกว่านี้ - อย่างน้อยถ้าคุณต้องการมีภาพที่ชัดเจนเพียงพอ แนวคิดที่เป็นรัศมีของโปรแกรมที่คล้ายกันจะดีในสนามกอล์ฟ ด้วยการฝึกฝนคุณจะต้องสร้างโปรแกรมของคุณเป็นโหลกว่ารุ่นก่อนที่จะลองใช้โปรแกรมหนึ่งและคุณจะมั่นใจได้ 95% ว่าโปรแกรมที่สั้นที่สุดของคุณจะทำงานอย่างถูกต้อง
โชคดี! มีคนเพียงไม่กี่คนที่อยากเขียน Brainfuck ให้รัดกุม แต่ฉันคิดว่านั่นเป็นวิธีเดียวที่ภาษาจะสามารถแสดงให้เห็นถึงความสนใจอย่างต่อเนื่อง - ในรูปแบบศิลปะที่ไม่ชัดเจน
เคล็ดลับที่นี่:
Esolangs หน้าคงมีรายการที่มีประโยชน์อย่างมากในวิธีที่สั้นที่สุดในการสร้างค่าเฉพาะ ฉันพบว่าตัวเองกำลังปรึกษาหน้านี้อย่างน้อยสองครั้งต่อโปรแกรม
+++[[<+>>++<-]>]
ชุดนี้ติดตั้งเทปในรูปแบบ 3 * n ^ 2 ซึ่งดูเหมือน
3 6 12 24 48 96 192 128 0 0 '
ทำไมสิ่งนี้สำคัญมาก
ลองลงรายการ:
0
a
A
สำหรับจากอัลกอริทึมนี้เราจะเริ่มต้นทุกลำดับในช่วง ASCII พร้อมกับตัวนับสำหรับแต่ละบรรทัดและบรรทัดใหม่ที่เข้าถึงได้ง่าย
ตัวอย่างการปฏิบัติ:
การพิมพ์ตัวอักษรและตัวเลขตัวพิมพ์ใหญ่และเล็กทั้งหมด
ด้วยอัลกอริทึม:
+++[[<+>>++<-]>]<<[-<->]<<<<++[->>+.>+.<<<]<--[>>.+<<-]
โดยไม่ต้อง:
+++++++++++++[->+++++++>++>+++++>++++>+<<<<<]>+++++>[-<+.>>.+<]>>---->---[-<.+>]
เราใช้ไบต์ส่วนใหญ่ในการเริ่มต้นเทปในตัวอย่างที่สอง บางส่วนมันชดเชยด้วยการเคลื่อนไหวพิเศษในตัวอย่างแรก แต่วิธีนี้มีข้อดีอย่างชัดเจน
สองอัลกอริทึมที่น่าสนใจอื่น ๆ ในหลอดเลือดดำเดียวกัน:
3 * 2 ^ n + 1:
+++[[<+>>++<-]+>]
Tape: 4 7 13 25 49 65 197 129 1 0'
สิ่งนี้จะชดเชยค่าที่ 1 ซึ่งทำให้บางสิ่งสำเร็จ มันทำให้ 12 carriage return, 64 การเริ่มต้นที่แท้จริงของตัวอักษรตัวพิมพ์ใหญ่และ 24 อันใกล้ 26
2 ^ n:
+[[<+>>++<-]>]
Tape: 1 2 4 8 16 32 64 128
เนื่องจาก 64 ดีสำหรับตัวอักษรตัวพิมพ์ใหญ่ 32 คือ ASCII สำหรับเว้นวรรคและ 128 สามารถใช้เป็นตัวนับสำหรับ 26 (130/5 = 26) วิธีนี้สามารถบันทึกไบต์ในบางสถานการณ์ที่ไม่ต้องใช้ตัวเลขและตัวอักษรพิมพ์เล็ก
+[[-<+>>+>+<<]>]
) หรือการประมวลผลจำนวนที่มากขึ้น / ลบ ข้อเสียคือวิธีการทั่วไปบางอย่างเช่น[-]
และ[->+<]
ไม่สามารถพึ่งพาได้ในกรณีที่จำนวนเป็นค่าลบทุกครั้งที่คุณควรมีความคิดเห็นเกี่ยวกับตำแหน่งที่ตัวชี้ควรสัมพันธ์กับข้อมูลที่อยู่รอบ ๆ และตรวจสอบให้แน่ใจว่าคุณทราบช่วงของค่าที่เป็นไปได้ของแต่ละเซลล์ นี่คือโดยเฉพาะอย่างยิ่งความสำคัญเมื่อคุณแยกตัวชี้ต่อหน้าวงเนื่องจากคุณต้องการรวมความเป็นไปได้สองอย่างเข้าด้วยกันในภายหลัง
ณ จุดใดรหัสของฉันเกลื่อนไปด้วยความคิดเห็นในบรรทัดอื่น ๆ ที่มีลักษณะเช่นนี้:
*0 *dat a_1 ? 0' !0 0*
or
*0 *dat 0' ap1 0 !0 0*
คำแนะนำพิเศษบางอย่างคือการกำหนดสัญลักษณ์ความหมายพิเศษ ในตัวอย่างข้างต้น'
คือที่ชี้เป็น*
วิธีการทำซ้ำในทิศทางที่?
หมายความว่าเซลล์ที่มีค่าที่ไม่รู้จัก!0
หมายถึงไม่ใช่ศูนย์เซลล์_
แทนหา-
และแทนสำหรับp
+
or
บอกเป็นนัยว่าเทปอาจมีลักษณะเป็นตัวแทนอย่างใดอย่างหนึ่งและจำเป็นต้องได้รับการจัดการเช่นนี้
รูปแบบสัญลักษณ์ของคุณไม่จำเป็นต้องเหมือนกับของฉัน (ซึ่งมีข้อบกพร่องเล็กน้อย) เพียง แต่ต้องสอดคล้องกัน สิ่งนี้มีประโยชน์อย่างมากเมื่อทำการดีบั๊กเนื่องจากคุณสามารถเรียกใช้จนถึงจุดนั้นและเปรียบเทียบเทปจริงกับสิ่งที่คุณควรมีซึ่งสามารถชี้ให้เห็นข้อบกพร่องที่อาจเกิดขึ้นในโค้ดของคุณ
คำแนะนำหลักของฉันจะไม่
ตกลงคุณต้องการสิ่งที่มีประโยชน์มากกว่านั้น BF นั้นเป็นภาษาที่สั้นมาก แต่สิ่งที่ฆ่าคุณได้จริงคือเลขคณิตซึ่งจำเป็นต้องทำอย่างมีประสิทธิภาพ มันคุ้มค่าที่จะอ่านบนหน้าค่าคงที่ใน Esolang เพื่อเลือกวิธีการเขียนจำนวนมากอย่างมีประสิทธิภาพและเพื่อใช้ประโยชน์จากการห่อหากเป็นไปได้
การเข้าถึงหน่วยความจำยังมีราคาแพงมาก เนื่องจากคุณกำลังอ่านจากเทปคุณต้องจำไว้ว่าหัวของคุณเคลื่อนไหวในเวลาใดก็ตาม แตกต่างจากภาษาอื่น ๆ ที่คุณสามารถเพียงแค่เขียนa
, b
, c
ใน BF คุณจะต้องย้ายอย่างชัดเจนหัวจำนวนไบต์บางทางซ้ายหรือขวาเพื่อให้คุณจะต้องมีสติในการที่คุณเก็บสิ่งที่ ฉันค่อนข้างมั่นใจว่าการจัดระเบียบหน่วยความจำของคุณอย่างเหมาะสมที่สุดคือ NP-hard ดังนั้นขอให้โชคดีกับมัน
ในคำตอบนี้ฉันจะอ้างอิงเซลล์เฉพาะบนเทปหลายครั้ง ไม่สำคัญว่าจะเป็นเซลล์ใด แต่เป็นเซลล์เดียวกันตลอดทั้งคำตอบ สำหรับจุดประสงค์ของโพสต์นี้ฉันจะเรียกเซลล์นั้นว่า "ทอดด์"
เมื่อพยายามตั้งค่าเซลล์ให้มีค่าคงที่บางครั้งก็จ่ายให้ไม่จบทันที ตัวอย่างเช่นสมมติว่าคุณต้องการให้ทอดด์มี 30 ในภายหลังในรหัสของคุณ (ซึ่งอาจแก้ไขค่าของทอดด์ แต่ไม่เคยอ่าน) คุณกลับมาที่ทอดด์ หากค่าของทอดด์เป็น 0 โปรแกรมจะออก มิฉะนั้นคุณค่าของทอดด์จะถูกพิมพ์ตลอดไป
ตามที่หน้า esolangs.org ของค่าคงที่ brainfuck (ซึ่งอาจจะเป็นเรื่องของเคล็ดลับใน! ของตัวเอง) >+[--[<]>>+<-]>+
ทางที่สั้นที่สุดที่จะได้รับคือ ส่วนนำ>
นั้นอยู่ที่นั่นเพื่อให้แน่ใจว่าไม่มีการแก้ไขตัวชี้ทางซ้าย แต่ในกรณีนี้เราจะสมมติว่าเราไม่สนใจและวางลง เมื่อใช้รหัสนั้นรหัสของคุณจะมีลักษณะดังนี้:
+[--[<]>>+<-]>+(MISC. CODE)(GO TO TODD)[.]
คุณสามารถนึกถึงโค้ดก้อนแรกเช่นนี้:
(SET TODD TO 30)(MISC. CODE)(GO TO TODD)[.]
>+
แต่จำได้ว่าตัวละครสองตัวสุดท้ายในก้อนที่: เป็นเพียงการคิดวิธีนี้:
(SET TODD TO 29)(GO TO TODD)(ADD 1 TO TODD)(MISC. CODE)(GO TO TODD)[.]
ขอให้สังเกตว่าคุณ(GO TO TODD)
สองครั้ง! คุณสามารถเขียนโค้ดด้วยวิธีนี้แทน:
(SET TODD TO 29)(MISC. CODE)(GO TO TODD)(ADD 1 TO TODD)[.]
+[--[<]>>+<-](MISC. CODE)(GO TO TODD)+[.]
สมมติว่าจำนวนไบต์ที่ใช้(GO TO TODD)
ก่อนหน้านี้เท่ากันหนึ่งย้ายน้อย == หนึ่งไบต์น้อย! บางครั้งความจริงที่ว่าตำแหน่งเริ่มต้นของคุณเปลี่ยนไปอาจทำให้คุณได้รับประโยชน์ แต่ก็ไม่เสมอไป
ทิปเล็ก ๆ น้อย ๆ สำหรับความท้าทายที่ไม่มีอินพุต คุณสามารถใช้,
แทน[-]
หากคุณต้องการล้างเซลล์อย่างรวดเร็วเนื่องจากล่ามส่วนใหญ่ (รวมถึง TIO.run หนึ่ง) จะตั้งค่าเนื้อหาของเซลล์ให้เป็นตัวแทน EOF เป็นศูนย์ สิ่งนี้ทำให้โปรแกรมไม่สามารถพูดได้นิดหน่อย แต่ใครสนใจเรื่องนี้ในการเขียนโค้ด