The Devil's Staircase adalah fungsi seperti fraktal yang terkait dengan set Cantor.
Tugas Anda adalah mereplikasi fungsi funky ini - dalam seni ASCII!
Memasukkan
Bilangan bulat tunggal n >= 0
, menunjukkan ukuran output. Input dapat diberikan melalui STDIN, argumen fungsi atau argumen baris perintah.
Keluaran
Karya ASCII-art dari tangga Iblis ukurannya n
, baik dikembalikan sebagai string atau dicetak ke STDOUT. Mengejar spasi di akhir setiap baris tidak apa-apa, tetapi spasi di depan tidak. Anda dapat secara opsional mencetak satu baris baru.
Untuk ukuran 0
, outputnya hanya:
x
(Jika diinginkan, Anda dapat menggunakan karakter ASCII lain yang dapat dicetak selain ruang, sebagai ganti x
.)
Untuk ukuran n > 0
, kami:
- Ambil output ukuran
n-1
dan regangkan setiap baris dengan faktor tiga - Riffle di antara barisan single
x
s - Geser baris ke kanan sehingga tepat ada satu
x
di setiap kolom, dan posisi yang pertamax
minimal sambil mengurangi dengan baris
Sebagai contoh, output untuk n = 1
adalah:
x
xxx
x
Untuk mendapatkan hasil n = 2
, kami meregangkan setiap baris dengan faktor tiga:
xxx
xxxxxxxxx
xxx
Riffle diantara baris single x
:
x
xxx
x
xxxxxxxxx
x
xxx
x
Bergeser ke kanan:
x
xxx
x
xxxxxxxxx
x
xxx
x
Sebagai contoh lain, di sini adalah n = 3
.
Mencetak gol
Ini adalah kode-golf, jadi solusi dalam byte paling sedikit menang.
(,],~3^#@~.)@]
bukannya(1,[:,1,"0~3*])
menyimpan 1 byte. Dan jika Anda baik-baik saja dengan!
output charu:32+
bukannya' #'{~
menyimpan yang lain.#\
alih-alihi.@#
dan Anda menyusul APL! :)n-1
bukan untukn
.Hexagony , 217 byte
Ini sangat menyenangkan. Terima kasih telah mengirimkan tantangan ini.
Pengungkapan penuh: Bahasa (Hexagony) tidak ada pada saat tantangan ini diposting. Namun, saya tidak menciptakannya, dan bahasanya tidak dirancang untuk tantangan ini (atau tantangan spesifik lainnya).
Ditata secara heksagon:
Program tidak benar-benar menggunakan
#
instruksi, jadi saya menggunakan karakter itu untuk menunjukkan sel mana yang benar-benar tidak digunakan.Bagaimana cara kerja program ini? Itu tergantung. Apakah Anda ingin versi pendek, atau panjang?
Penjelasan singkat
Untuk mengilustrasikan apa yang saya maksud dengan "garis" dan "segmen" dalam penjelasan berikut, pertimbangkan diseksi ini dari output yang dimaksudkan:
Dengan penjelasan itu, program berhubungan dengan pseudocode berikut:
Penjelasan panjang
Silakan lihat diagram jalur kode kode warna ini.
Eksekusi dimulai di sudut kiri atas. Urutan instruksi
){2'"''3''"2}?)
dieksekusi (ditambah beberapa pembatalan yang berlebihan, seperti"{
dll.) Dengan mengejar jalur yang cukup berbelit-belit. Kita mulai dengan Instruction Pointer # 0, disorot dalam crimson. Di tengah jalan, kami beralih ke # 1, mulai dari sudut kanan atas dan dicat hijau hutan. Ketika IP # 2 dimulai dengan warna biru jagung (kanan tengah), tata letak memorinya adalah ini:Sepanjang keseluruhan program, tepi berlabel 2a dan 2b akan selalu memiliki nilai
2
(kami menggunakannya untuk menghitung 2ⁿ⁺¹ dan untuk membagi dengan 2, masing-masing) dan tepi berlabel 3 akan selalu3
(kami menggunakannya untuk menghitung 3ⁱ).Kami mulai berbisnis saat kami memasuki lingkaran pertama kami, disorot dengan warna biru bunga jagung. Loop ini menjalankan instruksi
(}*{=&}{=
untuk menghitung nilai 2ⁿ⁺¹. Ketika loop keluar, jalur sadel coklat diambil, yang membawa kita ke Instruction Pointer # 3. IP ini hanya berkecimpung di sepanjang tepi bawah ke arah barat dengan warna kuning keemasan dan segera memberikan kontrol ke IP # 4.Jalur fuchsia menunjukkan bagaimana IP # 4, mulai dari kiri bawah, berjalan dengan cepat ke garis penurunan , set ch ke
32
(karakter spasi) dan seg ke (nilai baru dari) baris . Hal ini disebabkan oleh penurunan awal yang sebenarnya kita mulai dengan 2ⁿ⁺¹ − 1 dan akhirnya mengalami iterasi terakhir dengan nilai 0. Kami kemudian memasuki loop bersarang pertama .Kita mengalihkan perhatian kita ke indigo bercabang, di mana, setelah penurunan singkat dari seg , kita melihat ch diperbarui
x
hanya jika seg sekarang nol. Setelah itu, n disetel ke garis - seg untuk menentukan jumlah sebenarnya dari segmen yang kita masuki. Segera kita memasuki lingkaran lain, kali ini dalam warna tomat yang adil.Di sini, kita mencari tahu berapa kali n (jumlah segmen saat ini) dapat dibagi dengan 2. Selama modulo memberi kita nol, kita menambah i dan membagi n dengan 2. Ketika kita puas n tidak lagi dengan demikian dapat dibagi , kita bercabang ke dalam abu-abu batu tulis, yang berisi dua loop: pertama itu meningkatkan 3 pangkat dari i yang kita hitung, dan kemudian menghasilkan ch yang berkali-kali. Perhatikan bahwa loop pertama ini berisi a
[
instruksi, yang beralih kontrol ke IP # 3 - yang hanya mengambil langkah kecil di sepanjang tepi bawah sebelumnya. Tubuh loop (dikalikan dengan 3 dan decrementing) dieksekusi oleh IP # 3 yang kesepian, dipenjara dalam siklus hijau zaitun gelap tak berujung di sepanjang tepi bawah kode. Demikian pula, yang kedua dari loop abu-abu batu tulis ini berisi]
instruksi, yang mengaktifkan IP # 5 untuk menghasilkan ch dan pengurangan, ditunjukkan di sini dalam warna merah India gelap. Dalam kedua kasus tersebut, Instruksi Pointer yang terjebak dalam perbudakan dengan patuh melaksanakan satu iterasi pada satu waktu dan memberikan kontrol kembali ke IP # 4, hanya untuk menunggu saat layanan mereka dipanggil sekali lagi. Sementara itu, abu-abu batu tulis bergabung kembali dengan saudara-saudaranya yang fuchsia dan nila.Ketika seg tak terelakkan mencapai nol, loop nila keluar ke jalur hijau halaman, yang hanya menampilkan karakter baris baru dan segera bergabung kembali ke fuchsia untuk melanjutkan loop baris . Di luar iterasi akhir dari loop line, terdapat jalur ebon pendek dari terminasi program akhir.
sumber
Python 2, 78
Dimulai dengan daftar
L=[1]
, kami menduplikatnya dan menyisipkan kekuatan 3 berikutnya di tengah, menghasilkan[1, 3, 1]
. Ini berulangn
kali untuk memberi kita panjang baris untuk tangga Iblis. Kemudian kami mencetak setiap baris yang diisi dengan spasi.sumber
APL, 38
Contoh:
Penjelasan:
sumber
GNU sed, 142
Bukan jawaban terpendek, tetapi sed !:
Karena ini adalah sed (bukan aritmatika asli), saya mengambil kebebasan dengan aturan "Bilangan bulat tunggal n> = 0, menunjukkan ukuran output" . Dalam hal ini integer input harus berupa string
1
s, yang panjangnya adalah n. Saya pikir ini "menunjukkan" ukuran output, meskipun itu bukan setara numerik langsung dengan n. Jadi untuk n = 2, string input akan menjadi11
:Ini tampaknya lengkap dengan kompleksitas waktu eksponensial dari O (c n ), di mana c adalah sekitar 17. n = 8 membutuhkan waktu sekitar 45 menit untuk saya.
Atau jika diperlukan bahwa n dimasukkan tepat secara numerik, maka kita bisa melakukan ini:
sed, 274 byte
Keluaran:
sumber
Python 2, 81
Versi program (88)
Jumlah x pada baris
n
ke-1 yang diindeks adalah 3 pangkat (indeks dari bit set pertaman
, mulai dari lsb).sumber
Python 2, 74
Pendekatan rekursif. Ukuran- $ n $ tangga setan dibagi menjadi tiga bagian
n-1
, yang panjangnya3**n - 2**n
x
', panjangnya3**n
n-1
, yang panjangnya3**n - 2**n
Perhatikan bahwa panjang total dari tiga bagian adalah
3*(3**n) - 2*(2**n)
atau3**(n+1) - 2**(n+1)
, yang mengkonfirmasi induksi.Variabel opsional
s
menyimpan offset bagian yang saat ini kami cetak. Pertama-tama kita kambuh ke cabang kiri dengan offset yang lebih besar, lalu cetak garis tengah, lalu lakukan cabang kanan pada offset saat ini.sumber
CJam,
363533 byteBerikut ini adalah pendekatan CJam lain (saya belum melihat kode Pengoptimal, jadi saya tidak tahu apakah itu sebenarnya jauh berbeda):
Ini digunakan
0
untuk kurva. Atau, (menggunakan trik grc)yang menggunakan
x
.Uji di sini.
Penjelasan
Ide dasarnya adalah untuk pertama-tama membentuk array dengan baris, seperti
Dan kemudian untuk pergi melalui daftar ini, mengawali jumlah ruang yang tepat.
Versi lain berfungsi sama, tetapi membuat array dengan panjang, seperti
Dan kemudian mengubahnya menjadi string
x
s di peta akhir.sumber
Dyalog APL, 34 karakter
Menggunakan pendekatan oleh grc. Gambar tangga dengan
⌹
karakter (domino) dan ambil input dari stdin. Solusi ini mengasumsikan⎕IO←0
.⎕
- ambil input dari stdin.⌽⍳1+⎕
- urutan angka dari⎕
bawah ke 0. (misalnya3 2 1 0
)3*⌽⍳1+⎕
- tiga pangkat dari itu (misalnya27 9 3 1
)(⊢,,)/3*⌽⍳1+⎕
- hasil sebelumnya dilipat dari kanan oleh fungsi diam-diam⊢,,
yang sama dengan dfn{⍵,⍺,⍵}
menghasilkan panjang langkah tangga iblis sesuai pendekatan grc.{⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕
panjang langkah diubah menjadi langkah.(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕
itu diklasifikasikan sendiri, seperti dalam solusi J saya . Perhatikan bahwa⊖
sudah membalik hasilnya dengan benar.' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕]
angka-angka digantikan oleh blanko dan domino.sumber
Ruby, 99
Jawaban berbeda dari jawaban saya yang lain, terinspirasi oleh jawaban FUZxxl
FUZxxl mencatat bahwa jumlah x sesuai dengan jumlah faktor 2 indeks. misalnya untuk n = 2 kita memiliki faktorisasi berikut:
Saya menggunakan cara yang lebih mudah untuk mengekstraksi kekuatan 2 ini:
i=m&-m
yang menghasilkan urutan1 2 1 4 1 2 1
dll. Ini berfungsi sebagai berikut:m-1
adalah samam
dengan bit yang paling signifikan, tetapi bit 1 yang paling signifikan menjadi nol, dan semua nol di sebelah kanan menjadi 1.Untuk dapat DAN ini dengan yang asli, kita perlu membalik bit. Ada berbagai cara untuk melakukan ini. Salah satu caranya adalah dengan mengurangi
-1
.Rumus keseluruhan inilah
m& (-1 -(m-1))
yang disederhanakan menjadim&(-m)
Contoh:
Inilah kodenya: baris baru dihitung, indentasi tidak perlu dan karenanya tidak dihitung, seperti jawaban saya yang lain. Ini sedikit lebih lama dari jawaban saya yang lain karena konversi yang canggung dari basis 2:
1 2 1 4 1 2 1 etc
ke basis 3:1 3 1 9 1 3 1 etc
(apakah ada cara untuk menghindari ituMath::
?)sumber
Ruby,
14099Kode Ruby kedua saya, dan penggunaan bahasa saya yang non-privat pertama. Saran dipersilahkan. Jumlah byte tidak termasuk spasi awal untuk indentasi, tetapi termasuk baris baru (tampaknya sebagian besar baris baru tidak dapat dihapus kecuali jika mereka diganti dengan spasi setidaknya.)
Input adalah dengan panggilan fungsi. Output adalah array string, yang ruby dengan mudah dibuang ke stdout sebagai daftar yang dipisahkan dengan baris baru dengan satu
puts
.Algoritma ini hanya
new iteration
=previous iteration
+extra row of n**3 x's
+previous iteration
. Namun adabanyakcukup kode hanya untuk mendapatkan ruang terkemuka dalam output yang tepat.Edit: Ruby, 97
Ini menggunakan pendekatan yang sama tetapi berbeda untuk membangun tabel numerik dari semua jumlah x yang diperlukan dalam array
a
dengan cara yang dijelaskan di atas, tetapi kemudian membangun tabel string setelahnya. Tabel string dibangun mundur dalam arrayc
menggunakan metode yang agak anehunshift
untuk menambahkan ke array yang ada.Saat ini pendekatan ini terlihat lebih baik - tetapi hanya dengan 2 byte :-)
sumber
for m in(0..n-1)do ... end
dengann.times{|m|...}
.n.times
dan saya pasti akan mengingatnya. Ini menghilangkanend
juga! Namun pada kesempatan ini saya bertanya - tanya apakahfor m in (1..n)
mungkin lebih baik, untuk menghindari(m+1)
. Apakah ada cara penulisan yang lebih pendek?for
panjang terutama karena Anda dipaksa untuk menggunakanend
(Anda dapat menggantido
dengan baris baru atau dengan;
). Untuk1..n
bisa kamu gunakan1.upto(n){|m|...}
. Saya suka tampilan(1..n).each{|i|...}
tetapi sedikit lebih lama daripada menggunakanupto
. Dan perhatikan bahwa iterasi dengan meneleponeach
atauupto
tidak hanya lebih pendek, itu juga mempertimbangkan Ruby yang lebih idiomatis.1.upto(n)
! Dengan itu dan beberapa tanda kurung yang tidak perlu hilang, saya sudah turun ke 120. Saya pikir di bawah 100 adalah mungkin, saya akan memposting kode revisi nanti.Haskell, 99 karakter
Fungsinya adalah
d
:sumber
q
dan lakukanq x=x
dalam case daftar kosong. Juga, tampaknya tanda kurung di sekitariterate...[1]
tidak perlu.PHP - 137 byte
Di sini saya menggunakan trik yang sama dengan grc . Ini adalah versi yang tidak disunat:
sumber
3**$i
-> terasa seperti PHP 5.6. Anda harus menentukannya. Ini tidak kompatibel dengan hampir setiap instalasi PHP. Untuk menghemat beberapa byte, Anda harus mulai dengan$r=str_repeat;
dan di mana Anda memiliki fungsi itu, Anda bisa menggantinya dengan$r
, menghemat 2 byte. Juga,$r('x',$v)
bisa$r(x,$v)
dan itu akan berfungsi dengan baik (perhatikan bahwa saya sudah mengganti nama fungsi dengan variabel). Juga, saya percaya bahwa++$i<=$n
dapat ditulis ulang karena$n>++$i
menghemat byte lain.function f($n){$r=str_repeat;$a=[1];while($n>++$i)$a=array_merge($a,[3**$i],$a);foreach($a as$v){$o=$r(' ',$s).$r(x,$v)."\r$o";$s+=$v;}echo$o;}
(alih-alih memiliki baris jelek itu, saya telah menambahkan urutan escape\r
di dalam string yang dikutip ganda, dengan variabel$o
di dalamnya. Dengan demikian"\r$o"
memiliki byte-count yang sama dengan yang''.$o
ada, dengan baris baru dihentikan pada yang terakhir dan menghasilkan hasil yang samawhile
harus$n>$i++
untuk pengurangan ini untuk bekerja dengan baik.$r=str_repeat
triknya. Saya hanya memikirkan$r='str_repeat';
, yang tidak menyimpan byte. Konstanta yang tidak terdefinisi juga merupakan trik yang baik, dilakukan dengan baik;). Baris baru lebih kecil satu byte dari pada menulis\n
, jadi saya menyimpannya, tetapi saya telah menggunakan tanda kutip ganda untuk menghindari penggabungan dengan$0
. Terima kasih lagi !3 ** $i
saya akan mengatakan bahwa Anda memiliki sintaks yang mengerikan. Anda dapat mengatasi koreksi itu. Saya katakan tentang ini saja dan bukan[1]
karena itu berasal dari PHP5.4, yang cukup 'lama'. 1 tahun yang lalu, saya akan meminta Anda untuk menentukannya. Hari ini, saya meminta Anda untuk hanya menentukan (dalam garis yang sangat pendek) yang menentukan ini. Berbicara tentang kode, Anda masih memiliki++$i<=$n
yang dapat diganti$n>$i++
. Saya harus mengubah semua kode Anda ke PHP5.3 untuk mengujinya. Itu menyakitkan. Tapi saya melihat Anda makan 7 byte sejauh ini.C, 165
Berikut kode yang sama dibongkar dan sedikit dibersihkan:
Ini didasarkan pada ide yang sama dengan solusi FUZxxl untuk masalah tersebut, yaitu menggunakan formulir eksplisit dan bukan implisit untuk baris. Deklarasi j menetapkannya menjadi 2 ^ (n + 1), dan loop while pertama menghitung k = 3 ^ (n + 1); maka l = 3 ^ (n + 1) -2 ^ (n + 1) adalah lebar total tangga (ini tidak terlalu sulit untuk dibuktikan). Kami kemudian memeriksa semua angka r dari 1 hingga 2 ^ (n + 1) -1; untuk masing-masing, jika itu habis dibagi (tepat) 2 ^ n maka kami berencana untuk mencetak s = 3 ^ n 'X's. Aku disesuaikan untuk memastikan kita mulai dari tempat yang tepat: kita menulis l spasi dan s 'X, lalu baris baru.
sumber
(*p)()=putchar;
di awal untuk memanggilputchar
sebagaip
. Saya pikir itu harus berhasil.CJam,
46 43 41 39 3635 bytePEMBARUAN menggunakan pendekatan yang berbeda sekarang.
Pendekatan lama:
Cukup naif dan panjang, tetapi sesuatu untuk memulai.
Akan menambahkan penjelasan setelah saya golf itu.
Cobalah online di sini
sumber
Java,
271269 byteMenggunakan metode grc.
Bertakuk:
Setiap saran dipersilahkan.
2 byte berkat mbomb007
sumber
b.size()>0
bukannya!b.isEmpty()
menghemat 2 byte.Perl, 62
Pertama hitung hasilnya secara iteratif tanpa spasi terkemuka. Kemudian tambahkan mereka sebelum setiap baris sesuai dengan jumlah
x
karakter di sisa string.sumber
JavaScript (ES6) 104
106 118Edit Menghapus fungsi rekursif, daftar '*' untuk setiap baris diperoleh secara iteratif, mengutak-atik bit dan kekuatan 3 (seperti dalam banyak jawaban lainnya)
Di dalam loop, string multiline dibangun dari bawah ke atas, menjaga hitungan berjalan ruang terkemuka untuk ditambahkan di setiap baris
Coba Pertama dihapus
Fungsi R rekursif membangun array dengan jumlah '*' untuk setiap baris. Misalnya R (2) adalah
[1, 3, 1, 9, 1, 3, 1]
larik ini dipindai untuk membangun string multiline dari bawah ke atas, menjaga agar hitungan spasi terdepan ditambahkan di setiap baris
Uji di Firefox / konsol FireBug
Keluaran
sumber
R - 111 karakter
Implementasi langsung, membangun array berulang dan menghancurkannya perlahan.
Pemakaian:
sumber
n
argumen dari baris perintahn=scan()
.x
untuk menggunakannya sebagai kursor, Anda juga tidak perluif(n)
. Juga, jeda baris dihitung sebagai karakter yang saya pikir.x
. Namun tidak yakinif(n)
. Saya menambahkan bagian itu untuk menangani kasus inin=0
. Theif(n)
kemudian kembaliF
dan karenanya mengembalikan tunggalx
. Jika saya menghapusnya,n=0
memberikan hasil yang tidak diinginkan. Baru di sini, jadi tidak tahu tentang jeda baris. Termasuk sekarang!a=0
dan memulai loopx in 0:n
itu juga berfungsi untuk n = 0. Maka Anda dapat menghilangkanif(n)
.