99 (diucapkan "sembilan puluh sembilan") adalah bahasa pemrograman Esoterik yang sama sekali baru (jangan dikelirukan dengan 99 , catat huruf miring). Tugas Anda dalam tantangan ini adalah menulis penerjemah untuk 99 yang sesingkat mungkin. Kiriman dengan byte paling sedikit menang. Tiebreaker pergi ke kiriman yang diposting terlebih dahulu.
Karena pertanyaan ini sedikit lebih dalam dari biasanya, dan saya ingin sekali melihat jawaban yang bagus, saya akan memberikan hadiah 250 rep untuk jawaban favorit saya (belum tentu pemenangnya).
99 Spesifikasi
99 adalah bahasa yang sangat penting . Setiap baris dalam program 99 adalah pernyataan tunggal , dan selama eksekusi, penunjuk instruksi dimulai di baris paling atas dan melewati setiap baris berikutnya secara berurutan, mengeksekusi mereka di sepanjang jalan. Program berakhir ketika baris terakhir telah dieksekusi. Pernyataan Goto dapat mengubah rute lintasan penunjuk instruksi.
Baris baru, spasi, dan 9
hanya tiga karakter yang penting dalam program 99 . Semua karakter lain sepenuhnya diabaikan. Selain itu, spasi tambahan pada setiap baris diabaikan, dan beberapa spasi dalam satu baris dibaca sebagai satu spasi. ("Baris Baru" mengacu pada penyandian baris istirahat umum apa pun . Tidak masalah yang mana juru bahasa Anda gunakan.)
Jadi program ini:
9 BLAH 99 9a9bb9c9
9 this line and the next have 6 trailing spaces 9
Identik dengan program ini:
9 99 9999
9 9
Variabel
Variabel dalam 99 semuanya memiliki nama yang satu atau lebih 9
dirangkai ( 9+
dalam regex). Sebagai contoh, 9
, 99
, dan 9999999999
semua variabel yang berbeda. Secara alami, ada banyak sekali (pembatasan keterbatasan memori).
Nilai setiap variabel adalah bilangan bulat presisi bertanda tangan yang ditandatangani . Secara default, setiap variabel ditugaskan ke representasi numeriknya sendiri. Jadi, kecuali jika telah dipindahkan, nilai variabel 9
adalah angka 9, dan nilai variabel 99
adalah angka 99, dan seterusnya. Anda bisa menganggapnya sebagai memperlakukan variabel sebagai angka polos sampai mereka ditetapkan secara eksplisit.
Saya akan gunakan V
untuk merujuk pada nama variabel arbitrer di bawah ini.
Setiap contoh V
bisa diganti dengan 9
, 99
, 999
, 9999
, dll
Pernyataan
Ada lima tipe pernyataan berbeda di 99 . Setiap baris dalam program 99 berisi tepat satu pernyataan.
Sintaks yang dijelaskan di sini mengasumsikan semua karakter asing telah dihapus, semua spasi tambahan telah dihapus, dan semua urutan banyak spasi telah diganti dengan spasi tunggal.
1. Tidak Ada Operasi
Baris kosong adalah no-op . Tidak melakukan apa-apa (selain menambah pointer instruksi).
2. Keluaran
V
Variabel tunggal V
pada baris mencetak variabel itu ke stdout.
Jika V
memiliki angka ganjil dari 9
( 9
,, 999
dll.) Maka nilai integer V
dibagi 9 akan dicetak (dalam desimal).
Jika V
memiliki angka genap 9
( 99
,, 9999
dll.) Maka karakter ASCII dengan kode V
dibagi 9, mod 128 akan dicetak. (Itu (V / 9) % 128
, nilai dari 0 hingga 127.)
Contoh : Program
9
9999
akan dicetak 1W
. Baris pertama mencetak 1
karena 9/9 adalah 1. Baris kedua mencetak W
karena 9999/9 adalah 1111, dan 1111 mod 128 adalah 87, dan 87 adalah kode karakter untuk W
.
Perhatikan bahwa jeda baris tidak dicetak di antara token output. \n
perlu dicetak secara eksplisit untuk jeda baris.
3. Input
V
Variabel tunggal V
pada baris dengan spasi terdepan mengambil input dari stdin dan menyimpannya dalam variabel itu.
Jika V
memiliki jumlah ganjil 9
maka pengguna dapat mengetikkan bilangan bulat apa pun yang ditandatangani, dan V
akan disetel ke 9 kali dari nilai itu.
Jika V
memiliki angka genap 9
maka pengguna dapat mengetikkan karakter ASCII apa pun, dan V
akan ditetapkan hingga 9 kali kode karakternya.
Contoh : Diberikan -57
dan A
sebagai input, program ini
9
9
99
99
akan menghasilkan -57A
. Secara internal, variabel 9
akan memiliki nilai -513, dan 99
akan memiliki nilai 585.
Penerjemah Anda dapat mengasumsikan bahwa input selalu valid secara sintaksis.
4. Penugasan
Pernyataan ini bisa lama sewenang-wenang. Ini adalah dua atau lebih variabel pada suatu garis, dipisahkan oleh spasi:
V1 V2 V3 V4 V5 ...
Ini menetapkan jumlah semua dengan indeks genap, dikurangi jumlah dari dengan indeks ganjil (tidak termasuk ). Tugas adalah berdasarkan nilai, bukan dengan referensi.V1
V
V
V1
Ini dapat diterjemahkan dalam sebagian besar bahasa sebagai .V1 = V2 - V3 + V4 - V5 + ...
Jadi, jika hanya ada dua variabel, itu tugas normal:
V1 V2
→ V1 = V2
Jika ada tiga, maka itu pengurangan:
V1 V2 V3
→ V1 = V2 - V3
Dan tanda +
/ -
terus berpindah-pindah dengan setiap variabel tambahan:
V1 V2 V3 V4
→ V1 = V2 - V3 + V4
Contoh : Program ini akan menampilkan 1110123
:
999 Prints triple-nine divided by nine (111).
999 9 9 Assigns triple-nine to zero (nine minus nine).
999 Prints triple-nine divided by nine (0)
9 999 9 Assigns single-nine to negative nine (zero minus nine).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (1).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (2).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (3).
5. Goto (melompat jika semuanya nol)
Pernyataan ini juga bisa panjang sewenang-wenang. Ini adalah dua atau lebih variabel pada garis, dipisahkan oleh spasi, dengan spasi terkemuka :
V1 V2 V3 V4 V5 ...
Jika beberapa nilai selain itu bukan nol, maka ini berlaku seperti no-op. Penunjuk instruksi dipindahkan ke baris berikutnya seperti biasa.V1
Jika semua nilai-nilai selain yang nol, maka instruksi pointer dipindahkan ke baris nomor . Garis-garis diindeks nol, jadi jika nol, maka penunjuk bergerak ke baris atas. Program berakhir (biasanya, tanpa kesalahan) jika negatif atau lebih besar dari indeks tertinggi yang mungkin (jumlah garis minus satu).V1
V1
V1
V1
Catatan yang tidak dibagi dengan 9 di sini. Dan karena tidak mungkin memiliki variabel menjadi nilai yang bukan kelipatan dari 9, hanya nomor baris yang merupakan kelipatan dari 9 yang dapat dilompati.V1
Contoh:
Program ini akan mencetak 1
selamanya:
9 Prints single-nine divided by nine (always 1).
99 9 9 Assigns double-nine to zero.
99 99 Jumps to line zero (top line) if double-nine is zero.
Program ini
99999999 Print G.
999 99 Set triple-nine to ninety-nine.
9999999999 9999999999 9999999999 99 99 9 9 999 999 Set 10-nine to zero.
99999999999 9999999999 Set 11-nine to zero.
999 Print triple-nine's value divided by nine. (This is the ninth line.)
99999999 Print G.
999 999 9 Subtract nine from triple-nine.
99999 999 Jump to line 5-nines if triple-nine is zero (ends program).
9 99999999999 9999999999 Jump to line nine if 10-nine and 11-nine are zero (always jumps).
akan menampilkan angka 11 hingga 1, dalam urutan menurun, dikelilingi oleh G
:
G11G10G9G8G7G6G5G4G3G2G1G
detil tambahan
Interpreter ideal akan dijalankan dari baris perintah dengan nama file program 99 sebagai argumen. I / O juga akan dilakukan dengan cepat di baris perintah.
Anda dapat, bagaimanapun, hanya menulis fungsi juru bahasa yang mengambil dalam program sebagai string serta daftar token input (misalnya ["-57", "A"]
). Fungsi harus mencetak atau mengembalikan string keluaran.
Cara yang sedikit berbeda dalam menjalankan juru bahasa dan menangani I / O baik-baik saja jika opsi ini tidak mungkin dalam bahasa Anda.
Bonus: Tulis sesuatu yang keren di 99 dan saya akan dengan senang hati memasukkannya di posting ini sebagai contoh.
- Berikut adalah Pastebin dari program "99 Bottles of Beer" yang rapi dari jawaban Mac .
Semoga Anda menikmati tantangan ke-99 saya ! : D
sumber
Jawaban:
CJam, 157 byte
Cobalah online:
Penjelasan
Mencoba memformat ini dengan lekukan yang tepat dan komentar mungkin akan berlangsung selamanya, jadi saya hanya akan memberikan ringkasan algoritmik.
Kode ini adalah blok, fungsi analog ke anonim CJam. Blok mengharapkan string program dan daftar input pada stack ketika dieksekusi.
Inisialisasi terdiri dari tiga langkah. Pertama, daftar input disimpan. Kemudian, setiap karakter dalam program yang tidak berarti dihapus dan hasilnya dibagi menjadi daftar baris dan disimpan. Akhirnya, daftar variabel diinisialisasi. Daftar ini memetakan setiap variabel, yang diindeks berdasarkan panjang nama, ke nilainya dibagi dengan 9 (suatu variabel tidak pernah dapat menyimpan nilai yang bukan kelipatan dari 9, dan semua operasi kecuali mendapat manfaat dari perubahan ini). Daftar ini diinisialisasi hingga panjang garis terpanjang, yang merupakan batas atas pada nama terpanjang yang ada sekarang. Ada juga sedikit inisialisasi implisit karena nilai variabel awal: nomor baris adalah 0 dan indeks input -1.
Penerjemah diimplementasikan seperti yang diharapkan: loop yang membaca baris berikutnya, menambah nomor baris, dan mengeksekusi baris sementara nomor baris menunjuk ke baris yang ada. Penguraian baris pertama-tama memeriksa apakah garis tidak kosong, lalu bercabang berdasarkan apakah aritynya 1 atau> 1, kemudian bercabang berdasarkan apakah ada ruang terdepan. Keempat cabang ini meniru empat operasi (tidak termasuk operasi tanpa operasi) dalam cara yang kebanyakan langsung, meskipun golf secara agresif seperti yang lainnya. Mungkin salah satu optimasi dari catatan adalah bahwa, karena urutan input yang valid harus selalu menghasilkan elemen tipe yang diharapkan oleh program, saya dihilangkan membuat kasus terpisah untuk input berdasarkan pada panjang nama variabel. Secara sederhana diasumsikan bahwa elemen yang dibaca dari daftar input adalah tipe yang diharapkan.
sumber
128%
dengan128,=
.Python 3,
421414410404388395401 byteGolf:
Tidak Disatukan:
Cukup banyak implementasi spek literal, bermain sejauh yang saya bisa.
Jalankan dari baris perintah dengan menyediakan file kode sumber 99 sebagai argumen tunggal (mis. Contoh terakhir dari OP):
Sebagai bonus tambahan, inilah penerapan "99 botol" dalam 99 : http://pastebin.com/nczmzkFs
sumber
else
setelah nomor dapat dihapus, tetapi ketika saya mencobanya sebelumnya saya mendapat kesalahan sintaksis. Tips Anda yang lain sangat dihargai!goto
rutin dan ketika mendapatkan nilai default dari variabel). Sejauh menyangkut pengguna bahasa, tidak ada bedanya.else
itu sendiri, hanya ruang sebelumnya. Misalnya3*n+1if n%2else n//2
.else
. Misalnya, saya mencoba menggantiprint(w if L(e)%2 else chr(w%128))
denganprint(w if L(e)%2else chr(w%128))
dan mendapatkan pengecualian sintaks.e
atauE
, dan (dari komentar) tidak untuk0or
keduanya.Common Lisp,
1180857837836 byteSaya tahu ini tidak akan menang, tapi saya senang bermain golf yang satu ini. Saya berhasil menghapus 343 byte, yang lebih dari dua 99 penerjemah ditulis dalam CJam.
Juga, cukup mengherankan, semakin saya mencoba untuk mengompresnya, semakin saya yakin bahwa untuk Common Lisp, lebih pendek untuk mengkompilasi kode daripada mencoba menafsirkannya dengan cepat.
ada satu
tagbody
untuk melakukan 2 loop:variabel lokal dideklarasikan dalam
&aux
Tidak disatukan, berkomentar
Kami menggunakan input / output standar selama evaluasi, artinya kami menggunakan standar
read
danprinc
fungsi. Oleh karena itu, kode yang dihasilkan dapat dieksekusi pada command-line, seperti yang ditunjukkan di bawah ini.Input tidak sepenuhnya disanitasi dengan baik ketika menjalankan 99 program: diasumsikan bahwa pengguna tahu nilai seperti apa yang diharapkan.
Satu-satunya overhead runtime yang mungkin dapat terjadi saat melompat, karena kita harus mengevaluasi nilai variabel dan mencocokkan nilai itu dengan label. Kecuali itu, juru bahasa harus cukup efisien.
Berdasarkan pengamatan cerdas dari Mac bahwa kita tidak perlu membagi dan mengalikan dengan 9 setiap kali, versi saat ini berhasil untuk tidak pernah membagi atau mengalikan dengan 9 selama eksekusi.
Contoh
Jika kita ganti
defmacro
dengandefun
, kita melihat kode yang dihasilkan. Sebagai contoh:Ini kode yang dihasilkan:
Saat dijalankan, cetak "G11G10G9G8G7G6G5G4G3G2G1G"
Garis komando
Kita dapat membangun executable dengan membuang inti dan menentukan
toplevel
fungsi. Tentukan file bernamaboot.lisp
tempat Anda meletakkandefmacro
, dan kemudian tulis yang berikut ini:Menjalankan
sbcl --load boot.lisp
memberikan output berikut:Kemudian, jalankan program yang dikompilasi 99 :
99 botol
Jika Anda tertarik, berikut ini adalah kode kompilasi untuk program 99 botol yang ditulis dalam jawaban Mac : http://pastebin.com/ZXe839CZ (ini adalah versi lama tempat kami memiliki
jmp
danend
memberi label, lambda sekitarnya dan aritmatika yang lebih cantik).Berikut ini adalah eksekusi dengan versi baru, untuk membuktikannya masih berfungsi: http://pastebin.com/raw.php?i=h73q58FN
sumber
TI-84 Basic (Script Kalkulator),
376373377381 byteJika ini berjalan pada kalkulator TI-84, Anda akan dapat menggunakannya pada tes standar ... jadi ini berguna;)
Versi sistem operasi minimum - 2.53MP (MathPrint) karena sigma penjumlahan
Pedoman PS ASCII tidak bisa diikuti dengan tepat, tetapi dalam TI-Basic
:
adalah baris baru. Dengan demikian, semua baris baru aktual dalam kode berarti bahwa:
atau#
pada awal setiap baris tidak diperlukan. Token awal:
dan#
hanya membedakan antara komentar dan kode.Hex Dump Asli (376 Bytes)
Sunting # 1 - Dioptimalkan 3 byte menggunakan observasi Mac. Suntingan # 2 & # 3 - Bug yang diperbaiki ditemukan oleh Runer112.
sumber
#
, untuk komentar? (NB: Komentar dalam kode aktual diimplementasikan sebagai garis dengan hanya string yang tidak tertutup, yang akan membuat Ans)Ans
input ditimpa sehinggaAns->Str0
pada baris 6 akan kesalahan, ada beberapa contoh di mana argumen panjang suatusub()
perintah bisa nol yang menghasilkan kesalahan,Ans
pada baris 11 akan menjadi string jadiAns-J
akan kesalahan ... Dan saya hanya melihat sekitar paruh pertama program.sub()
perintah dapat memiliki panjang nol dan melemparkan kesalahan. Dan begitusub()
doa diperbaiki, saya khawatir itu dapat mengungkapkan lebih banyak masalah.9
adalah angka 9, dan nilai variabelnya99
adalah angka 99, dan seterusnya." Dan string dengan panjang 0 dapat diproduksi dengan cara seperti""
, tapi itu semacam bug yang pada dasarnya tidak ada perintah manipulasi string dapat mengkonsumsi atau menghasilkan string kosong, termasuksub()
.C 426
458 481 497Sunting Mungkin saya melangkah terlalu jauh, tetapi ini bekerja dengan Visual C: dihapus stdio.h, menggunakan int bukan FILE * untuk fopen dan getc
Sunting 2 Susun ulang langkah eksekusi, lebih banyak kekacauan, 32 karakter tersimpan
Program konsol yang berdiri sendiri, nama program yang diambil pada baris perintah dan input / output melalui konsol.
K&R gaya lama, int standar untuk vars dan parameter global. Dengan asumsi EOF didefinisikan sebagai -1 (seperti dalam setiap implementasi C yang saya tahu)
Kompilasi dengan peringatan dengan Visual Studio 2010 (proyek Win32 konsol C ++, kompilasi sebagai C) Kompilasi pada Ideone, tetapi tidak dapat berjalan karena membutuhkan file.
Langkah pertama, kode sumber dibaca dan diuraikan, setiap baris disimpan sebagai urutan bilangan bulat berdasarkan angka 9s. Jika ada spasi awal, angka pertama negatif. Jadi:
9 BLAH 99 9a9bb9c9
(9 99 9999
) menjadi-1,2,4
Ada pintasan - tidak terlalu legal: semua kode ascii yang kurang dari '' dianggap sebagai baris baru.Pada langkah ini semua variabel yang digunakan diinisialisasi.
Langkah eksekusi mengikuti spesifikasi, tanpa embel-embel, menyimpan nomor penyimpanan dibagi dengan 9.
Kode yang sama lebih mudah dibaca (saya harap), spasi dan baris baru ditambahkan
sumber
Haskell, 550 byte
Contoh dijalankan dengan program "hitung mundur" yang disimpan dalam file
i.99
Versi tidak disatukan:
sumber
JavaScript (ES6) 340
352Fungsi dengan 2 parameter
Parameter opsional ketiga (default 10k) adalah jumlah iterasi maksimum - Saya tidak suka program yang berjalan selamanya
JSFiddle Untuk menguji
sumber
q / k,
490469.
Script adalah campuran dari q dan k, jadi pertama-tama saya mendefinisikan beberapa kata kunci q yang ingin saya gunakan beberapa kali dalam fungsi k. (pada dasarnya #define macro)
f
membaca file yang diteruskan ke program dan menghapus karakter yang tidak perlum
mengambil daftar / vektor dan mengalikan indeks ganjil dengan -1b
hanyalah fungsi kosong, digunakan untuk jalur no-opp
adalah fungsi cetak.K
adalah fungsi yang menguji suatu variabel. Jika variabel ada, ia mengembalikannya, jika tidak, ia hanya mengembalikan literal.v
adalah fungsi penugasan.g
adalah fungsi goto.r
mengambil string dan memutuskan operasi mana yang perlu diterapkan.Dan akhirnya, saya hanya mengulang
f
daftar string, dengann
iterator. Fungsi goto akan diperbaruin
sesuai kebutuhan.sumber
Perl,
273 266 255 244238Jeda baris ditambahkan untuk kejelasan.
Nama program diambil pada baris perintah:
Setiap baris program diubah menjadi kode Perl, misalnya:
Keterangan lebih lanjut
sumber