Tantangan ini didasarkan dari pertanyaan Helka Homba , Programming a Pristine World . Dari pertanyaan itu, definisi program murni adalah:
Mari kita mendefinisikan program murni sebagai program yang tidak memiliki kesalahan itu sendiri tetapi akan kesalahan jika Anda memodifikasinya dengan menghapus substring N karakter yang berdekatan, di mana
1 <= N < program length
.Misalnya, program tiga karakter Python 2
`8`
adalah program murni ( terima kasih, Sp ) karena semua program yang dihasilkan dari menghapus substring dengan panjang 1 menyebabkan kesalahan (kesalahan sintaks sebenarnya, tetapi semua jenis kesalahan akan dilakukan):
8` `` `8
dan juga semua program yang dihasilkan dari menghapus substring panjang 2 menyebabkan kesalahan:
` `
Jika, misalnya,
`8
telah menjadi program non- kesalahan maka`8`
tidak akan murni karena semua hasil penghapusan substring harus kesalahan.Catatan:
- Peringatan kompiler tidak dihitung sebagai kesalahan.
- Subprogram yang error dapat mengambil input atau memberikan output atau melakukan hal lain selama mereka melakukan kesalahan tidak peduli apa akhirnya.
Tugas Anda adalah membuat program yang panjangnya tidak nol yang mencetak kode sumbernya sendiri dengan tepat, mengikuti aturan untuk quine yang tepat , dan masih asli.
Jawaban terpendek dalam byte untuk setiap bahasa menang.
Jawaban:
Haskell , 132 byte
Cobalah online!
Ini adalah perpanjangan dari quine
yang bekerja dengan menggabungkan string data dengan versi yang dikutip (dengan menggunakan
show
) dari dirinya sendiri dan mencetak hasilnya. Namun, ini bukan murni karena karakter apa pun dalam string data dapat dihapus tanpa gagal dan juga bagian$(++)<*>show$
atau(++)<*>
dapat dihapus tanpa melanggar program.Untuk memperbaikinya, fungsi cetak khusus
q
didefinisikan yang memeriksa panjang string yang diberikan dan memanggilfail
jika lebih pendek dari 132. Ini menangkap penghapusan urutan apa pun dari string data dan juga penghapusan$(++)<*>show$
atau(++)<*>
, seperti dalam kedua kasus yang dihasilkan string yang diteruskan keq
lebih pendek.Di
q
nomor132
dapat disingkat menjadi1
,13
,32
atau2
, tetapi dalam setiap kasus lagifail
disebut.Sejauh yang saya tahu, penghapusan substring lainnya menyebabkan kesalahan sintaks atau tipe, sehingga program bahkan tidak dapat dikompilasi. (Sistem tipe ketat Haskell sangat berguna di sini.)
Sunting: Terima kasih kepada Ørjan Johansen dan Shelvacu karena menunjukkan kekurangan!
sumber
fail[]|length x/=122
bisa dihapus.fail[]:[putStr x|length x==122]
mungkin bekerja lebih baik.|length x==122
bisa dihilangkan.if length x==122 then putStr x else fail[]
mungkin?if then else
sebelumnya tapi saya pikir saya bisa mempersingkatnya.putStr x
dapat menjadip x
, yang ketika saya mencoba pada sistem saya berjalan untuk waktu yang sangat lama sebelum saya membunuhnya, saya curiga rekursi panggilan ekor dioptimalkan, jadi itu adalah loop tak terbatas. Saya tidak cukup tahu haskell untuk memberikan saran tentang cara memperbaikinya.p
menjadiq
harus memperbaikinya.Python 3 , 113 byte
Cobalah online!
Bagaimana itu bekerja
Kami tidak dapat dengan mudah menggunakan banyak pernyataan karena yang kedua dapat dihapus, jadi kami mulai dengan quine ekspresi tunggal:
Untuk melindunginya dari penghapusan substring, kami menggunakan
open(1,"w").write
sebagai gantiprint
. Dalam Python 3,write
mengembalikan jumlah karakter tertulis, yang akan kami verifikasi adalah113
untuk memastikan bahwa tidak ada bagian dari string yang dihapus. Kami melakukan ini dengan mencari nilai kembali dalam kamus{113:[]}
, dan mengulang hasilnyafor[]in…:a
, yang akan gagal jika kami tidak mendapatkan iterable kosong atau jikafor
pernyataan dihapus.sumber
Ruby, 78 byte
Saya menulis ini ketika saya memikirkan tantangan untuk memastikan itu mungkin. Ia menggunakan "pembungkus" yang sama dari salah satu jawaban saya untuk tantangan asli yang asli.
Penjelasan:
eval(*[
expr])
Ini mengevaluasi kode apa pun yang dikembalikan sebagai program ruby. Ini secara efektif menguji bahwa string yang dikembalikan kode adalah program ruby yang valid. Mudah, program ruby bisa kosong, atau hanya terdiri dari spasi putih.
Operator "percikan"
*
memungkinkan Anda menggunakan array sebagai argumen untuk suatu fungsi. Ini juga berarti bahwa jikaeval
dihapus, program yang dihasilkan adalah(*[
expr])
, yang bukan ruby yang valid.($>.write(
str)-78).chr
$>
adalah variabel pendek untuk STDOUT.$>.write(foo)
menulis foo ke STDOUT dan, yang penting untuk kode ini, mengembalikan jumlah byte yang ditulis.$>.write(foo)-78
: Berikut78
adalah panjang program, dan jika program tidak hancur, juga akan menjadi jumlah byte yang ditulis. Karenanya, dalam kasus tanpa cacat, ini akan mengembalikan nol.num.chr
mengembalikan num sebagai karakter, misalnya0.chr
akan mengembalikan string yang berisi byte nol tunggal. Dalam program tidak cacat, ini akan memberikan string dengan byte nol tunggal keeval
, yang merupakan program ruby yang valid yang merupakan no-op.Selain itu, program dapat menghilangkan substring sedemikian rupa sehingga hanya
eval(*[(78).chr])
ataueval(*[(8).chr])
, yang berarti konstanta numerik tidak dapat diakhiri dengan angka apa pun (0, 4, 9, 10, 11, 12, 13, 26, 32, 35, 48 , 49, 50, 51, 52, 53, 54, 55, 56, 57, 59, 64, 95) karena merupakan kode ascii untuk program ruby karakter tunggal yang valid.%{
str}
Ini adalah sintaks yang kurang dikenal untuk string literal di ruby. Alasan itu digunakan di sini adalah bahwa pasangan seimbang
{}
dapat digunakan dalam string, yang berarti sintaks ini dapat mengandung dirinya sendiri. Misalnya,%{foo{bar}}
sama dengan"foo{bar}"
.(s=%{
data})%s
Ini mendefinisikan variabel
s
yang merupakan data quine ini, sebagai string printf.Tugas dalam ruby mengembalikan apa yang ditugaskan, jadi ini sama dengan penugasan pertama
s
dan kemudian berjalans%s
%
pada string adalah gula sintaksis untuk setara dengan ruby dari sprintf. Itu%s
menandakan di mana dalam data data itu sendiri harus tertanam.Bit kode ini mendefinisikan bagian data quine dan menyematkannya untuk membuat kode lengkap.
sumber
Standar ML (MLton) ,
204182189 byteCobalah online!
Untuk MLton, program SML lengkap adalah ekspresi dibatasi dan diakhiri oleh
;
(misalnyaprint"Hello";print"World";
) atau deklarasi denganvar
danfun
kata kunci (misalnyavar _=print"Hello"var _=print"World"
) di mana_
kartu liar yang juga dapat diganti dengan nama variabel apa pun.Opsi pertama tidak berguna untuk pemrograman murni karena
;
dengan sendirinya adalah program yang valid (yang tidak melakukan apa-apa, tetapi tidak salah juga). Masalah dengan pendekatan kedua adalah bahwa deklarasi sepertivar _=print"Hello"
dapat disingkat menjadi hanyavar _="Hello"
(atau bahkanvar _=print
) karena deklarasi denganvar
karya selama sisi kanan adalah ekspresi atau nilai SML yang valid (SML adalah bahasa fungsional, sehingga fungsi dapat digunakan sebagai nilai juga).Pada titik ini, saya siap untuk menyatakan pemrograman asli di SML tidak mungkin, ketika kebetulan saya menemukan pencocokan pola di
val
-deklarasi. Ternyata sintaks untuk deklarasi tidakval <variable_name> = <expression>
tetapival <pattern> = <expression>
, di mana pola dapat terdiri dari nama variabel, konstanta dan konstruktor. Karenaprint
fungsi memiliki tipestring -> unit
, kita bisa menggunakan pola pertandingan diunit
-nilai()
untuk menegakkan bahwa fungsi cetak benar-benar diterapkan ke string:val()=print"Hey"
. Dengan pendekatan ini, menghapus salah satuprint
atau"Hey"
menghasilkanPattern and expression disagree
-tindakan.Dengan cara ini mencetak murni, langkah selanjutnya adalah menulis quine, sebelum akhirnya beberapa penjaga perlu ditambahkan. Saya sebelumnya menggunakan teknik quine SML yang mudah (lihat sejarah revisi ), tetapi Anders Kaseorg menunjukkan pendekatan yang berbeda yang dapat menghemat beberapa byte dalam kasusnya. Menggunakan built-in
String.toString
fungsi bawaan untuk menangani pelolosan string dan merupakan bentuk umum<code>"<data>"
, di mana"<data>"
adalah string pelolosan daricode
sebelumnya:Ini adalah quine yang berfungsi tetapi belum asli. Pertama-tama Anders Kaseorg mengetahui bahwa MLton menerima satu kutipan
"
sebagai kode tanpa menghasilkan kesalahan, yang berarti kita tidak dapat memiliki kode yang diakhiri dengan penawaran seperti di atas. Cara terpendek untuk mencegah hal ini adalah dengan membungkus semuanya setelahval()=
dalam tanda kurung, namun kemudian kode dapat dikurangi menjadival()=()
. Cara terpendek kedua yang saya temukan adalah menggunakanval()=hd[ ... ]
, yaitu kita membungkus semuanya menjadi daftar dan mengembalikan elemen pertamanya untuk membuat pemeriksa tipe senang.Untuk memastikan bahwa tidak ada bagian dari string data yang dapat dihapus tanpa diketahui, pencocokan pola di
val
-deklarasikan berguna lagi: Panjang string terakhir yang akan dicetak (dan dengan demikian panjang program) harus sama dengan 195, jadi kita bisa menulislet val t=... val 195=size t in print t end
di badanfn
abstraksi bukanprint(...)
. Menghapus bagian dari string menghasilkan panjang kurang dari 189, sehingga menyebabkanBind
pengecualian dilemparkan.Masih ada masalah yang tersisa: seluruh
val 195=size t
pemeriksaan bisa dibatalkan. Kami dapat mencegah hal ini dengan memperluas cek agar sesuai dengan tuple:,val t=... val(216,u)=(n+size t,t)in print u end
sehingga menghapus hasil cek dalam variabel tidak terikatu
.Secara keseluruhan, ini menghasilkan solusi 195 byte berikut:
Menerapkan trik golf menggunakan nama variabel operator seperti
!
,$
dan%
bukannyan
,t
danu
untuk menghemat ruang putih (lihat tip ini ) mengarah ke versi 182 byte terakhir.Semua pemindahan substring lainnya yang tidak secara eksplisit dinyatakan dalam penjelasan harus menghasilkan sintaks atau tipe kesalahan.
Sunting 1:
length(explode t)
adilsize t
.Sunting 2: Terima kasih kepada Anders Kaseorg untuk pendekatan quine yang berbeda dan menunjukkan "kerentanan".
sumber
"\""
secara langsung dan menggunakanString.toString
untuk melarikan diri."
, menghasilkan output kosong ( TIO ).let ... in ... end
."
sebagai program, dan sepertinya bug telah diperbaiki dalam komit ini , jadi mungkin 182 atau 180 saya baik-baik saja selama Anda menentukan versi Git yang belum dirilis dari MLton.