เรติน่า 12 ไบต์
จำนวนไบต์ถือว่าการเข้ารหัส ISO 8859-1
+%`\B
¶$`:
1
ลองออนไลน์!
ทางเลือกอื่น ๆ :
+1`\B
:$`:
1
คำอธิบาย
นี่อาจจะง่ายกว่าที่จะอธิบายตามเวอร์ชั่นเก่าที่ไม่ค่อยตีกอล์ฟแล้วแสดงว่าฉันย่อให้สั้นลงได้อย่างไร ฉันเคยแปลงเลขฐานสองเป็นทศนิยมเช่นนี้
^
,
+`,(.)
$`$1,
1
วิธีเดียวที่สมเหตุสมผลในการสร้างตัวเลขทศนิยมใน Retina คือการนับสิ่งต่าง ๆ (เพราะ Retina มีคุณสมบัติสองอย่างที่ให้มันพิมพ์ตัวเลขทศนิยมแทนจำนวน) ดังนั้นวิธีที่เป็นไปได้เพียงอย่างเดียวคือการแปลงไบนารี่เป็นเอกและจากนั้นก็นับจำนวนหลักเอก บรรทัดสุดท้ายทำการนับดังนั้นสี่ตัวแรกจะแปลงเป็นไบนารี
เราจะทำอย่างนั้นได้อย่างไร? โดยทั่วไปการแปลงจากรายการของบิตเป็นจำนวนเต็มเราเริ่มต้นผลลัพธ์เป็น0
และจากนั้นไปถึงบิตจากที่สำคัญมากที่สุดไปถึงอย่างน้อยที่สุดเพิ่มค่าที่เรามีและเพิ่มบิตปัจจุบันเป็นสองเท่า เช่นถ้าเลขฐานสองเป็นจำนวน1011
จริงเราจะคำนวณ:
(((0 * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 1 = 11
^ ^ ^ ^
โดยที่ฉันทำเครื่องหมายบิตแต่ละรายการเพื่อความชัดเจน
กลอุบายในการทำสิ่งนี้โดยไม่รวมกันคือก) การเพิ่มเป็นสองเท่านั้นหมายถึงการทำซ้ำหมายเลขและ b) เนื่องจากเรานับจำนวน1
s ตอนท้ายเราไม่จำเป็นต้องแยกแยะระหว่าง0
s และ1
s ในกระบวนการ สิ่งนี้จะชัดเจนขึ้นในไม่กี่วินาที
สิ่งที่โปรแกรมทำคือการเพิ่มเครื่องหมายจุลภาคแรกไปยังจุดเริ่มต้นเป็นเครื่องหมายสำหรับจำนวนการป้อนข้อมูลที่เราประมวลผลแล้ว:
^
,
ด้านซ้ายของตัวทำเครื่องหมายเราจะมีค่าที่เรากำลังสะสม (ซึ่งถูกเริ่มต้นอย่างถูกต้องกับการเป็นตัวแทนของศูนย์ unary) และด้านขวาของค่าจะเป็นบิตถัดไปในการประมวลผล ตอนนี้เราใช้การทดแทนต่อไปนี้ในลูป:
,(.)
$`$1,
เพียงแค่ดู,(.)
และ$1,
สิ่งนี้จะย้ายเครื่องหมายหนึ่งบิตไปทางขวาในแต่ละครั้ง แต่เราก็แทรก$`
ซึ่งก็คือทุกสิ่งที่อยู่ข้างหน้าของเครื่องหมายเช่นค่าปัจจุบันซึ่งเราเพิ่มเป็นสองเท่า นี่คือขั้นตอนแต่ละขั้นตอนในการประมวลผลอินพุต1011
โดยที่ฉันได้ทำเครื่องหมายผลลัพธ์ของการแทรก$`
ด้านบนแต่ละบรรทัด (ว่างเปล่าสำหรับขั้นตอนแรก):
,1011
1,011
_
110,11
___
1101101,1
_______
110110111011011,
คุณจะเห็นว่าเราได้รักษาไว้และเพิ่มศูนย์เป็นสองเท่าพร้อมกับทุกอย่างอื่น แต่เนื่องจากเราไม่สนใจพวกเขาในตอนท้ายมันไม่สำคัญว่าเราจะเพิ่มพวกเขาเป็นสองเท่าตราบใดที่จำนวน1
s เป็น แก้ไข. หากคุณนับพวกเขามี11
พวกเขาเพียงแค่สิ่งที่เราต้องการ
นั่นทำให้คำถามเกี่ยวกับวิธีตีกอล์ฟนี้ลงถึง 12 ไบต์ ส่วนที่แพงที่สุดของรุ่น 18 ไบต์ต้องใช้เครื่องหมาย เป้าหมายคือการกำจัดสิ่งนั้น เราต้องการเพิ่มส่วนนำหน้าของทุก ๆ สองบิตดังนั้นความคิดแรกอาจเป็นเช่นนี้:
.
$`$&
ปัญหาคือการแทนที่เหล่านี้เกิดขึ้นพร้อมกันดังนั้นบิตแรกจะไม่เพิ่มเป็นสองเท่าสำหรับแต่ละบิต แต่จะได้รับการคัดลอกหนึ่งครั้งในแต่ละครั้ง สำหรับการป้อนข้อมูล1011
เราจะได้รับ (ทำเครื่องหมายการแทรก$`
):
_ __ ___
1101011011
เรายังคงต้องดำเนินการอินพุตซ้ำเพื่อให้คำนำหน้าแรกสองเท่าเป็นสองเท่าอีกครั้งโดยที่สองและอื่น ๆ แนวคิดหนึ่งคือการแทรกเครื่องหมายทุกที่และแทนที่ด้วยคำนำหน้าซ้ำ ๆ :
\B
,
+%`,
¶$`
หลังจากแทนที่เครื่องหมายแต่ละตัวด้วยคำนำหน้าเป็นครั้งแรกเราจำเป็นต้องจำตำแหน่งที่จุดเริ่มต้นของอินพุตดังนั้นเราจึงแทรก linefeeds ด้วยและใช้%
ตัวเลือกเพื่อให้แน่ใจว่าสิ่งต่อไปนี้$`
จะเลือกเฉพาะตัวป้อนข้อมูลที่ใกล้เคียงที่สุดเท่านั้น
วิธีนี้ใช้งานได้ แต่ก็ยังยาวเกินไป (16 ไบต์เมื่อนับ1
s ตอนท้าย) แล้วเราจะเปลี่ยนสิ่งต่าง ๆ สถานที่ที่เราต้องการแทรกเครื่องหมายถูกระบุด้วย\B
(ตำแหน่งระหว่างตัวเลขสองหลัก) ทำไมเราไม่ใส่คำนำหน้าเข้าไปในตำแหน่งเหล่านั้น? เกือบจะใช้งานได้ แต่ความแตกต่างคือในโซลูชันก่อนหน้านี้เราลบเครื่องหมายเดียวในแต่ละการแทนที่และที่สำคัญคือการทำให้กระบวนการยุติลง อย่างไรก็ตาม\B
ตัวละครไม่ได้เป็นเพียงแค่ตำแหน่งดังนั้นไม่มีอะไรจะถูกลบออก อย่างไรก็ตามเราสามารถหยุด\B
จากการจับคู่โดยแทนที่จะใส่อักขระที่ไม่ใช่ตัวเลขลงในสถานที่นี้ ที่เปลี่ยนขอบเขตที่ไม่ใช่คำไปเป็นขอบเขตของคำซึ่งเทียบเท่ากับการลบอักขระเครื่องหมายก่อนหน้านี้ และนั่นคือสิ่งที่โซลูชันขนาด 12 ไบต์ทำ:
+%`\B
¶$`:
เพื่อความสมบูรณ์นี่คือแต่ละขั้นตอนของการประมวลผล1011
โดยมีบรรทัดว่างหลังจากแต่ละขั้นตอน:
1
1:0
10:1
101:1
1
1:0
1
1:0:1
1
1:0
10:1:1
1
1:0
1
1:0:1
1
1:0
1
1:0:1:1
อีกครั้งคุณจะพบว่าผลลัพธ์สุดท้ายมีทั้งหมด 11 1
วินาที
ในแบบฝึกหัดสำหรับผู้อ่านคุณจะเห็นได้อย่างไรว่าลักษณะนี้ทำให้ฐานอื่น ๆ ค่อนข้างง่าย (สำหรับสองสามไบต์ต่อการเพิ่มขึ้นที่ฐาน)