Saya persembahkan untuk Anda, 3% pertama dari penerjemah mandiri Hexagony ...
|./...\..._..>}{<$}=<;>'<..../;<_'\{*46\..8._~;/;{{;<..|M..'{.>{{=.<.).|.."~....._.>(=</.\=\'$/}{<}.\../>../..._>../_....@/{$|....>...</..~\.>,<$/'";{}({/>-'(<\=&\><${~-"~<$)<....'.>=&'*){=&')&}\'\'2"'23}}_}&<_3.>.'*)'-<>{=/{\*={(&)'){\$<....={\>}}}\&32'-<=._.)}=)+'_+'&<
Cobalah online! Anda juga dapat menjalankannya sendiri, tetapi akan memakan waktu sekitar 5-10 detik.
Pada prinsipnya ini mungkin cocok dengan panjang sisi 9 (untuk skor 217 atau kurang), karena ini hanya menggunakan 201 perintah, dan versi yang tidak di-serang yang saya tulis pertama kali (pada panjang sisi 30) hanya membutuhkan 178 perintah. Namun, saya cukup yakin akan butuh waktu lama untuk benar-benar membuat semuanya pas, jadi saya tidak yakin apakah saya benar-benar akan mencobanya.
Seharusnya juga memungkinkan untuk bermain golf ini sedikit dalam ukuran 10 dengan menghindari penggunaan satu atau dua baris terakhir, sehingga trailing no-ops dapat dihilangkan, tetapi itu akan membutuhkan penulisan ulang yang substansial, sebagai salah satu jalur pertama bergabung memanfaatkan sudut kiri bawah.
Penjelasan
Mari kita mulai dengan membuka kode dan membubuhi keterangan jalur alur kontrol:
Itu masih cukup berantakan, jadi di sini adalah diagram yang sama untuk kode "ungolfed" yang saya tulis pertama (sebenarnya, ini adalah sisi-panjang 20 dan awalnya saya menulis kode pada sisi-panjang 30 tapi itu sangat jarang sehingga tidak akan dapat meningkatkan keterbacaan sama sekali, jadi saya memadatkannya sedikit agar ukurannya lebih masuk akal):
Klik untuk versi yang lebih besar.
Warnanya persis sama terlepas dari beberapa detail yang sangat kecil, perintah non-kontrol-aliran juga persis sama. Jadi saya akan menjelaskan bagaimana ini bekerja berdasarkan versi yang tidak di-serigala, dan jika Anda benar-benar ingin tahu cara kerja golf, Anda dapat memeriksa bagian mana yang sesuai dengan yang ada di segi enam yang lebih besar. (Satu-satunya tangkapan adalah bahwa kode golf dimulai dengan cermin sehingga kode sebenarnya dimulai di sudut kanan ke kiri.)
Algoritma dasar hampir identik dengan jawaban CJam saya . Ada dua perbedaan:
- Alih-alih memecahkan persamaan bilangan heksagonal terpusat, saya hanya menghitung angka heksagonal terpusat berturut-turut sampai satu sama dengan atau lebih besar dari panjang input. Ini karena Hexagony tidak memiliki cara sederhana untuk menghitung akar kuadrat.
- Alih-alih melapisi input dengan no-ops segera, saya memeriksa nanti apakah saya sudah kehabisan perintah dalam input dan mencetak sebagai
.
gantinya jika saya punya.
Itu berarti ide dasar bermuara pada:
- Baca dan simpan string input sambil menghitung panjangnya.
- Temukan panjang sisi terkecil
N
(dan angka heksagonal tengah yang sesuai hex(N)
) yang dapat menampung seluruh input.
- Hitung diameternya
2N-1
.
- Untuk setiap baris, hitung indentasi dan jumlah sel (yang dijumlahkan
2N-1
). Cetak indentasi, cetak sel (menggunakan .
jika input sudah habis), cetak linefeed.
Perhatikan bahwa hanya ada no-ops sehingga kode aktual dimulai di sudut kiri ( $
,, yang melompati >
, jadi kita benar-benar mulai di ,
dalam jalur abu-abu gelap).
Ini adalah kotak memori awal:
Jadi penunjuk memori dimulai pada input berlabel tepi , menunjuk Utara. ,
membaca byte dari STDIN atau -1
jika kita menekan EOF ke tepi itu. Oleh karena itu, <
hak setelah adalah syarat untuk apakah kita sudah membaca semua input. Mari tetap di loop input untuk saat ini. Kode selanjutnya yang kita jalankan adalah
{&32'-
Ini menulis 32 ke dalam tepi berlabel ruang , dan kemudian menguranginya dari nilai input di tepi berlabel beda . Perhatikan bahwa ini tidak pernah dapat menjadi negatif karena kami dijamin bahwa input hanya berisi ASCII yang dapat dicetak. Ini akan menjadi nol ketika inputnya adalah spasi. (Seperti yang Timwi tunjukkan, ini akan tetap bekerja jika inputnya bisa berisi baris atau tab, tetapi juga akan menghapus semua karakter yang tidak patut lainnya dengan kode karakter kurang dari 32). Dalam hal ini, <
defleksi penunjuk instruksi (IP) tersisa dan jalur abu-abu terang diambil. Jalur itu hanya menyetel ulang posisi MP dengan {=
dan kemudian membaca karakter berikutnya - dengan demikian, spasi dilewati. Kalau tidak, jika karakter itu bukan spasi, kami mengeksekusi
=}}})&'+'+)=}
Ini langkah pertama sekitar segi enam melalui panjang tepi sampai kebalikannya yang diff tepi, dengan =}}}
. Kemudian ia menyalin nilai dari berlawanan dengan tepi panjang ke tepi panjang , dan menambahkannya dengan )&'+'+)
. Kita akan melihat sebentar mengapa ini masuk akal. Akhirnya, kami memindahkan keunggulan baru dengan =}
:
(Nilai tepi tertentu berasal dari test case terakhir yang diberikan dalam tantangan.) Pada titik ini, loop berulang, tetapi dengan semuanya bergeser satu hexagon timur laut. Jadi setelah membaca karakter lain, kita mendapatkan ini:
Sekarang Anda dapat melihat bahwa kami secara bertahap menulis input (spasi minus) di sepanjang diagonal timur laut, dengan karakter di setiap sisi lainnya, dan panjangnya hingga karakter tersebut disimpan sejajar dengan tepi berlabel panjang .
Ketika kita selesai dengan loop input, memori akan terlihat seperti ini (di mana saya sudah memberi label beberapa tepi baru untuk bagian selanjutnya):
Ini %
adalah karakter terakhir yang kita baca, 29
jumlah karakter non-spasi yang kita baca. Sekarang kita ingin menemukan panjang sisi segi enam. Pertama, ada beberapa kode inisialisasi linier di jalur hijau / abu-abu gelap:
=&''3{
Di sini, =&
salin panjangnya (29 dalam contoh kami) ke tepi berlabel panjang . Kemudian ''3
pindah ke tepi berlabel 3 dan tetapkan nilainya 3
(yang kita perlukan sebagai konstanta dalam perhitungan). Akhirnya {
pindah ke tepi berlabel N (N-1) .
Sekarang kita memasuki lingkaran biru. Peningkatan loop ini N
(disimpan dalam sel berlabel N ) kemudian menghitung angka heksagonal terpusatnya dan mengurangkannya dari panjang input. Kode linear yang melakukan itu adalah:
{)')&({=*'*)'-
Di sini, {)
bergerak ke dan bertahap N . ')&(
pindah ke tepi berlabel N-1 , menyalin di N
sana dan menurunkannya. {=*
menghitung produk mereka dalam N (N-1) . '*)
mengalikannya dengan konstanta 3
dan meningkatkan hasilnya di tepi berlabel hex (N) . Seperti yang diharapkan, ini adalah angka heksagonal terpusat ke-N. Akhirnya '-
menghitung perbedaan antara itu dan panjang input. Jika hasilnya positif, panjang sisi belum cukup besar, dan loop berulang (di mana }}
pindahkan MP kembali ke tepi berlabel N (N-1) ).
Setelah panjang sisi cukup besar, perbedaannya akan menjadi nol atau negatif dan kami mendapatkan ini:
Pertama, sekarang ada jalur hijau linier yang sangat panjang yang melakukan inisialisasi yang diperlukan untuk loop keluaran:
{=&}}}32'"2'=&'*){=&')&}}
The {=&
dimulai dengan menyalin hasil dalam diff tepi ke dalam panjang tepi, karena kita kemudian membutuhkan sesuatu non-positif di sana. }}}32
menulis 32 ke tepi berlabel ruang . '"2
menulis konstanta 2 ke tepi unlabelled di atas diff . '=&
salinan N-1
ke tepi kedua dengan label yang sama. '*)
mengalikannya dengan 2 dan menambahkannya sehingga kami mendapatkan nilai yang benar di tepi berlabel 2N-1 di bagian atas. Ini adalah diameter segi enam. {=&')&
menyalin diameter ke tepi lainnya berlabel 2N-1 . Akhirnya }}
bergerak kembali ke tepi berlabel 2N-1 di bagian atas.
Mari beri label ulang pada tepi-tepinya:
Tepi kita saat ini (yang masih memegang diameter segi enam) akan digunakan untuk beralih di atas garis output. Indentasi tepi berlabel akan menghitung berapa banyak ruang yang dibutuhkan pada baris saat ini. Tepi berlabel sel akan digunakan untuk beralih pada jumlah sel pada baris saat ini.
Kami sekarang berada di jalur merah muda yang menghitung lekukan . ('-
mengurangi garis iterator dan menguranginya dari N-1 (ke tepi indentasi ). Cabang pendek biru / abu-abu dalam kode hanya menghitung modulus hasil ( ~
meniadakan nilai jika negatif atau nol, dan tidak ada yang terjadi jika positif). Sisa dari jalur merah muda adalah "-~{
yang mengurangi indentasi dari diameter ke tepi sel dan kemudian bergerak kembali ke tepi indent .
Jalan kuning kotor sekarang mencetak lekukan. Konten loop benar-benar adil
'";{}(
Di mana '"
bergerak ke tepi ruang , ;
mencetaknya, {}
bergerak kembali ke indentasi dan (
menurunkannya.
Ketika kita selesai dengan itu, jalur abu-abu gelap (kedua) mencari karakter berikutnya untuk dicetak. The =}
bergerak dalam posisi (yang berarti, ke sel tepi, menunjuk Selatan). Kemudian kita memiliki loop {}
yang sangat ketat yang hanya bergerak ke bawah dua sisi ke arah Barat Daya, sampai kita mencapai ujung string yang disimpan:
Perhatikan bahwa saya telah me-relabelled satu sisi EOF di sana ? . Setelah kami memproses karakter ini, kami akan membuat edge itu negatif, sehingga {}
loop akan berakhir di sini alih-alih iterasi berikutnya:
Dalam kode, kita berada di ujung jalur abu-abu gelap, tempat '
bergerak mundur satu langkah ke karakter input. Jika situasinya adalah salah satu dari dua diagram terakhir (yaitu masih ada karakter dari input yang belum kami cetak), maka kami mengambil jalur hijau (yang paling bawah, untuk orang-orang yang tidak pandai dengan hijau dan biru). Yang itu cukup sederhana: ;
mencetak karakter itu sendiri. '
pindah ke tepi ruang yang sesuai yang masih memegang 32 dari sebelumnya dan ;
mencetak ruang itu. Lalu {~
buat EOF kita ? negatif untuk iterasi berikutnya, '
bergerak mundur satu langkah sehingga kita dapat kembali ke ujung Utara-Barat string dengan }{
loop ketat lain . Yang berakhir pada panjangsel (yang non-positif di bawah hex (N) . Akhirnya }
bergerak kembali ke tepi sel .
Jika kita sudah kehabisan input, maka loop mana yang mencari EOF? akan benar-benar berakhir di sini:
Dalam hal ini '
bergerak ke sel panjang , dan kami mengambil jalur biru muda (atas), yang mencetak no-op. Kode di cabang ini linear:
{*46;{{;{{=
The {*46;
menulis 46 ke tepi berlabel no-op dan mencetaknya (periode yaitu a). Kemudian {{;
pindah ke tepi ruang dan cetak itu. The {{=
bergerak kembali ke sel tepi untuk iterasi berikutnya.
Pada titik ini jalur bergabung kembali dan (
mengurangi tepi sel . Jika iterator belum nol, kita akan mengambil jalur abu-abu terang, yang hanya membalik arah MP =
dan kemudian mencari karakter berikutnya untuk dicetak.
Jika tidak, kami telah mencapai akhir dari baris saat ini, dan IP akan mengambil jalur ungu sebagai gantinya. Beginilah bentuk kotak memori pada saat itu:
Jalur ungu berisi ini:
=M8;~'"=
The =
membalikkan arah MP lagi. M8
set nilai set ke 778
(karena kode karakter M
is 77
dan digit akan menambahkan sendiri ke nilai saat ini). Ini kebetulan 10 (mod 256)
, jadi ketika kami mencetaknya ;
, kami mendapat umpan baris. Kemudian ~
buat tepi negatif lagi, '"
bergerak kembali ke tepi garis dan =
membalikkan MP sekali lagi.
Sekarang jika garis tepi nol, kita selesai. IP akan mengambil jalur merah (sangat pendek), tempat @
menghentikan program. Kalau tidak, kita melanjutkan jalur ungu yang kembali ke jalur merah muda, untuk mencetak baris lain.
Diagram alir kontrol dibuat dengan HexagonyColorer Timwi . Diagram memori dibuat dengan debugger visual dalam IDE Esoteriknya .
abc`defg
akan benar-benar menjadi pastebin.com/ZrdJmHiR