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
ลงไปทางซ้ายและเริ่มใหม่! เราต้องทำความสะอาดนิดหน่อย>>[-]<<
แล้วก็วางตัวแทนของเราลง<-
ไป หลังจากนั้นเราก็อยู่ในสถานที่เดียวกันกับที่เราป้อนข้อมูลดังนั้นเราสามารถออกไปทำเช็คเดียวกัน: <+[-<+]->>+
และบูม! เราได้วนเต็มแล้ว! ]
ทั้งหมดที่เราต้องการคือวงเล็บปิดและเมื่อมันจบแล้วเราได้ทุกอย่างที่ออกเพื่อให้เราดำเนินการเสร็จแล้ว: