Tulis Program Yang Menghasilkan Tingkat Cerminnya

31

Ada 95 karakter ASCII yang dapat dicetak :

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Dalam font Consolas (default kode blok Stack Exchange), beberapa karakter memiliki mirror di sekitar sumbu simetri vertikal:

  • Pasangan karakter ini adalah cerminan satu sama lain: () [] {} <> /\
  • Karakter-karakter ini adalah cermin dari dirinya sendiri: ! "'*+-.8:=AHIMOTUVWXY^_ovwx|(Perhatikan bahwa ruang adalah satu.)
  • Ini tidak memiliki cermin: #$%&,012345679;?@BCDEFGJKLNPQRSZ`abcdefghijklmnpqrstuyz~

( i, l, 0, #, Dan mungkin karakter lain adalah cermin mereka sendiri dalam beberapa font tapi kami akan tetap berpegang pada bentuk Consolas.)

Sebuah string dikatakan sebagai cermin dari dirinya sendiri jika dibuat hanya dengan 39 karakter cermin , disusun sedemikian rupa sehingga string tersebut memiliki garis simetri vertikal tengah. Begitu ](A--A)[juga cermin dari dirinya sendiri tetapi ](A--A(]tidak.

Tulis program satu garis panjang rata yang merupakan cerminan dari dirinya sendiri. Ketika N salinan bagian kirinya telah ditambahkan sebelumnya dan N salinan bagian kanannya telah ditambahkan padanya, ia akan menghasilkan N + 1. N adalah bilangan bulat non-negatif.

Misalnya, jika programnya adalah ](A--A)[(setengah kiri:, setengah ](A-kanan:) -A)[, maka:

  • Menjalankan ](A--A)[harus menampilkan 1. (N = 0)
  • Menjalankan ](A-](A--A)[-A)[harus menampilkan 2. (N = 1)
  • Menjalankan ](A-](A-](A--A)[-A)[-A)[harus menampilkan 3. (N = 2)
  • Menjalankan ](A-](A-](A-](A--A)[-A)[-A)[-A)[harus menampilkan 4. (N = 3)
  • . . .
  • Menjalankan ](A-](A-](A-](A-](A-](A-](A-](A-](A-](A--A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[harus menampilkan 10. (N = 9)
  • dll.

Aturan

  • Output ke stdout atau alternatif terdekat bahasa Anda. Mungkin ada trailing newline opsional. Tidak ada input yang harus diambil.
  • Secara teori proses ini harus bekerja untuk N hingga 2 15 -1 atau lebih, mengingat memori dan daya komputasi yang cukup.
  • Diperlukan program lengkap, bukan hanya perintah REPL .

Program awal terpendek (N = 0 case) dalam bytes menang.

Hobi Calvin
sumber
Dalam beberapa font, #adalah relection sendiri juga, tetapi, Anda benar, bukan di konsol.
SuperJedi224
1
Menggunakan replika diizinkan? Dengan kata lain: haruskah kita menulis program lengkap yang valid atau ekspresi sudah cukup? Saya berpikir tentang entri Haskell yang akan bekerja ketika berjalan dalam ghci tetapi bukan program lengkap yang valid.
Bakuriu
@ Bakuriu Diperlukan program lengkap. Jawaban Haskell tidak valid.
Calvin Hobbies
4
Mengapa cermin 'b' dan 'd' tidak dari satu sama lain? Itu membuat rencana saya tidak mungkin: P
Thijs ter Haar
1
@ ThijsterHaar Saya sebenarnya tidak mempertimbangkan hal itu tetapi sepertinya bentuk Consolas mereka hanya sedikit berbeda, maaf: P
Calvin Hobbies

Jawaban:

20

Pip, 12 8 4 byte

Sekarang dengan 66% lebih sedikit byte!

x++x
  • xadalah variabel, diinisialisasi ke "". Dalam konteks numerik, ini menjadi 0.
  • Babak pertama, tanpa final +, membuat ekspresi bentuk x+x+...+x. Ini adalah pernyataan yang valid yang tidak melakukan apa-apa.
  • Babak kedua, termasuk final +dari babak pertama, membuat ekspresi bentuk ++x+x+...+x. ++xbertahap xuntuk 1, dan sisanya menambahkan ke itu sendiri N kali. Karena ekspresi dievaluasi dari kiri ke kanan di Pip, peningkatan dijamin terjadi terlebih dahulu, dan hasilnya sama dengan jumlah tingkat cermin.
  • Pada akhirnya, nilai ekspresi ini dicetak otomatis.

Sayangnya, Pip tidak memproses dengan baik ekspresi besar: solusi ini menyebabkan maximum recursion depth exceededkesalahan untuk N di atas 500 atau lebih. Inilah solusi sebelumnya yang tidak, untuk 8 byte :

x++oo++x

Lebih lanjut tentang Pip

DLosc
sumber
OK, kecuali seseorang mengirim jawaban 2 byte, sepertinya Anda punya yang ini di dalam tas. Ngomong-ngomong, saya tidak tahu apakah Anda sudah menjalankannya dengan N = 32767 , tetapi output sebenarnya Fatal error: maximum recursion depth exceeded while calling a Python object.
Dennis
@ Dennis Ya, saya benar-benar bertemu - itu dimulai cukup awal, sekitar 600 jika tidak sebelumnya. Alasannya adalah bahwa ekspresi dievaluasi dengan mengevaluasi semua subekspresi secara rekursif terlebih dahulu, sehingga x+x+...+xmenghasilkan kedalaman rekursi O (N). Mungkin itu membatalkan jawaban ini. Saya akan menambahkan catatan.
DLosc
Batas rekursi mudah disesuaikan dengan Python, bukan?
Dennis
@ Dennis Ya, meskipun ada peringatan mengerikan tentang apa yang akan dilakukannya pada sistem Anda jika Anda mengaturnya terlalu tinggi, jadi saya belum pernah mencobanya. ;) Selain itu, mengonfigurasi itu tidak mungkin dari dalam Pip , jadi sepertinya agak curang kepada saya. Jika Anda ingin mencobanya, saya akan tertarik mendengar hasilnya.
DLosc
Saya sudah mencoba. Di mesin saya, meningkatkan batas rekursi menjadi 20000 sudah segfault. Tetapi karena jawabannya harus bekerja hanya dengan memori dan daya komputasi yang cukup , itu seharusnya tidak menjadi masalah.
Dennis
34

GolfScript, 10 byte

!:{)::(}:!

Cobalah online dengan Web Golfscript: N = 0 , N = 1 , N = 2 , N = 3 , N = 41

Web GolfScript memiliki batas 1024 karakter, tetapi interpreter Ruby menangani N = 32767 dengan sempurna:

$ curl -Ss http://www.golfscript.com/golfscript/golfscript.rb > golfscript.rb
$ echo '"!:{):"32768*":(}:!"32768*' | ruby golfscript.rb > mirror-level-32767.gs
$ ruby golfscript.rb mirror-level-32767.gs
32768

Bagaimana itu bekerja

Tanpa input apa pun, GolfScript awalnya memiliki string kosong di tumpukan.

Di babak kiri pertama, berikut ini terjadi:

  • !berlaku TIDAK logis untuk string kosong. Ini mendorong 1.

  • :{menyimpan integer pada stack dalam variabel {.

    Ya, itu adalah pengidentifikasi yang valid, meskipun tidak ada cara untuk mengambil nilai yang disimpan.

  • ) menambah bilangan bulat pada tumpukan.

  • : adalah instruksi yang tidak lengkap.

Bagian kiri berikutnya, yang berikut terjadi:

  • :!(Di mana :adalah sisa dari sebelumnya) menyimpan integer pada stack dalam variabel !.

    Ya, itu juga merupakan pengidentifikasi yang valid. Ini melanggar !perintah, tapi kami tidak menggunakannya lagi.

  • :{, )dan :bekerja seperti sebelumnya.

Di babak kanan pertama, berikut ini terjadi:

  • ::(Di mana :adalah sisa dari sebelumnya) menyimpan integer pada stack dalam variabel :.

    Ya, bahkan itu adalah pengidentifikasi yang valid. Seperti halnya {, tidak ada cara untuk mengambil nilai yang disimpan.

  • ( mengurangi integer pada stack, menghasilkan jumlah belahan kiri.

  • }, karena tidak cocok dan mengakhiri eksekusi segera.

    Ini adalah fitur tidak berdokumen. Saya menyebutnya supercomments .

Kode yang tersisa diabaikan begitu saja.

Dennis
sumber
Tampaknya sangat aneh memiliki }kode yang tidak tertandingi di paruh ke-2 Anda dalam kompetisi mirror.
ballesta25
Ini adalah trik umum dalam varian palindrome. Dalam "\""/", kuotasi ganda keempat tidak akan tertandingi juga karena yang kedua telah lolos.
Dennis
27

Kode Mesin Z80, 8 6 byte *

<8ww8> * Mengasumsikan kondisi tertentu dengan memasukkan dari Amstrad BASIC

<   INC A         // A=A+1
8w  JR C, #77     ## C is unset unless A has overflowed, does nothing

w   LD (HL), A    // Saves A to memory location in HL (randomly initialised)
8>  JR C, #3E     ## C is still unset, does nothing

Aawalnya 0 ketika dimasukkan dari BASIC. Ini menambah A n kali, lalu menulisnya n kali ke lokasi memori yang sama (yang diatur ke lokasi yang sedikit acak oleh BASIC)! Operasi JRJump Relative tidak pernah melakukan apa-apa karena Cflag selalu tidak disetel, sehingga digunakan untuk "mengomentari" byte berikut! Versi ini sedikit curang dengan mengasumsikan kondisi entri tertentu, yaitu masuk dari jaminan BASIC yang Aselalu 0. Lokasi (HL)tidak dijamin aman, dan mungkin merupakan lokasi berbahaya. Kode di bawah ini jauh lebih kuat dan karena itu jauh lebih lama.

Kode Mesin Z80, 30 byte

Sebagai ASCII: o!.ww.!>A=o>{))((}<o=A<!.ww.!o

Pada dasarnya, babak pertama menjamin penciptaan nilai nol dan babak kedua menambahkannya dan menulisnya ke memori. Dalam versi yang diperluas di bawah ini ##menunjukkan kode yang tidak memiliki tujuan di bagian cerminnya.

o   LD L, A       ## 
!.w LD HL, #772E  // Load specific address to not corrupt random memory!
w   LD (HL), A    ## Save random contents of A to memory
.!  LD L, #21     ## 
>A  LD A, #41     // A=#41
=   DEC A         // A=#40
o   LD L, A       // L=#40
>{  LD A, #7B     ## 
)   ADD HL, HL    // HL=#EE80
)   ADD HL, HL    // HL=#DD00. L=#00 at this point

((  JR Z, #28     ## 
}   LD A, L       // A=L
<   INC A         // A=L+1
o   LD L, A       // L=L+1
=   DEC A         // A=L
A   LD B, C       ## 
<   INC A         // A=L+1
!.w LD HL, #772E  // Load address back into HL
w   LD (HL), A    // Save contents of A to memory
.!  LD L, #21     ## 
o   LD L, A       // L=A

Rincian instruksi yang diizinkan:

n   op    description
--  ----  -----------
28  LD    LoaD 8-bit or 16-bit register
3   DEC   DECrement 8-bit or 16-bit register
1   INC   INCrement 8-bit or 16-bit register
1   ADD   ADD 8-bit or 16-bit register

Available but useless instructions:
3   JR    Jump Relative to signed 8-bit offset
1   DAA   Decimal Adjust Accumulator (treats the A register as two decimal digits
          instead of two hexadecimal digits and adjusts it if necessary)
1   CPL   1s ComPLement A
1   HALT  HALT the CPU until an interrupt is received

Dari 39 instruksi yang diizinkan, 28 adalah operasi pemuatan (blok dari 0x40 hingga 0x7F adalah semua LDinstruksi byte tunggal ), yang sebagian besar tidak membantu di sini! Satu-satunya instruksi memuat ke memori masih diperbolehkan adalah LD (HL), Ayang berarti saya harus menyimpan nilai A. Karena Ahanya register yang tersisa dengan INCinstruksi yang diizinkan, ini sebenarnya cukup berguna!

Saya tidak dapat memuat Adengan 0x00 untuk memulainya karena ASCII 0x00 bukan karakter yang diizinkan! Semua nilai yang tersedia jauh dari 0 dan semua instruksi matematika dan logis telah dianulir! Kecuali ... saya masih bisa melakukannya ADD HL, HL, tambahkan 16-bit HLke dirinya sendiri! Terlepas dari memuat nilai secara langsung (tidak digunakan di sini!), Menambah Adan Menurunkan A, Latau HLini adalah satu-satunya cara saya mengubah nilai register! Sebenarnya ada satu instruksi khusus yang bisa membantu di babak pertama tetapi menyusahkan untuk mengerjakan di babak kedua, dan instruksi satu-pelengkap yang hampir tidak berguna di sini dan hanya akan mengambil ruang.

Jadi, saya menemukan nilai terdekat dengan 0 saya bisa: 0x41. Bagaimana itu mendekati 0? Dalam biner itu 0x01000001. Jadi saya mengurangi, memuatnya Ldan melakukan ADD HL, HLdua kali! Lsekarang nol, yang saya masukkan kembali ke A! Sayangnya, kode ASCII untuk ADD HL, HLini )sehingga saya sekarang harus menggunakan (dua kali. Untungnya, (ini JR Z, e, di mana eadalah byte berikutnya. Jadi itu memakan byte kedua dan saya hanya perlu memastikan itu tidak melakukan apa-apa dengan berhati-hati dengan Zbendera! Instruksi terakhir untuk mempengaruhi Zflag adalah DEC A(kontra-intuitif, ADD HL, HLtidak mengubahnya) dan karena saya tahu Aitu 0x40 pada saat itu dijamin Ztidak diatur.

Instruksi pertama di babak kedua JR Z, #28tidak akan melakukan apa-apa 255 kali pertama karena bendera Z hanya dapat diatur jika A telah meluap dari 255 ke 0. Setelah itu output akan salah, namun karena itu hanya menyimpan nilai 8-bit tetap saja bahwa seharusnya tidak masalah. Kode tidak boleh diperluas lebih dari 255 kali.

Kode harus dieksekusi sebagai potongan karena semua cara yang tersedia untuk kembali dengan bersih telah dianulir. Semua instruksi RETurn di atas 0x80 dan beberapa operasi Jump diizinkan hanya dapat melompat ke offset positif, karena semua nilai negatif 8-bit telah dianulir juga!

CJ Dennis
sumber
6
APA. APA INI.
cloudfeet
4
Sekarang saya sudah melihat jawaban ini, menggunakan GolfScript / J / etc. sepertinya curang. : p
cloudfeet
Apakah ada prosesor yang kompatibel dengan Z80 dengan register 16-bit A? Saya bertanya karena pertanyaannya memerlukan kode harus bekerja untuk N = 32767 .
Dennis
1
@ Dennis Agar suatu program dapat bekerja untuk N = 32767 , panjangnya harus minimal 2 x 32767 atau 65534 byte. Z80 hanya dapat mengatasi memori 65536 byte, menjadikan ini tugas yang mustahil karena saya tidak percaya saya bisa membuat program lebih kecil dari 6 byte! The Amendaftar selalu 8 bit, jika prosesor tidak akan kompatibel dengan Z80. Saya akan mengatakan bahwa memori yang diberikan cukup dan daya komputasi telah ditutup di sini!
CJ Dennis
1
@ Dennis Anda mengerti mengapa tidak ada prosesor yang kompatibel dengan Z80 akan memiliki Aregister selain 8 bit? Mengubahnya menjadi 16-bit akan memecah kode mengandalkan 255 + 1 = 0 misalnya. Anda harus menciptakan CPU, sebut saja Z160, yang menggunakan register 16-bit default tetapi masih menggunakan instruksi 8-bit yang sama dari Z80. Aneh!
CJ Dennis
19

J, 16 14 byte

(_=_)]++[(_=_)

Penggunaan:

   (_=_)]++[(_=_)
1
   (_=_)]+(_=_)]++[(_=_)+[(_=_)
2
   (_=_)]+(_=_)]+(_=_)]++[(_=_)+[(_=_)+[(_=_)
3

Penjelasan:

  • J mengevaluasi dari kanan ke kiri.

  • (_=_)adalah inf equals infyang benar, memiliki nilai 1, sehingga ungkapan menjadi 1+]...[+1. ( (8=8)juga berfungsi tetapi ini terlihat lebih keren. :))

  • [dan ]kembalikan argumen kiri dan kanan mereka masing-masing jika ada 2 argumen. Jika hanya mendapat 1, mereka mengembalikannya.

  • +menambahkan 2 argumen. Jika hanya mendapat 1, mengembalikannya.

Sekarang mari kita evaluasi ekspresi level 3 (dari kanan ke kiri):

(_=_)]+(_=_)]++[(_=_)+[(_=_)  NB. (_=_) is 1

1]+1]+1]++[1+[1+[1  NB. unary [, binary +

1]+1]+1]++[1+[2  NB. unary [, binary +

1]+1]+1]++[3  NB. unary [, unary +

1]+1]+1]+3  NB. unary +, binary ]

1]+1]+3  NB. unary +, binary ]

1]+3  NB. unary +, binary ]

3

Seperti yang kita lihat separuh kanan 1ditambahkan dan sisi kiri 1dihapus yang menghasilkan bilangan bulat yang diinginkan N, tingkat cermin.

Cobalah online di sini.

randomra
sumber
12

Haskell, 42 byte

(8-8)-(-(8-8)^(8-8))--((8-8)^(8-8)-)-(8-8)

Untungnya komentar baris di Haskell (-> --) dapat dicerminkan dan setengahnya (-> -) adalah fungsi yang valid. Sisanya adalah beberapa matematika untuk mendapatkan angka 0dan 1. Pada dasarnya kami memiliki (0)-(-1)dengan komentar untuk N=0dan prepend (0)-(-1)-dalam setiap langkah.

Jika angka floating point diizinkan untuk diproduksi, kita dapat membangun 1dari 8/8dan bertahan dengan 26 byte:

Haskell, 26 byte

(8-8)-(-8/8)--(8\8-)-(8-8)

Output 1.0, 2.0dll

nimi
sumber
2
Secara teknis ini tidak valid karena harus berupa program lengkap.
Hobi Calvin
@ CalvinHobbies: Begitu ya. Apakah kita memiliki konsensus tentang persyaratan minimum untuk program penuh? Saya telah mencari meta, tetapi hanya menemukan diskusi tentang fungsi, bukan program. Tergantung pada definisi program lengkap saya mungkin dapat memperbaiki solusi saya.
nimi
Saya akan menyebutnya program lengkap jika Anda dapat menyimpannya dalam file program.hsdan kemudian jalankan $ runhaskell program.hsdari baris perintah dan lihat hasilnya. Saya tidak tahu Haskell jadi saya tidak bisa mengatakan dengan tepat apa yang perlu diubah.
Hobi Calvin
2
@ Calvin'sHobbies: runhaskelladalah skrip shell yang mengatur beberapa lingkungan dan akhirnya memanggil ghc, kompilator Haskell. Anda dapat menjalankan kode saya langsung dengan ghc: ghc -e "(8-8)-(-8/8)--(8\8-)-(8-8)". Peluncuran ini ghcyang mengevaluasi kode yang disediakan sebagai argumen, mencetak hasil dan keluar. Tidak ada REPL, tidak ada interaksi. Tentu saja ini akan menambahkan +1 ke jumlah byte -e.
nimi
@nimi: -etidak berkontribusi pada skor dalam kasus ini. Kami tidak menghitung byte perl -Eatau gcc -std=c99salah satunya.
Dennis
11

CJam, 14 byte

]X+:+OooO+:+X[

Cobalah online di juru bahasa CJam: N = 0 , N = 1 , N = 2 , N = 3 , N = 41

Perhatikan bahwa kode ini selesai dengan pesan kesalahan. Menggunakan penerjemah Java, pesan kesalahan itu dapat ditekan dengan menutup atau mengarahkan STDERR. 1

Bagaimana itu bekerja

Di bagian kiri, berikut ini terjadi:

  • ] membungkus seluruh tumpukan dalam sebuah array.

  • Xditambahkan 1ke array itu.

  • :+ menghitung jumlah semua elemen array.

  • Oo mencetak isi array kosong (mis., tidak ada).

Di babak kanan pertama, berikut ini terjadi:

  • o mencetak bilangan bulat pada tumpukan, yang merupakan output yang diinginkan.

  • O+ mencoba untuk menambahkan array kosong ke item paling atas dari tumpukan.

    Namun, tumpukan itu kosong sebelum mendorong O. Ini gagal dan menghentikan eksekusi program.

Kode yang tersisa diabaikan begitu saja.

1 Menurut jajak pendapat meta Haruskah pengajuan diizinkan untuk keluar dengan kesalahan? , ini diizinkan.

Dennis
sumber
Saya akan skeptis menerima ini karena kesalahan, tapi karena tidak menang, saya tidak terlalu khawatir.
Hobi Calvin
Tugas seperti ini sangat sulit di CJam, mengingat itu adalah bahasa golf. Bahkan kesalahan sintaksis (misalnya, operator yang tidak ditentukan) di blok yang tidak dieksekusi akan mencegah seluruh program dari mengeksekusi. Saya masih berusaha untuk menyingkirkan kesalahan.
Dennis