Rebmu : 79 ตัวอักษรหรือ (37 + ความยาว (p1) + 2 * สูงสุด (ความยาว (p2), ความยาว (p3)))
ก่อนอื่นฉันจะให้คำตอบ 79 ตัวอักษรที่ถามว่าคุณต้องเรียนภาษาอะไร (เอนโทรปี 4.0, 30 ตัวอักษรไม่รวม?
) และเสนอคำแนะนำของRebol และ [Red] ให้คุณ :
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} pp{{[RReebdo]l}}
กลยุทธ์พิเศษที่มีให้ที่นี่ที่ไม่ได้อยู่ในภาษาอื่นมาจากการใช้ประโยชน์จากความจริงที่ว่าเครื่องหมายวงเล็บปีกกาเป็นตัวคั่นสตริงแบบอสมมาตรซึ่งสามารถซ้อนกันได้อย่างถูกกฎหมาย:
my-string: {"It's cool," said {Dr. Rebmu}, "for MANY reasons--like less escaping."}
ที่ให้ฉันสร้างทางออกทั่วไปที่สามารถทำงานได้อย่างง่ายดายในโปรแกรมใด ๆ ที่ไม่ได้ใช้ลำดับหนี เวอร์ชันตัวละคร 79 นั้นง่ายพอที่จะใช้ทางลัด แต่การมีแหล่งโปรแกรมโดยพลการสำหรับโปรแกรม p2 และ p3 อย่างถูกต้องคุณต้องมีเทมเพลตเต็มรูปแบบ ถ้าเราใช้มันก็จะเป็น 87 ตัวอักษร:
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} ddoo{{pp{{[RReebdo]l}}}}
รูปแบบสำหรับการใช้รูปแบบทั่วไปนี้คือถ้าคุณมีข้อความแหล่งที่มาสามตัวของอักขระเรียงตามลำดับความยาวตัวแปร (ลองใช้ตัวอย่างเช่น AAA
, BBBBB
, CCCCCCC
) คุณสามารถเข้ารหัสพวกเขาเป็นสิ่งที่ตามสายของ:
DD 11 DD :do dd {dd {AAAqt}} ddoo{{BCBCBCBCBC C C}}
(หมายเหตุ: แม้ว่ารูปแบบนี้จะใช้งานไม่ได้หากไม่ได้ปรับแต่งโปรแกรมที่ใช้อักขระเลี่ยง แต่นี่ไม่ใช่ข้อบกพร่องที่ร้ายแรงการได้รับวงเล็บปีกกาซ้ายที่ไม่ตรงกันในสตริงที่คั่นด้วยวงเล็บปีกกาต้องการบางสิ่งเช่น{Foo ^{ Bar}
... แต่คุณสามารถเขียนใหม่ได้ง่าย สัญกรณ์สตริงทางเลือก"Foo { Bar"
และกรณีรวมสามารถจัดการได้ด้วยการติดกาวส่วนผสมของสตริงที่ไม่ใช้ค่า Escape)
ดังนั้น ... แล้วตัวอย่างล่ะ เมื่อแบบฟอร์มทั่วไปพร้อมใช้งานโปรแกรมตัวอักษร 573 นี้ประกอบขึ้นในเวลาเพียงไม่กี่นาทีจาก 3 โซลูชั่นกอล์ฟรหัสก่อนหน้า:
DD 11 DD: ทำ dd {dd {rJ N 0% rN Wa1m2j S {\ x /} D00 Hc & [u [Ze? Wa Qs ~ rpKw [isEL00c [skQd2k] [eQ? kQ [tlQ]] pcSeg - b00 [ eZ 1 5] 3] prRJ [si ~ dSPscSqFHs] eZ 1 [s + dCa + wM2cNO]]] Va | [mpAp2j] prSI ~ w { } Ls2w Wl h01tiVsb01n -1 chRVs { } [sn [{N sbeo [tIt0l1eV} 0e5gXN1 01L {5s0} C {1} 0 {0 Do5f0 0bMe1e0r0} 0]]] tMw9C9 Numz Jl [paN + [KperlCJBn [ba sWS {b}] {K, j} b P { } lf EZ - - n [N m {G อื่น ๆ อีกมาก}} {{akeonedownandpassitar ound} c B w P lf]]}}
หากใครต้องการลองเขียนโปรแกรมในภาษาที่พวกเขาเลือกและคิดว่าพวกเขาสามารถเอาชนะ 573 ได้โปรดแจ้งให้เราทราบ ฉันจะทำให้คุณมีชื่อเสียงอย่างมากถ้าคุณทำ - สมมติว่าภาษาที่คุณเลือกไม่ใช่ Rebmu เพราะฉันรู้ว่าโปรแกรมเหล่านั้นไม่ได้น้อยที่สุด :-)
ระยะห่างที่ "สิ้นเปลือง" ที่คุณได้รับในตอนท้ายคือสิ่งที่เกิดขึ้นเมื่อ p2 และ p3 มีความยาวไม่สมดุล แต่ทั้ง 3 โปรแกรมมีขนาดแตกต่างกันในกรณีนี้ดังนั้นจึงไม่มีการจับคู่ที่ดีพอที่จะเลือกสำหรับ p2 / p3 (ฉันเลือกสิ่งเหล่านี้เพราะไม่มีข้อมูลภายนอกเป็นอินพุตเช่นเขาวงกตหรืออะไรก็ตามไม่ใช่ว่าพวกเขามีความยาวเท่ากันในขณะที่ฉันสามารถเขียนโปรแกรมใหม่ที่เหมาะสมที่สุดได้ฉันใช้เวลามากพอและประเด็นก็คือ คุณทำไม่ได้ต้องเขียนโปรแกรมใหม่ ... )
มันทำงานอย่างไร
(หมายเหตุ: ฉันเริ่มต้นด้วยวิธี "สร้างสรรค์" มากกว่าที่ไม่คล่องตัว แต่ดูน่าสนใจกว่าฉันย้ายมันไปยังรายการในบล็อกของฉันตามที่อธิบายถึงวิธีการนี้ยาวเกินไป)
กุญแจสำคัญในที่นี้คือเล่ห์เหลี่ยม "รหัส eval เป็นสายอักขระ" เช่นเดียวกับรายการอื่น ๆ เพียงแค่มีทรัมการ์ดของตัวคั่นสตริงแบบอสมมาตร ฉันจะเริ่มต้นด้วยการอธิบายการทำงานของตัวละคร 80 ตัว
นี่คือโปรแกรม "ทั้ง" ปรับช่องว่างสำหรับการอ่านของกรณีนี้:
DD 11 ; assign 11 to dd (about to overwrite again)
DD :do ; make dd a synonym for DO (a.k.a. "eval")
; eval a string as source code that ends with QUIT (QT)
dd {dd {p{Which languages must you learn?}qt}}
; we'll never get here, but whatever's here must be legally parseable
pp{{[RReebdo]l}}
ที่นี่เราไขการตั้งค่า DD เป็นคำพ้องสำหรับ DO (aka "eval") แต่เคล็ดลับคือเมื่อโปรแกรมลดลงครึ่งหนึ่งพวกเขาปิดท้ายการเรียกใช้โค้ดที่มีผลเพียงอย่างเดียวคือการกำหนด D ให้กับตัวอักษรที่ไม่เป็นอันตราย 1
นี่คือสิ่งที่รหัสตัวอักษรคี่ทำให้ช่องว่างปรับอีกครั้ง:
D 1 ; assign 1 to d
D d ; assign d to itself, so it's still 1
d ; evaluates to integer, no side effect
{d pWihlnugsms o er?q} ; string literal, no side effect
p {Rebol} ; print "Rebol"
และนี่คือรหัสตัวอักษร:
D 1 ; assign 1 to d
D:od ; URL-literal (foo:...), no side effect
d ; evaluates to integer, no side effect
{{hc agae utyulan}t} ; string literal (well-formed!), no side effect
p {[Red]} ; print "[Red]"
เป็นจริงในกรณีที่โปรแกรมที่ไม่ได้ลดลงครึ่งหนึ่งdd {dd {(arbitrary code)qt}}
จะรันโค้ดอะไรก็ตามที่คุณต้องการ อย่างไรก็ตามมีการเรียกสองสายเพื่อประเมินแทนการโทรเพียงครั้งเดียว นั่นเป็นเพราะในขณะที่วงเล็บปีกกาซ้อนกันทำงานได้ดีในโค้ด interleaved พวกมันทำพฤติกรรมที่ไม่ดีของ DO เพราะ:
do {{print "Hello"}}
จะโหลดสตริงเป็นโปรแกรม {print "Hello"}
แต่ลมโปรแกรมที่ขึ้นเป็นเพียงค่าคงที่สตริง ดังนั้นเคล็ดลับที่ฉันใช้ที่นี่คือการใช้ DD ของฉัน (ถือค่าฟังก์ชั่นเดียวกับ DO) และเรียกใช้มันสองครั้ง Halvers เคี้ยวที่ส่วนต่าง ๆ ของสาย แต่พวกเขาไม่ได้เคี้ยวทั้งคู่ถ้าคู่ / คู่นั้นถูกต้องสำหรับเนื้อหาและเนื่องจากสิ่งที่เหลืออยู่นอกสายหลังจากหยุดครึ่งเป็นเพียงค่าคงที่หนึ่งd
ไม่เป็นอันตราย
ด้วยรูปแบบนี้ไม่มีความท้าทายในการเขียนพฤติกรรมของโปรแกรมเมื่อมันไม่ลดครึ่ง - คุณสามารถใส่อะไรก็ได้ตราบใดที่ความยาวของอักขระของโค้ดนั้นเป็นเท่ากัน (แปลกถ้าคุณนับ QT ซึ่งเป็น QUIT) หากคุณต้องการที่จะได้รับแม้กระทั่งจากจำนวนคี่หนึ่งโยนในพื้นที่(เพื่อให้มีจริงเป็น 1 ในสูตรของฉันข้างต้นใน p1 สำหรับความยาวโปรแกรมคี่ของ p1) เคล็ดลับดูเหมือนว่าจะเขียนโค้ด interleaved หลังจากนั้นซึ่งจะต้องผ่านการแยกวิเคราะห์ถ้ามันไม่ได้ลดลงครึ่งหนึ่ง (มันจะไม่ทำงานเพราะ QT แต่ต้องโหลดได้ก่อนที่จะถูกเรียกใช้)
กรณีนี้เป็นเรื่องเล็กน้อย pp
โหลดได้ดีเป็นสัญลักษณ์แม้ว่าจะไม่ได้กำหนดและจะแบ่งออกเป็นp
สำหรับการพิมพ์ในแต่ละโปรแกรมครึ่ง แต่เราสามารถทำเคล็ดลับอื่นได้โดยใช้สตริงตัวอักษรอีกครั้ง โปรแกรมที่ลดลงครึ่งหนึ่งยังคงมีการกำหนดค่า DO ตามปกติดังนั้นเราจึงอาจกล่าวได้ว่า:
ddoo{{pp{{[RReebdo]l}}}}
โดยมีส่วนเดียวที่ parser หยิบขึ้นมาในกรณีทั้งหมดเป็นคำที่เป็นสัญลักษณ์ ddoo
เป็นและตัวอักษรสตริงเราสามารถแทรกโปรแกรมสองโปรแกรมใด ๆ ที่เราต้องการภายในสตริงตัวอักษรนั้นและไม่โกรธ parser รุ่นลดลงครึ่งหนึ่งจะพูดว่า:
do{p{Rebol}}
..และ...
do{p{[Red]}}
อย่างที่ฉันพูดส่วนนี้ดูคุ้นเคยกับโซลูชันอื่น ๆ ที่ปฏิบัติต่อโปรแกรมเป็นสตริงและประเมินพวกเขา แต่ในกรณีของการแข่งขันเมื่อโปรแกรมที่คุณบรรจุมีสตริงที่ซ้อนอยู่ นี่คือสิ่งเดียวที่จะทำให้คุณมีปัญหาคือการใช้การหลบหนีผ่าน carets (^
) ... ซึ่งสามารถได้ง่าย
(หมายเหตุ 'โกง' เล็กน้อย: ฉันเพิ่ม QT สำหรับ "QUIT" เพื่อตอบสนองต่อปัญหานี้จริง ๆ แล้วฉันได้ลบตัวย่อสำหรับการเลิกก่อนหน้านี้อย่างเด็ดเดี่ยวเนื่องจาก ... ฉันคิดว่ามันดีสำหรับการใช้คอนโซลเท่านั้น ช่องว่างสองตัวอักษรถ้ามันไม่ได้อยู่ใน REPL ฉันกำลังเพิ่มเพราะฉันเห็นว่าฉันคิดผิดไม่ได้เพิ่มมันสำหรับกรณีนี้โดยเฉพาะอย่างไรก็ตามก่อนที่จะมีการเปลี่ยนแปลงมันจะมีความยาว 2 ตัวอักษรอีกด้วย เมื่อฉันโพสต์โซลูชันเป็นครั้งแรกมีข้อผิดพลาดใน Rebmu ที่ป้องกันไม่ให้ทำงานได้แม้ว่ามันควรจะมี ... ตอนนี้มันใช้งานได้)
x0=00;;
ไกลฉันจะได้รับเป็นสิ่งที่ต้องการ ท้าทายมาก!