Prindeal (diucapkan prin-dee-al ) adalah bahasa pemrograman esoterik baru yang hanya memiliki empat perintah: pr int , in crement , de crement , dan al ias . Meskipun minimalis, operasi matematika yang kompleks dapat dilakukan di Prindeal dengan menggabungkan empat perintah secara cerdik.
Tugas Anda dalam tantangan golf kode ini adalah menulis program terpendek yang dapat menjalankan kode Prindeal.
Speknya panjang tapi saya sudah mencoba membuatnya sejelas mungkin dan saya percaya bahwa jika Anda berusaha untuk belajar Prindeal Anda akan menemukannya cukup elegan!
Intrepreting Prindeal
Preprocessing
Sebelum sebuah program Prindeal dapat diartikan hal-hal ini perlu dihapus darinya dalam urutan ini:
- Apa pun setelah
#
tanda ke ujung garis itu aktif, ditambah tanda#
itu sendiri. (Ini adalah komentar.) - Membuntuti spasi putih pada baris apa pun.
- Baris benar-benar kosong.
Misalnya, program Prindeal
p cat #The next line has 7 trailing spaces.
p dog
#p mouse
akan diolah menjadi
p cat
p dog
Dari sini kita akan menganggap langkah preprocessing ini telah dilakukan.
Variabel
Kita dengan cepat perlu mendefinisikan variabel sebelum menunjukkan bagaimana mereka digunakan.
Variabel (dan referensi ke variabel) adalah apa yang diteruskan ke argumen perintah Prindeal. Variabel selalu bersifat global , jadi modifikasi terhadap suatu variabel, di mana pun mereka terjadi, tercermin di mana-mana.
Setiap variabel memiliki integer presisi arbitrer non-negatif (0, 1, 2, 3, ...). Variabel tidak perlu diinisialisasi - mereka selalu mulai dengan nilai 0 saat pertama kali mereka digunakan atau dipanggil.
Nama variabel dapat berupa string alfanumerik dan garis bawah non-kosong yang tidak dimulai dengan digit - [a-zA-Z_][0-9a-zA-Z_]*
dalam regex . Mereka peka huruf besar-kecil, jadi spiny_lumpsuck3r
dan Spiny_lumpsuck3r
merupakan variabel yang berbeda.
Eksekusi
Prindeal adalah bahasa pemrograman yang sangat penting . Ketika program Prindeal dijalankan, pernyataannya dieksekusi dari atas ke bawah secara berurutan dan kemudian program berakhir.
Setiap baris non-indentasi dalam program Prindeal adalah pernyataan yang melibatkan eksekusi satu perintah yang mungkin atau tidak dapat mengambil argumen.
Baris indentasi hanya muncul setelah perintah alias . Secara khusus, tepat tiga baris yang ditandai dengan spasi tunggal muncul setelah setiap perintah alias dan dianggap sebagai bagian darinya. Jadi pernyataan alias benar-benar panjang empat baris. (Mereka bisa menjadi satu baris, empat hanya lebih mudah dibaca.)
Pernyataan Non- alias
Dengan pengecualian alias , setiap pernyataan dalam program Prindeal memiliki formulir:
[command name] [argument 1] [argument 2] [argument 3] ...
Mungkin ada sejumlah argumen sewenang-wenang (termasuk tidak ada sama sekali). Setiap argumen selalu merupakan variabel atau (seperti yang akan kita lihat ketika membahas alias ) referensi ke variabel .
Setelah selesai dieksekusi, setiap pernyataan ditandai sebagai kegagalan atau keberhasilan tergantung pada apakah kesalahan ditemukan atau tidak. (Ini hanya masalah ketika kita menggunakan alias .)
Cetak built-in , increment , dan decrement adalah pernyataan dengan formulir di atas. Inilah yang mereka lakukan:
print memiliki nama perintah
p
dan mengambil satu argumen. Ini mencetak nama variabel yang diteruskan dan nilainya (dalam desimal) dipisahkan oleh "=", lalu baris baru. Itu selalu ditandai sebagai keberhasilan .Misalnya, program Prindeal
p _MyVariable_321 p screaming_hairy_armadillo
akan menghasilkan
_MyVariable_321 = 0 screaming_hairy_armadillo = 0
karena semua variabel mulai dari 0. (Spasi sebelum dan sesudah tanda sama dengan diperlukan.)
increment memiliki nama perintah
i
dan mengambil satu argumen. Itu menambah nilai variabel yang dilewatkan oleh 1. Itu selalu ditandai sebagai sukses ..Misalnya saja programnya
i alpaca p alpaca i alpaca p alpaca
akan menghasilkan
alpaca = 1 alpaca = 2
Perhatikan bagaimana
alpaca
peningkatan dari 0 menjadi 1 meskipun belum pernah diakses sebelumnya.decrement memiliki nama perintah
d
dan mengambil satu argumen. Jika variabel yang diteruskan adalah nol, nilainya dikurangi dengan 1 dan pernyataan ditandai sebagai sukses . Jika variabel yang dikirimkan adalah 0 maka tidak ada yang dilakukan dan pernyataan ditandai sebagai kegagalan .Misalnya saja programnya
i malamute p malamute d malamute #success p malamute d malamute #failure p malamute d akita #failure p akita
akan menghasilkan
malamute = 1 malamute = 0 malamute = 0 akita = 0
Perhatikan bahwa pengurangan variabel dengan nilai 0 adalah satu-satunya cara untuk menghasilkan kegagalan .
The alias Pernyataan dan Alias Perintah
The alias perintah memiliki sintaks khusus dan adalah yang paling kuat karena dapat digunakan untuk menentukan perintah baru. Nama perintah alias adalah a
dan pernyataan alias memiliki bentuk:
a [name of new command]
[statement A]
[statement B]
[statement C]
Dimana masing-masing [statement X]
mewakili pernyataan non- alias , yaitu sesuatu dengan formulir [command name] [argument 1] [argument 2] [argument 3] ...
.
Nama perintah alias [name of new command]
mungkin berupa string alfanumerik dan garis bawah yang tidak kosong yang tidak dimulai dengan digit - [a-zA-Z_][0-9a-zA-Z_]*
dalam regex.
(Ini adalah kumpulan nama yang sama dengan variabel tetapi perintah dan variabel yang berbeda adalah hal yang berbeda yang digunakan di tempat yang berbeda . Suatu variabel dapat dinamai sama sebagai perintah tanpa konsekuensi buruk.)
Ketika pernyataan alias dijalankan, perintah baru ditambahkan di samping empat p
i
d
a
perintah asli. Perintah baru dapat digunakan sebagai [command name]
pernyataan dalam dan dipanggil dengan argumen seperti halnya perintah non- alias lainnya .
Ketika pernyataan dengan nama perintah alias dijalankan, tepat dua pernyataan lagi dari pernyataan alias aslinya dijalankan:
[statement A]
selalu dijalankan[statement B]
Dijalankan jika[statement A]
sudah sukses[statement C]
dijalankan jika[statement A]
sebuah kegagalan
Pernyataan A, B, dan C selalu dijalankan dengan malas , yaitu mereka dievaluasi dengan cepat pada saat dijalankan.
Ketika selesai dieksekusi, perintah alias ditandai dengan flag sukses atau gagal yang sama dengan pernyataan B atau C, mana pun yang dieksekusi . ( alias pernyataan itu sendiri tidak perlu ditandai karena tidak dapat muncul di dalam dirinya sendiri.)
Contoh Alias 1
Katakanlah kita menginginkan perintah baru yang menambah variabel
frog
dua kali. Pernyataan alias ini membuatnya:a increment_frog_twice i frog i frog d frog
Pernyataan A (
i frog
) selalu dijalankan dan selalu ditandai sebagai keberhasilan sehingga pernyataan B (i frog
) juga selalu dijalankan dan variabelnyafrog
bertambah dengan 2.increment_frog_twice
Perintah selalu ditandai sebagai keberhasilan karena pernyataan B selalu dijalankan dan B selalu merupakan sukses . Pernyataan C (d frog
) tidak pernah dijalankan.Jadi output untuk
a increment_frog_twice i frog i frog d frog p frog increment_frog_twice p frog
akan menjadi
frog = 0 frog = 2
Kita dapat menggeneralisasi contoh ini sehingga variabel apa pun dapat ditambahkan dua kali dengan memberikan perintah alias argumen.
Dalam pernyataan alias , bilangan bulat positif 1, 2, 3, dll. Mewakili argumen 1, 2, 3, dll. Diteruskan ke perintah alias. (Argumen ini mungkin variabel biasa atau referensi ke variabel itu sendiri.) Angka-angka ini hanya dapat muncul dalam argumen pernyataan A, B, dan C dalam pernyataan alias . Tidak masuk akal bagi mereka untuk muncul di tempat lain.
Contoh Alias 2
Ini menggeneralisasi contoh terakhir - variabel apa pun yang dilewatkan
increment_twice
akan ditambahkan oleh 2 karena1
merupakan referensi ke argumen pertama yang dilewatkan dalam:a increment_twice i 1 i 1 d 1 #never reached p toad increment_twice toad p toad
Output dari program ini adalah
toad = 0 toad = 2
Kami kemudian dapat alias perintah lain yang mengambil dua argumen dan memanggil
increment_twice
keduanya:a increment_twice i 1 i 1 d 1 #never reached a increment_both_twice increment_twice 1 increment_twice 2 d 1 #never reached increment_both_twice platypus duck p platypus p duck
Outputnya di sini adalah
platypus = 2 duck = 2
Sangat penting untuk menyadari bahwa perintah alias dapat bersifat rekursif, karena di sinilah letak kekuatan mereka yang sebenarnya. Sebagai contoh, kita dapat membuat perintah yang menetapkan variabel apa pun yang diteruskan ke 0:
Contoh Alias 3
The
set_to_zero
perintah mengambil satu argumen dan menetapkan variabel untuk 0 dan ditandai sebagai keberhasilan bila dilakukan:a set_to_zero d 1 set_to_zero 1 i _dummy_ i oryx i oryx i oryx p oryx set_to_zero oryx p oryx
Output dari program ini adalah
oryx = 3 oryx = 0
Apa yang terjadi adalah ketika
set_to_zero oryx
dijalankan,d 1
berhasil mengurangioryx
dari 3 ke 2, kemudianset_to_zero 1
dipanggil, yang sama dengan meneleponset_to_zero oryx
lagi. Jadi mengulangi proses sampaid 1
adalah kegagalan , menghentikan rekursi dan kenaikan_dummy_
variabel sehingga sukses diproduksi.
Tantangan
Tulis program yang dapat menjalankan kode Prindeal persis seperti yang dijelaskan di atas. Ambil kode Prindeal melalui stdin, baris perintah, atau sebagai file teks. Cetak output program Prindeal ke stdout atau alternatif terdekat bahasa Anda.
Atau, Anda dapat menulis fungsi yang mengambil kode sebagai string dan mencetak atau mengembalikan string output.
Selain itu, Anda dapat mengasumsikan bahwa:
- Kode Prindeal input hanya akan berisi baris baru dan ASCII yang dapat dicetak dan (secara opsional) berakhir dengan baris kosong.
- Kode input akan valid Prindeal - terbentuk dengan baik dan secara sintaksis benar.
- Menjalankan kode tidak akan menghasilkan loop tak terbatas atau referensi yang tidak valid untuk perintah yang belum didefinisikan atau argumen yang belum diberikan.
- Nama perintah
p
,i
,d
, dana
tidak akan pernah alias lebih. (Anda mungkin tidak berasumsi bahwa variabel tidak akan memiliki nama-nama ini.)
Juga, tidak masalah jika nilai variabel Anda tidak benar-benar bilangan bulat presisi arbitrer karena hanya angka kurang dari sekitar 1000 yang akan diuji. Tidak masalah jika bahasa Anda memiliki batas rekursi (seperti Python ) yang mungkin dihadapi oleh program Prindeal yang lebih kompleks selama program pengujian di bawah ini berfungsi.
Program Tes
Berikut ini adalah program Prindeal besar yang membangun operasi penambahan, perkalian, dan eksponensial melalui penggunaan variabel dummy (dimulai dengan _
konvensi) dan banyak alias penolong:
#Command Definitions:
a s #flag as a success
i _
d _
d _
a f #flag as a failure
d _
d _
d _
a z #1 = zero
d 1
z 1
s
a n #1 = one
z 1
i 1
s
a move #2 += 1, 1 = zero
moveH 1 2
move 1 2
s
a moveH #move helper
d 1
i 2
f
a dupe #2 += 1, 3 += 1, 1 = zero
dupeH1 1 2 3
dupe 1 2 3
s
a dupeH1 #dupe helper
d 1
dupeH2 2 3
f
a dupeH2 #dupe helper
i 1
i 2
s
a copy #2 = 1
z 2
copyH 1 2
s
a copyH #copy helper
dupe 1 2 _copy
move _copy 1
s
a addTo #1 += 2
copy 2 _add
#testing comments #
move _add 1#in weird places # just because #
s
#it's a g##d idea
###
a add #1 = 2 + 3
#its a good idea
z 1
addH 1 2 3
s
##
#
a addH #add helper
#this is a comment
addTo 1 2 #as is this
addTo 1 3
s
a mul #1 = 2 * 3
mulH1 1 2
mulH2 1 3
s
a mulH1 #mul helper
z 1
copy 2 _mul
s
a mulH2 #mul helper
mulH3 1 2
mulH2 1 2
s
a mulH3 #mul helper
d _mul
addTo 1 2
f
a mulBy #1 *= 2
mul _mulBy 1 2
copy _mulBy 1
s
a pow #1 = 2^3
powH1 1 3
powH2 1 2
s
a powH1 #pow helper
n 1
copy 2 _pow
s
a powH2 #pow helper
powH3 1 2
powH2 1 2
s
a powH3 #pow helper
d _pow
mulBy 1 2
f
#Running Tests:
p A
p B
p C
n A #A = 1
n B #B = 1
add C A B #C = A + B = 1 + 1 = 2
p ____
p A
p B
p C
add B A C #B = A + C = 1 + 2 = 3
p ____
p A
p B
p C
mul d B C #d = B * C = 3 * 2 = 6
p ____
p d
mulBy d B #d = d * B = 6 * 3 = 18
p ____
p d
d A #A = A - 1 = 1 - 1 = 0
mulBy d A #d = d * A = 18 * 0 = 0
p ____
p d
pow A C B #A = C ^ B = 2 ^ 3 = 8
p ____
p A
p B
p C
pow A B C #A = B ^ C = 3 ^ 2 = 9
p ____
p A
p B
p C
pow C A B #C = A ^ B = 9 ^ 3 = 729
p ____
p A
p B
p C
(Jika Anda bermain-main dengan kode ini, sadarilah bahwa banyak perintah akan gagal jika variabel yang sama diberikan beberapa kali sebagai argumen. Ini dapat dengan mudah diperbaiki tetapi kode yang dihasilkan lebih panjang.)
Penerjemah Prindeal Anda harus dapat menghasilkan output yang tepat:
A = 0
B = 0
C = 0
____ = 0
A = 1
B = 1
C = 2
____ = 0
A = 1
B = 3
C = 2
____ = 0
d = 6
____ = 0
d = 18
____ = 0
d = 0
____ = 0
A = 8
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 729
Mencetak gol
Kode terpendek dalam byte menang. Tiebreak pergi ke pengiriman sebelumnya.
Brownie Bonus: Tulis program keren di Prindeal. Saya menerapkan penambahan dan perkalian, bisakah Anda melakukan pengurangan atau pembagian?
sumber
p
, lalup p
, mana yang akan mencetak 1, kan?Jawaban:
Pyth,
162136 byteDemonstrasi.
Golf 26 karakter dengan inlining variabel dan berubah dari
I
danE
berdasarkan aliran kontrol ke?
dan.x
berdasarkan aliran kontrol.Untuk pertama kalinya, saya kehabisan variabel dalam Pyth. Setiap variabel tunggal dalam Pyth (
bdkGHNTY
danJK
) sedang digunakan, dan saya ingin menggunakanb
sebagai baris baru. Secara luar biasa, saya dapat menggunakanN
untuk mengartikan dua hal yang sama sekali berbeda di berbagai bagian program, dan masih berfungsi.Tidak disatukan (dijalankan dengan -m):
sumber
Python 2,
600584397373 byteIni adalah solusi referensi golf saya sendiri. Siapa pun boleh memperbaikinya atau mengikuti logikanya dalam jawaban mereka sendiri asalkan diberikan atribusi.
Bagian yang rapi tentang hal itu adalah bahwa tidak ada rekursi yang dilakukan, sehingga tidak akan pernah memiliki masalah dengan batas rekursi Python. Misalnya, Sp ini Program Countup Prindeal dapat berjalan tanpa batas.
Ini adalah program yang mengambil dalam string dikutip Program dengan baris baru lolos, misalnya
'p _MyVariable_321\np screaming_hairy_armadillo'
.Saya mengambil berbagai isyarat golf dari jawaban Sp dan Pietu . Terima kasih teman-teman :)
sumber
Python 3,
345336335328 byte(-6 byte terima kasih kepada @orlp)
Masih bermain golf. Menganggap program disimpan dalam file bernama
P
.Menempatkan panggilan ke
f
dalam lambdad
akan menghemat beberapa byte, tetapi itu akan membuat test case terakhir mencapai kedalaman rekursi maksimal.Beberapa program Prindeal
Program pengurangan yang tidak berguna
Ini adalah program pengurangan yang tidak berguna . Tidak ada gunanya karena, meskipun dikurangi dengan benar, itu tidak mengembalikan keberhasilan / kegagalan yang sesuai.
Outputnya harus:
Countup
Hitung ke atas dan cetak
n
selamanya. Mungkin bisa berfungsi sebagai tes untuk kecepatan juru bahasa (berhati-hatilah pada traceback yang panjang pada keyboard interrupt).sumber
l[:(l+"#").find("#")]
dan semua variasinya bisa diganti dengan yang sederhanal.split('#')[0]
.find
yang saya lupa Anda bisasplit
bahkan jika#
s tidak ada di sana. Terima kasih :)JavaScript (ES6), 273
258Edit bug yang diperbaiki dan menambahkan paket uji nyata.
Tidak termasuk spasi dan baris baru.
Tentunya bisa bermain golf lebih sedikit.
Terlalu lelah untuk menulis penjelasan sekarang, saya pikir itu adalah contoh yang baik menggunakan penutupan untuk mempertahankan nilai sementara (parameter).
Tes menjalankan cuplikan pada peramban apa pun yang mendukung EcmaScript 6 (terutama bukan Chrome, bukan MSIE. Saya menguji pada Firefox, Safari 9 dapat berjalan)
sumber
C # 6, 653 byte
Inilah entri saya, di tengah lautan Python ...
Diperluas dan dikomentari:
Untuk menggunakannya, cukup instantiate kelas dan panggil
R()
metode, misalnya:sumber
Gangguan umum,
758646619Masukkan ini
file.lisp
dan panggil misalnyasbcl --script file.lisp
; input dibaca dari aliran input standar.Versi ini mem-parsing superset dari Prindeal: tanpa banyak kesulitan, Anda dapat mengakses semua Common Lisp dari sumber Prindeal. Saya menganggap ini sebagai fitur dari intepreter.
Versi yang dikomentari
Contoh
Jika kita ganti
eval
denganprint
di loop baca / eval, maka kita dapat melihat apa yang sedang dievaluasi:Ekspansi makro
Jika kita memilih definisi alias berikut:
... kita bisa melihat referensi ke variabel bernama
g
yang tidak ditemukan dalam lingkup leksikal. Tetapi setelah ekspansi makro, berikut adalah kode aktual yang sedang dievaluasi:Sekarang,
g
merujuk ke daftar argumen fungsi yang sedang didefinisikan.sumber
Python 2, 486 byte
Ini adalah solusi referensi yang saya golf lebih banyak (saat ini -98 byte).
Perubahan (yang saya ingat):
[l,l[:l.find('#')]]['#'in l]
).V[k]=-~V[k]if k in V else 1
)k=s[1]
)print
secara otomatis menambahkan spasi (print k,'=',V.get(k,0)
)'0'<t[0]<':'
)r
sekitar untuk menyimpanreturn
smap(str.split,c[:3]))
)sumber
Python 3, 1322 byte
Golf:
Tidak Disatukan:
Pemakaian:
Di mana
c
isi teksnya.Contoh:
String baris tunggal diterima:
P("p cat")
P("p dog\ni dog\np dog")
String multi-baris juga diterima:
Atau:
Dll
Catatan:
Ini berfungsi dengan benar untuk semua kasus uji, tetapi mencapai batas rekursi pada:
Karena itu
sys.setrecursionlimit(2000)
.sumber
Python -
695688 byte<TAB>
adalah karakter tab literal.sumber
C ++, 1111 bytes
Yang ini adalah C ++ - sebodoh yang saya bisa lakukan.
Itu berarti membuatnya lebih C ++ - ish dan lebih sedikit C-ish.
Itu juga berarti lebih besar dari program C yang setara.
Saya pikir C ++ saingan Java untuk perpustakaan standar verbose.
Ini mengkompilasi dengan VS2013 dan g ++ 4.9.2 (dengan -std = c ++ 11)
Di bawah ini adalah yang asli. Jika ada yang bisa memikirkan cara untuk membuatnya lebih idiomatis dan lebih pendek pada saat yang bersamaan tolong beri tahu saya.
sumber
Haskell, 1009
Saya melakukan yang terbaik untuk golf itu; kode ungolfed saya terdiri dari lebih dari 3.000 karakter. Pada titik ini saya tidak dapat mengingat apa yang dilakukan semua fungsi sehingga bermain golf lebih berarti menebak apa yang akan merusaknya dan apa yang tidak.
sumber