Rebmu : 79 karakter ATAU (37 + panjang (p1) + 2 * maks (panjang (p2), panjang (p3)))
Pertama saya akan memberikan solusi 79 karakter yang menanyakan Bahasa mana yang harus Anda pelajari? (entropi 4.0, 30 huruf tidak termasuk ?
) dan menawarkan Anda saran Rebol dan [Merah] :
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} pp{{[RReebdo]l}}
Taktik unik yang tersedia di sini yang tidak dalam bahasa lain berasal dari mengambil keuntungan dari fakta bahwa kurung kurawal adalah pembatas string asimetris, yang dapat bersarang secara legal:
my-string: {"It's cool," said {Dr. Rebmu}, "for MANY reasons--like less escaping."}
Itu membuat saya menghasilkan solusi umum, yang dapat bekerja dengan mudah pada program apa pun yang tidak menggunakan urutan pelarian. Versi 79 karakter cukup sederhana untuk pintasan, tetapi untuk memuat sumber program yang sewenang-wenang untuk program p2 dan p3 Anda memerlukan templat lengkap. Seandainya kami menggunakan itu, itu akan menjadi 87 karakter:
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} ddoo{{pp{{[RReebdo]l}}}}
Pola untuk menggunakan bentuk umum ini adalah bahwa jika Anda memiliki tiga teks sumber karakter berurutan dari panjang variabel (mari kita gunakan contoh seperti AAA
, BBBBB
, CCCCCCC
) Anda bisa mengkodekan mereka sebagai sesuatu di sepanjang baris:
DD 11 DD :do dd {dd {AAAqt}} ddoo{{BCBCBCBCBC C C}}
(Catatan: Meskipun pola ini tidak akan berfungsi tanpa mengubah program yang menggunakan karakter escape, ini bukan cacat fatal. Mendapatkan kurung kurawal yang tidak tertandingi dalam string yang dibatasi oleh kurung memerlukan sesuatu seperti {Foo ^{ Bar}
... tetapi Anda dapat dengan mudah menulis ulang menggunakan notasi string alternatif "Foo { Bar"
, dan case kombinasi dapat dikelola dengan menempelkan campuran string yang tidak terhapus.)
Jadi ... bagaimana dengan contoh? Setelah formulir umum tersedia, program karakter 573 ini dikumpulkan hanya dalam beberapa menit dari 3 solusi golf kode sebelumnya:
DD 11 DD: lakukan dd {dd {rJ N 0% rN Wa1m2j S {\ x /} D00 Hc & [u [Ze? Wa Qs ~ rpKw [isEL00c [skQd2k] [eEV? 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 { } hLceVn01qt} fd {hr {hr} [sn [{N sbeo [tIt0l1eV} 0e5gXN1 01L {5s0} C {1} 0 {0 Do5f0 0bMe1e0r0} 0]]] tMw9C9 Numz Jl [paN + [KperlCJBn [[ba sWS {B noJn] tt] {K, j} b P {. } Jika EZ - - n [N m {G otothestoreandbuysome more}] {T akeonedownandpassitar ound} c B w P lf]]}}
Jika ada yang ingin mencoba menulis program itu dalam bahasa pilihan mereka, dan berpikir mereka bisa mengalahkan 573, beri tahu saya. Saya akan memberi Anda reputasi besar jika Anda melakukannya - dengan asumsi bahasa pilihan Anda bukan Rebmu, karena saya tahu program-program itu tidak minimal. :-)
Jarak "boros" yang Anda dapatkan pada akhirnya adalah apa yang terjadi ketika p2 dan p3 memiliki panjang yang tidak seimbang. Tetapi ketiga program memiliki ukuran yang berbeda dalam hal ini sehingga tidak ada pasangan yang baik untuk memilih p2 / p3. (Saya memilih ini karena tidak ada data eksternal sebagai input, seperti labirin atau apa pun, bukan karena mereka memiliki panjang yang sama. Sementara saya bisa menulis program baru yang lebih optimal, saya sudah menghabiskan cukup waktu dan intinya adalah Anda tidak perlu menulis program baru ...)
Bagaimana itu bekerja
(Catatan: Saya mulai dengan pendekatan yang lebih "kreatif" yang tidak terlalu ramping tetapi lebih menarik. Saya memindahkannya ke entri di blog saya karena menggambarkan pendekatan ini sudah lama.)
Kunci di sini adalah tipuan "kode eval sebagai string" seperti beberapa entri lainnya, ia hanya memiliki kartu truf dari pembatas string asimetris. Saya akan mulai dengan menjelaskan cara kerja huruf 80 karakter.
Inilah program "keseluruhan", menyesuaikan ruang kosong untuk keterbacaan kasus ini:
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}}
Di sini kita akhirnya mengatur DD ke sinonim untuk DO (alias "eval"). Tetapi triknya adalah bahwa ketika program yang dibelah dua berjalan, mereka menjalankan kode yang efeknya hanya mendefinisikan D ke literal tidak berbahaya 1.
Inilah yang dibuat oleh kode aneh-karakter, spasi putih disesuaikan lagi:
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"
Dan inilah kode genap:
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]"
Sebenarnya untuk program yang tidak terbelah dua, dd {dd {(arbitrary code)qt}}
akan mengeksekusi kode apa pun yang Anda inginkan. Namun, ada dua panggilan untuk mengevaluasi, bukan hanya satu. Itu karena sementara kawat gigi bersarang bekerja sangat baik dalam kode yang disisipkan, mereka mengacaukan perilaku eval DO. Karena:
do {{print "Hello"}}
Akan memuat string sebagai program, tetapi program itu berakhir menjadi hanya string konstan {print "Hello"}
. Jadi trik yang saya gunakan di sini adalah untuk mengambil DD saya (memegang nilai fungsi yang sama dengan DO) dan menjalankannya dua kali. Halvers mengunyah bagian-bagian berbeda dari string tetapi mereka tidak mengunyah keduanya jika genap / keanehan adalah benar untuk konten, dan karena apa yang tertinggal di luar string setelah membagi dua hanyalah konstanta integral d
mereka tidak berbahaya.
Dengan pola ini, tidak ada tantangan dalam menulis perilaku program ketika tidak dipotong setengah - Anda dapat memasukkan apa saja selama panjang karakter kode tersebut genap (aneh jika Anda menghitung QT, yang adalah QUIT). Jika Anda perlu mendapatkan angka genap dari angka ganjil, berikan spasi (jadi sebenarnya ada +1 di rumus saya di atas pada p1 untuk panjang program ganjil dari p1) . Triknya tampaknya untuk menulis kode yang disisipkan setelah itu, yang harus melewati parser jika tidak dibelah dua. (Ini tidak akan dijalankan karena QT, tetapi harus LOADable sebelum akan dieksekusi.)
Kasus ini sepele; pp
memuat baik sebagai simbol meskipun tidak terdefinisi, dan dibagi menjadi p
untuk dicetak di setiap program setengah. Tapi kita bisa melakukan trik lain hanya dengan menggunakan string literal lagi. Program yang dibelah dua masih memiliki DO yang didefinisikan secara normal, jadi kita bisa saja mengatakan:
ddoo{{pp{{[RReebdo]l}}}}
Dengan memiliki satu-satunya bagian yang diambil oleh parser dalam keseluruhan kasus menjadi kata simbolis ddoo
dan string literal, kita kemudian dapat interleave dua program yang kita inginkan di dalam string literal dan tidak membuat marah parser. Versi yang dibelah dua hanya akan mengatakan:
do{p{Rebol}}
..dan...
do{p{[Red]}}
Seperti yang saya katakan, bagian ini terlihat akrab dengan solusi lain yang memperlakukan program sebagai string dan mengevaluasi mereka. Tetapi dalam kasus kompetisi, ketika program yang Anda kemas berisi string bersarang, itu melemparkan kunci pas untuk mereka. Di sini satu-satunya hal yang akan membuat Anda dalam kesulitan adalah penggunaan melarikan diri melalui caret ( ^
) ... yang dapat dengan mudah diselesaikan.
(Catatan 'kecurangan' kecil: Saya menambahkan QT untuk "QUIT" dalam menanggapi masalah ini. Sebenarnya, saya sengaja menghapus singkatan untuk berhenti sebelum ... karena entah bagaimana saya pikir itu hanya baik untuk penggunaan konsol dan hanya mengambil ruang dua huruf jika tidak dalam REPL. Saya menambahkannya karena saya melihat saya salah, tidak menambahkannya untuk kasus ini secara khusus. Namun demikian, sebelum perubahan itu akan menjadi 2 karakter lagi. ketika saya pertama kali memposting solusinya ada bug di Rebmu yang membuatnya tidak berfungsi meskipun seharusnya ... sekarang berfungsi.)
x0=00;;
. Tantangan besar!