pengantar
Jika Anda tidak terbiasa dengan Hexagony , itu adalah bahasa esoterik yang dibuat oleh Martin Büttner. Masalahnya adalah bahwa bahasa ini menerima beberapa bentuk untuk program ini. Semua program berikut ini setara:
abcdefg
dan
a b
c d e
f g
Jadi pada dasarnya, kode tersebut telah digulung menjadi segi enam biasa. Tetapi perhatikan bahwa menambahkan perintah baru ke kode, yang abcdefgh
akan menghasilkan program berikut:
a b c
d e f g
h . . . .
. . . .
. . .
Seperti yang Anda lihat, langkah pertama adalah menggulung kode menjadi segi enam, dan setelah itu segi enam diisi dengan no-ops ( .
) ke nomor heksagonal tengah terpusat berikutnya .
Tugas Anda sederhana, ketika diberi string (kode sumber), mengeluarkan kode sumber segi enam lengkap.
Aturan
- Anda dapat menyediakan program atau fungsi.
- Ruang putih terkemuka diizinkan, tetapi hanya ketika segi enam tidak keluar dari bentuk
- Trailing whitespace diizinkan.
- Perhatikan bahwa spasi putih dalam program diabaikan . Begitu
a b c
juga denganabc
- Hanya karakter ASCII yang dapat dicetak (
32 - 126
) yang digunakan, jadi hanyaSpace
karakter biasa yang diabaikan. - Asumsikan bahwa panjang string lebih besar dari 0.
- Ini adalah kode-golf , jadi pengiriman dengan jumlah byte paling sedikit menang!
Uji kasus
Input: ?({{&2'2':{):!/)'*/
Output:
? ( {
{ & 2 '
2 ' : { )
: ! / )
' * /
Input: H;e;l;d;*;r;o;Wl;;o;*433;@.>;23<\4;*/
Output:
H ; e ;
l ; d ; *
; r ; o ; W
l ; ; o ; * 4
3 3 ; @ . >
; 2 3 < \
4 ; * /
Input: .?'.) .@@/'/ .!.> +=(<.!)} ( $>( <%
Output:
. ? ' .
) . @ @ /
' / . ! . >
+ = ( < . ! )
} ( $ > ( <
% . . . .
. . . .
abc`defg
akan benar-benar menjadi pastebin.com/ZrdJmHiR`
karakter)."Jawaban:
Pyth,
575450494846Test Suite
Mencetak ruang terkemuka di setiap baris.
Versi ini membutuhkan bukti bahwa 10 ^ n> = 3n (n - 1) + 1 untuk semua n> = 1 . Terima kasih kepada ANerdI dan ErickWong karena memberikan bukti.
Berikut ini ketidaksetaraan: 10 ^ n> (1 + 3) ^ n = 1 + 3n + 9n (n - 1) + ...> 3n (n - 1) + 1 orang dapat dengan mudah melihat bahwa ini benar untuk n> = 2 . Memeriksa kasus n = 1 agak sepele, memberi 10> 1 .
Sebagai alternatif, mengambil turunan dari persamaan ini dua kali menunjukkan bahwa 10 ^ n memiliki turunan kedua yang lebih besar untuk semua n> = 1 , yang kemudian dapat diturunkan ke derivatif pertama, dan akhirnya ke persamaan asli.
Penjelasan
sumber
Hexagony , 271 byte
Saya persembahkan untuk Anda, 3% pertama dari penerjemah mandiri Hexagony ...
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:
.
gantinya jika saya punya.Itu berarti ide dasar bermuara pada:
N
(dan angka heksagonal tengah yang sesuaihex(N)
) yang dapat menampung seluruh input.2N-1
.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 adalahIni 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 mengeksekusiIni 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:Di sini,
=&
salin panjangnya (29 dalam contoh kami) ke tepi berlabel panjang . Kemudian''3
pindah ke tepi berlabel 3 dan tetapkan nilainya3
(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 diN
sana dan menurunkannya.{=*
menghitung produk mereka dalam N (N-1) .'*)
mengalikannya dengan konstanta3
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:
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 .'=&
salinanN-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: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:
The
=
membalikkan arah MP lagi.M8
set nilai set ke778
(karena kode karakterM
is77
dan digit akan menambahkan sendiri ke nilai saat ini). Ini kebetulan10 (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 .
sumber
CJam,
56525048 bytePikiran pertama saya adalah, "hei saya sudah punya kode untuk ini!" Tetapi kemudian saya tidak dapat diganggu untuk menarik potongan-potongan yang diperlukan dari kode Ruby, terutama karena mereka sepertinya tidak terlalu cocok untuk bermain golf. Jadi saya mencoba sesuatu yang lain di CJam sebagai gantinya ...
Uji di sini.
Penjelasan
Sedikit matematika tentang angka heksagonal terpusat terlebih dahulu. Jika segi enam biasa memiliki panjang sisi
N
, maka akan berisi3N(N-1)+1
sel, yang harus sama dengan panjang kode sumberk
. Kita dapat menyelesaikannyaN
karena persamaan kuadrat sederhana:Kita dapat mengabaikan akar negatif, karena itu memberi N. negatif. Untuk ini memiliki solusi, kita perlu akar kuadrat menjadi setengah bilangan bulat. Atau dengan kata lain,
√(1 + 4(k-1)/3) = √((4k-1)/3)
harus berupa bilangan bulat (untungnya, bilangan bulat ini kebetulan merupakan diameterD = 2N-1
segi enam, yang bagaimanapun juga akan kita butuhkan). Jadi kita dapat berulang kali menambahkan satu.
hingga kondisi itu terpenuhi.Sisanya adalah loop sederhana yang menjabarkan segi enam. Pengamatan yang berguna untuk bagian ini adalah bahwa spasi di lekukan ditambah dengan non-spasi dalam kode di setiap baris bertambah hingga diameter.
Ternyata kita tidak perlu menggunakan aritmatika ganda sama sekali (kecuali untuk akar kuadrat). Karena perkalian dengan 4, tidak ada tabrakan saat membaginya dengan 3, dan yang diinginkan
k
akan menjadi yang pertama menghasilkan akar kuadrat bilangan bulat.sumber
Perl,
203200198termasuk +1 untuk
-p
jalankan sebagai:
echo abc | perl -p file.pl
Pendekatan yang sangat naif:
;
; kode itu sendiri di bawah 200 byte sekarang!$s=~/\S+/g
alih-alihsplit/\n/,$s
sumber
JavaScript (ES6), 162
172Fungsi anonim
Ukuran segi enam ditemukan menyelesaikan persamaan dari wikipedia
Rumus pemecahannya pada dasarnya
Dengan beberapa aljabar dan beberapa perkiraan (thx to @ user18655 juga) menjadi
Lebih mudah dibaca
Cuplikan uji (halaman penuh lebih baik - waktu berjalan ~ 1 menit)
sumber
n=...+1-1e-9|0
alih-alihn=Math.ceil(...)
menyimpan 2 byte. Anda juga bisa pergi ES7 dan menggunakan**0.5
bukannyaMath.sqrt
tapi itu terserah Anda. Saya biasanya hanya menyimpan jawaban saya ES6 karena mereka berfungsi di browser saya haha!Pyth,
5251 byteCobalah online. Suite uji.
Setiap baris memiliki satu ruang pemimpin tambahan, sebagaimana diizinkan oleh OP.
Penjelasan
sumber
Retina , 161 byte
Terima kasih kepada FryAmTheEggman karena telah menghemat 2 byte.
Jawaban ini tidak bersaing. Retina telah melihat beberapa pembaruan sejak tantangan ini, dan saya cukup yakin saya menggunakan beberapa fitur yang lebih baru (walaupun saya belum memeriksa).
Hitungan byte mengasumsikan penyandian ISO 8859-1. Baris pertama berisi satu ruang. Perhatikan bahwa sebagian besar
·
sebenarnya adalah titik tengah (0xB7).Cobalah online!
Baik...
Penjelasan
Tampaknya paling mudah untuk membangun tata letak terlebih dahulu menggunakan hanya satu karakter (
·
dalam hal ini) dan kemudian mengisi tata letak yang dihasilkan dengan karakter input. Alasan utama untuk ini adalah bahwa menggunakan satu karakter memungkinkan saya memanfaatkan referensi-ulang dan pengulangan karakter, di mana meletakkan input secara langsung akan membutuhkan kelompok penyeimbang yang mahal.Meskipun tidak terlihat banyak, tahap pertama ini menghilangkan spasi dari input.
Kita mulai dengan menambahkan baris tambahan yang berisi
M
titik-titik tengah, di manaM
panjang input (setelah menghilangkan spasi).Jika input adalah satu karakter, kami menghapus titik tengah itu lagi. Ini adalah kasus khusus yang tidak menguntungkan yang tidak dicakup oleh tahap selanjutnya.
Ini menghitung panjang sisi yang dibutuhkan
N
minus 1. Berikut ini cara kerjanya: bilangan heksagonal tengah berbentuk3*N*(N-1) + 1
. Karena bilangan segitiga adalahN*(N-1)/2
, itu berarti bilangan heksagonal adalah enam kali angka segitiga ditambah 1. Itu nyaman karena mencocokkan angka segitiga (yang benar-benar adil1 + 2 + 3 + ... + N
) dalam sebuah regex cukup mudah dengan referensi ke depan. Yang(^·|\2·)*
cocok dengan angka segitiga terbesar yang dimilikinya. Sebagai bonus yang bagus,$2
maka akan memegang indeks nomor segitiga ini. Untuk mengalikannya dengan 6, kami menangkapnya menjadi grup1
dan mencocokkannya 5 kali lagi. Kami memastikan setidaknya ada dua lagi·
dengan·
dan·+
. Dengan cara ini indeks bilangan segitiga yang ditemukan tidak meningkat sampai ada satu karakter lebih dari bilangan heksagonal terpusat.Pada akhirnya, pertandingan ini memberi kita dua kurang dari panjang sisi segi enam yang diperlukan dalam grup
$2
, jadi kami menulisnya kembali bersama dengan satu lagi titik pusat untuk mendapatkanN-1
.Ini mengubah string
N-1
titik pusat kami menjadiN-1
ruang,2N-1
titik pusat , danN-1
ruang lain . Perhatikan bahwa ini adalah lekukan maksimum, diikuti oleh diameter segi enam, diikuti oleh lekukan lagi.Ini panjang tidak menyenangkan, tetapi pada dasarnya hanya memberi kita semua pertandingan yang tumpang tindih , yang
2N-1
panjangnya a) karakter dan pada baris pertama atau b) baris kedua. Ini memperluas hasil dari tahap sebelumnya ke segi enam penuh, tapi aneh. Misalnya untuk input,12345678
kita akan mendapatkan:Ini sebabnya kami perlu menambahkan spasi di tahap sebelumnya juga.
Ini memperbaiki lekukan garis setelah pusat, dengan berulang kali indentasi setiap garis yang lebih pendek dari sebelumnya (mengabaikan ruang trailing), jadi kami mendapatkan ini:
Sekarang kita cukup menyisipkan beberapa spasi
Yang memberi kita:
Fiuh, sudah selesai.
Saatnya mengisi string input ke titik-titik tengah. Ini dilakukan dengan bantuan semacam tahapan. Kami mencocokkan semua titik pusat dan setiap karakter pada baris terakhir, dan kami mengurutkannya berdasarkan hasil substitusi yang diberikan. Substitusi itu kosong untuk karakter pada baris terakhir dan
·
untuk titik tengah, jadi yang terjadi adalah titik tengah hanya diurutkan hingga akhir (karena pengurutan stabil). Ini memindahkan karakter input ke tempatnya:Tinggal dua hal yang tersisa sekarang:
Ini mengubah titik pusat menjadi periode reguler.
Dan ini membuang baris terakhir.
sumber
JavaScript (ES6), 144 byte
Dimana
\n
mewakili karakter baris baru literal. Menggunakan teknik untuk membuat hexagon yang sebelumnya saya gunakan pada beberapa jawaban grid hexagonal lainnya . Untuk ES7 mengambil akar kuadrat berhasil sedikit lebih pendek daripada pendekatan rekursif:sumber
Python 3 , 144 byte
Cobalah online!
Ini menggunakan jumlah spasi spasial yang agak bervariasi untuk ukuran segi enam yang berbeda, tetapi bentuk umum tetap bertahan.
sumber