BrainF ** k, 396 391 ไบต์
>+>>++++[-<++++++++>]->,----------[++++++++++.>>++++++++[-<++++<------>>]<.,----------]-<+[-<+]->>+[-<<<<<++++++++++.[-]>[-<+>>.<]<[->+<]>+>>>[[->+]->>+<<<+[-<+]->]>+[-<->[[->+]->+>>+<<<<+[-<+]->]<+>->+[->+]->>[->+<]>+>++++++++++>>-<<[-<-[>>]<]<->>>+[-<<<+>>>[-<->]<+++++++++>>>+]++++++++[-<++++<++++++>>]<<<[-<<<<+[-<+]-<+>>+[->+]->>>>+<]>.>.[-]<[-]<<<[->+<]<<+[-<+]>+]>>[-]<<<-<+[-<+]->>+]
ฉันไม่สามารถต้านทานสิ่งล่อใจที่จะทำสิ่งนี้ อย่างน้อยรูปสามเหลี่ยมนั้นคือด้านที่แหลมลง
อินพุตเข้ามาเป็นสตริงของอักขระตัวเลขตามด้วยบรรทัดใหม่หนึ่งบรรทัด
เอาต์พุตจะมีช่องว่างต่อท้ายหนึ่งช่องในทุกบรรทัด
ตัวอย่าง:
$ bf sd.bf
010
0 1 0
1 1
2
$ bf sd.bf
123456
1 2 3 4 5 6
3 5 7 9 1
8 2 6 0
0 8 6
8 4
2
$ bf sd.bf
9245322
9 2 4 5 3 2 2
1 6 9 8 5 4
7 5 7 3 9
2 2 0 2
4 2 2
6 4
0
คำอธิบาย
เนื่องจากมันค่อนข้างยากที่จะอธิบายโค้ดจากมุมมองของการทำงานเราจึงสามารถดูได้จากมุมมองของสถานะของเทปในหลาย ๆ ครั้ง แนวคิดหลักที่นี่คือสามเหลี่ยมที่เราส่งออกนั้นเริ่มต้นเป็นอาร์เรย์ที่บรรจุแน่น (สำหรับ BF แล้ว) ที่หดขนาดโดย 1 ทุกการวนซ้ำของลูป ความคิดที่สำคัญอีกประการหนึ่งคือเราใช้255เพื่อระบุ "ตัวยึด" ที่เราสามารถค้นหาบนเทป
การเริ่มต้น
นี่เป็นขั้นตอนที่ง่ายที่สุด เมื่อเริ่มต้นโปรแกรมเราจะดำเนินการดังต่อไปนี้:
>+>>++++[-<++++++++>]->
สิ่งนี้บังคับให้เทปอยู่ในสถานะต่อไปนี้ (โดยที่>N<ระบุตำแหน่งของตัวชี้บนเทป)
[ 0 1 32 255 >0< 0 0 ...]
หมายเลขแรกที่นี่คือตำแหน่ง "บัฟเฟอร์" เราจะไม่ใช้มันในระยะยาว แต่มันมีประโยชน์ที่จะทำให้การดำเนินงานเล็ก ๆ น้อย ๆ ง่ายขึ้นและสำหรับการคัดลอกข้อมูล
ตัวเลขที่สองคือจำนวนของช่องว่างที่เราจะ outputting ในช่วงเริ่มต้นของแต่ละบรรทัดที่เริ่มต้นหลังจากบรรทัดแรก บรรทัดแรกจะไม่มีช่องว่างนำหน้า
หมายเลขที่สามคืออักขระช่องว่างที่เราส่งออก
ตัวเลขที่สี่คือตัวยึด 255 เพื่อให้เราสามารถกลับมาที่ตำแหน่งนี้ได้อย่างง่ายดาย
อินพุต
จากตำแหน่งนี้เราจะอ่านตัวละครทุกตัว ในตอนท้ายของขั้นตอนนี้เราหวังว่าจะอยู่ในสถานการณ์ต่อไปนี้:
[ 0 1 32 255 a b c d e f ... >255< 0 0 ... ]
โดยที่a b c d e f ...ระบุสตริงของอักขระตัวเลขที่เป็นอินพุต (ไม่ใช่บรรทัดใหม่)
เราทำสิ่งนี้สำเร็จด้วยสิ่งต่อไปนี้:
,----------[++++++++++.>>++++++++[-<++++<------>>]<.,----------]-
มีความแตกต่างเล็กน้อยในเรื่องนี้ ก่อนอื่นเราจะเอาท์พุทตัวละครแต่ละตัวเมื่อเราได้พวกมันออกมาแล้วเว้นวรรคหลังจากนั้น ประการที่สองเราไม่ต้องการคัดลอกค่า ASCII ไปยังเทปเราต้องการคัดลอกตัวเลขที่แท้จริง ประการที่สามเราต้องการหยุดเมื่อเราตีขึ้นบรรทัดใหม่และปล่อยให้ตัวเองอยู่ในสถานที่ที่ดีในเวลานั้น บอกว่าการป้อนข้อมูลของเราคือ
6723จากนั้นเมื่ออ่านครั้งแรก6เทปของเราจะเป็นดังนี้:
[ 0 1 32 255 >54< 0 0 ...]
เราตรวจสอบว่าค่านี้ไม่เท่ากับ10(คำขึ้นบรรทัดใหม่ ASCII) ,----------[++++++++++ด้วย จากนั้นเราพิมพ์ค่าออกมาและดำเนินการต่อโดยการลบ 48 จากค่าอินพุตและเพิ่ม 32 ไปยังค่าถัดจาก (พร้อมกัน>>++++++++[-<++++<------>>]<) ทิ้งเราไว้ที่นี่:
[ 0 1 32 255 6 >32< 0 ...]
แจ้งให้ทราบว่าตลอดกระบวนการนี้เราสามารถสรุปได้ว่าตัวเลขทั้งหมดทางด้านขวาของการป้อนข้อมูลของเรามี 0 - ที่นี้หมายถึงว่าเราไม่ได้อยู่ในอันตรายจากการทำลายของรัฐก่อนหน้านี้ถ้าเราใช้ค่าไปทางขวาเพื่อคำนวณและ6 * 8
ตอนนี้เราแสดงอักขระอวกาศที่เราเพิ่งสร้างขึ้นและรับข้อมูลใหม่ลบพื้นที่ที่เราคำนวณไป ในที่สุดอินพุตจะถูกยกเลิกโดยบรรทัดใหม่และลูปจะออกจากไปโดยที่บรรทัดใหม่จะเป็น ( ) นี่คือตัวยึดตำแหน่งที่สองที่เราจะใช้นำทางเทป ณ จุดนี้ในสถานการณ์ของเราเทปของเราตรงนี้:4 * 8
255,----------]-
[ 0 1 32 255 6 7 2 3 >255< 0 0 ... ]
การคำนวณ
วิธีการทำงานนี้คือรายการของตัวเลขระหว่าง255ตัวยึดตำแหน่งของเราจะลดลงหนึ่งรอบทุกรอบของการวนซ้ำ เมื่อมันเหลือเพียง 1 หลักเราก็เสร็จแล้วและควรจะหยุดทันที (โปรดทราบว่า ณ จุดนี้ทุกหลักในรายการนั้นได้รับการส่งออกแล้วดังนั้นเราไม่ต้องกังวลเกี่ยวกับการแสดงผลอีกครั้ง)
ขณะนี้เราใช้เคล็ดลับนี้เพื่อนำทางไปยังคนแรกที่ยึด:255 <+[-<+]-วิธีนี้จะทำการค้นหาเทปทางด้านซ้ายเพื่อหา a 255โดยไม่ต้องเปลี่ยนอะไร ตอนนี้เราได้ย้ายตัวชี้เราสามารถตรวจสอบสภาพทางออกของเรา: 255ถ้ามีเพียงหนึ่งหลักในรายการแล้วเซลล์สองช่องว่างด้านขวาจะถือ ดังนั้นเราตรวจสอบกับสิ่งนั้นและเริ่มวนซ้ำ:>>+[-<<
ขั้นตอนแรกในการวนซ้ำของเราคือการแสดงบรรทัดใหม่ ดังนั้นเราย้ายไปที่เซลล์แรก (เซลล์บัฟเฟอร์ของเรา) เพิ่ม 10 เข้าไปและส่งออก ขั้นตอนต่อไปคือการแสดงผลอักขระช่องว่างทั้งหมด หลังจากเอาท์พุทพวกเราเพิ่มจำนวนของเราสำหรับจำนวนของช่องว่างนำ ขั้นตอนเหล่านี้สามารถทำได้โดยทำดังต่อไปนี้:
-<<<<<++++++++++.[-]>[-<+>>.<]<[->+<]>+>>>
ซึ่งทำให้เราอยู่ในสถานะนี้:
[ 0 2 32 255 >6< 7 2 3 255 0 0 0 0 0 0 ]
ขั้นตอนต่อไปของเราคือการคัดลอกค่าแรกในรายการผ่านตัวยึดตำแหน่งที่สอง255:
[[->+]->>+<<<+[-<+]->]
เราทำสิ่งนี้โดยการกระโดดไปมาระหว่างตัวยึดตำแหน่งของเรา255และปล่อยให้เราอยู่ที่นี่:
[ 0 2 32 255 >0< 7 2 3 255 0 6 0 0 ... ]
ตอนนี้เราเริ่มวนซ้ำวนซ้ำส่วนที่เหลือของรายการหยุดเมื่อเรากด255:>+[-<
ณ จุดนี้ตัวเลขทางด้านซ้ายมือของเราอยู่เสมอ 0 ดังนั้นเนื่องจากเรารักพวกเขาเราจึงมีตัวยึดตำแหน่ง255ในนั้นเพื่อให้เราสามารถกลับมาที่สถานที่ของเราในรายการ 255ขั้นตอนต่อไปคือการย้ายสถานที่ที่สองในรายการไปยังสถานที่โดยรอบที่เราย้ายสถานที่แรกที่ผ่านมายึดตำแหน่งที่สอง ขั้นตอนเหล่านี้สามารถทำได้โดยทำดังต่อไปนี้:
->
[[->+]->+>>+<<<<+[-<+]->]
ออกจากเราที่นี่: [ 0 2 32 255 255 >0< 2 3 255 7 6 7 0 ]
ตอนนี้ทั้งสอง6และ7ถูกย้ายไปยังสถานที่ที่การคำนวณสามารถเกิดขึ้นได้ เราต้องการสำเนาสองชุด7เพราะหมายเลขถัดไปในรายการจะต้องใช้เช่นกัน 7ทันทีหลังจากที่255มีจุดมุ่งหมายนี้ในขณะที่คนอื่น ๆ7จะได้รับการบริโภคโดยการคำนวณ
อันดับแรกเราเพิ่มตัวเลขสองหลัก:
<+>->+[->+]->>
[->+<]>
ออกจากเราที่นี่:
[ 0 2 32 255 0 255 2 3 255 7 0 >13< 0 ]
การรวมกันของขั้นตอนต่อไปนั้นซับซ้อนที่สุด เราจำเป็นต้องดูว่าตัวเลขที่เรากำลังชี้ไปที่มีขนาดใหญ่กว่า 10 10และถ้ามันเป็นเราลบ ในความเป็นจริงสิ่งที่เราทำคือเราลบ 10 จากมันและดูว่ามันกระทบ0ที่จุดใด ๆ ในการลบหรือไม่ ถ้าเป็นเช่นนั้นเราจะเพิ่ม10ในภายหลัง ในตอนท้ายของเรื่องนี้เราควรจะมีผลรวมโมดูโล 10
Prepare a 10 to the right
+>++++++++++
Leave yet another 255 for a loop condition later
>>-<<
If the number is greater than 10 end up one space to the left
else one space to the right
[-<-[>>]<]<->
Check if the previous 255 is two spaces to the right and if it is
add 10 back to our sum--we've subtracted too much
>>+[-<<<+>>>[-<->]<+++++++++>>>+]
เมื่อมาถึงจุดนี้เราได้บรรลุเป้าหมาย เรามีโมดูโล่รวม 10! นอกจากนี้ไม่ว่าจำนวนจะมากกว่า 10 เราจะสิ้นสุดที่นี่:
[ 0 2 32 255 0 255 2 3 255 7 0 3 0 0 >0< ]
เป้าหมายต่อไปของเราคือการแสดงผลรวมใหม่นี้ตามด้วยช่องว่างแล้วอัดกลับเข้าไปในรายการของเรา เราทำสิ่งนี้ด้วยเทคนิคก่อนหน้าของเราในการ255กระโดดและเพิ่ม48เข้าไปในผลรวมของเราดังนั้นฉันจะไม่ครอบคลุมในรายละเอียด
++++++++[-<++++<++++++>>]
<<<[-<<<<+[-<+]-<+>>+[->+]->>>>+<]
>.>.
และเราอยู่ที่นี่: [ 0 2 32 255 3 255 2 3 255 7 0 0 51 >32< ]
สังเกตว่าเราใส่255ตัวยึดตำแหน่งเพิ่มเติมหลังจากที่ถูกแทรกใหม่3เพื่อไม่ให้สูญเสียตำแหน่งในรายการ ณ จุดนี้เรามีผลรวมของเราและพื้นที่ของมันดังนั้นเราจึงจำเป็นต้องทำความสะอาดและเปลี่ยนกลับสู่สถานะที่การวนซ้ำครั้งถัดไปของลูปนี้จะทำงาน เราจำเป็นต้องล้างออก51และ32เซลล์ของเราย้าย7ครั้งเดียวไปทางขวาและนำทางไปยังตัวยึดตำแหน่งรายการของเราเพื่อให้เราสามารถเริ่มต้นใหม่
[-]<[-]<<<[->+<]<<+[-<+]
ตอนนี้เราอยู่ที่นี่: [ 0 2 32 255 3 >0< 2 3 255 0 7 0 ... ]
ซึ่งเป็นสิ่งที่เราต้องการสำหรับการทำซ้ำต่อไปของเรา ดังนั้นตรวจสอบ 255 และไป! ( >+])
เมื่อเราหลุดออกจากวงเราจะมีรายการใหม่ทั้งหมด - ประกอบด้วยจำนวนเงินจากรายการก่อนหน้า ครั้งแรกมันจะเป็นดังนี้:
[ 0 2 32 255 3 9 5 0 >0< ]
ตอนนี้เราต้องการทำซ้ำกระบวนการทั้งหมดในรายการใหม่ของเราดังนั้นเราจึง255ลงไปทางซ้ายและเริ่มใหม่! เราต้องทำความสะอาดนิดหน่อย>>[-]<<แล้วก็วางตัวแทนของเราลง<-ไป หลังจากนั้นเราก็อยู่ในสถานที่เดียวกันกับที่เราป้อนข้อมูลดังนั้นเราสามารถออกไปทำเช็คเดียวกัน: <+[-<+]->>+และบูม! เราได้วนเต็มแล้ว! ]ทั้งหมดที่เราต้องการคือวงเล็บปิดและเมื่อมันจบแล้วเราได้ทุกอย่างที่ออกเพื่อให้เราดำเนินการเสร็จแล้ว: