Generator Quine Umum


19

Tantangan

Dalam tantangan ini, Anda menentukan bahasa sumber S dan bahasa target T . Tugas Anda adalah menulis program berikut Pdalam bahasa ini S. Jika program yang valid Qdalam bahasa Tdiberikan sebagai input P, itu akan menampilkan program yang valid Rdalam bahasa Tyang tidak memerlukan input dan output Q(R), yaitu, program yang Qditerapkan pada kode sumber R. Selain itu , Anda harus mempresentasikan dalam jawaban Anda program contoh nontrivial Q(semakin menarik, semakin baik, meskipun Anda tidak mendapat poin untuk ini), program yang dihasilkan R, dan output dari R. Ini kode-golf, jadi kode terpendek untuk Pmenang.

Dengan kata lain, ini adalah tantangan tentang menulis "konstruktor quine universal" yang dapat membuat jenis quines umum yang sewenang-wenang.

Klarifikasi

  • Sumber dan bahasa target Anda mungkin identik.
  • Program Pharus mengambil satu string sebagai input (dari STDIN atau yang setara), dan output satu string (ke STDOUT atau setara), sebagaimana seharusnya setiap program output R.
  • Program input Qjuga harus mengubah string menjadi string lain, tetapi bentuknya lebih fleksibel: mereka dapat berupa fungsi string-ke-string, potongan kode yang memodifikasi variabel dengan nama tertentu, potongan yang memodifikasi tumpukan data jika bahasa target Anda memiliki satu, dll. Anda juga dapat membatasi lebih jauh bentuk Qdengan menyatakan bahwa, misalnya, mereka mungkin tidak mengandung komentar apa pun. Namun, Anda harus dapat mengimplementasikan fungsi string-ke-string yang dapat dikomputasi sebagai program input Q, dan Anda harus secara eksplisit menyatakan bagaimana mereka berfungsi dan kendala apa lagi yang Anda tempatkan pada mereka.
  • Program keluaran Rharus benar-benar quine (digeneralisasi), jadi ia tidak boleh membaca input apa pun (input pengguna, file, dll.) Kecuali Qmelakukannya.
  • Celah standar tidak diijinkan.

Sebuah contoh

Misalkan saya memilih Python sebagai bahasa sumber saya, dan Haskell sebagai bahasa target saya, dan saya selanjutnya mengharuskan program input harus definisi satu-baris dari suatu String -> Stringfungsi bernama f. Jika saya memberikan program string-reversing

f x = reverse x

sebagai input ke program Python saya P, itu akan menampilkan kode sumber program Haskell lain R. Program ini mencetak untuk STDOUT kode sumber R, tetapi dibalik. Jika Pdiberikan fungsi identitas

f x = x

sebagai input, program output Radalah quine.

Jawaban:


7

Sumber = Target = CJam, 19 17 16 byte

{`"_~"+}`)q\"_~"

Ini mengasumsikan bahwa program input Q(diberikan pada STDIN) adalah beberapa potongan CJam yang mengharapkan string di atas tumpukan dan meninggalkan string lain di atas tumpukan.

Uji di sini.

Contohnya

  1. Identitas hanya akan menjadi potongan kosong, sehingga meninggalkan cetakan kosong STDIN

    {`"_~"+}_~
    

    Yang merupakan standar quine, dengan tambahan +.

  2. Untuk membalikkan string dalam CJam, Anda dapat menggunakan W%, jadi dengan meletakkannya di STDIN, ini menghasilkan:

    {`"_~"+W%}_~
    

    yang bisa kita jalankan untuk mendapatkan

    ~_}%W+"~_"`{
    
  3. Sebagai contoh ketiga, mengatakan kami menggunakan cuplikan yang menyelingi string dengan spasi: ' *. Berjalan Pdengan itu sebagai input, kita dapatkan

    {`"_~"+' *}_~
    

    yang pada gilirannya mencetak

    { ` " _ ~ " + '   * } _ ~  
    
  4. Sekarang juga berfungsi jika Qberisi jeda baris (meskipun itu tidak pernah diperlukan dalam CJam). Berikut ini adalah program dengan penghentian baris, yang menghapus semua penghentian baris dari suatu string (dengan cara berbelit-belit yang tidak perlu - dipisah menjadi beberapa baris, lalu bergabung):

    N/
    ""
    *
    

    Ini menghasilkan sebagai berikut R:

    {`"_~"+N/
    ""
    *}_~
    

    yang pada gilirannya mencetak

    {`"_~"+N/""*}_~
    

Penjelasan

Mari kita lihat output yang dihasilkan terlebih dahulu:

Quine CJam standar adalah

{`"_~"}_~

Ia bekerja sebagai berikut:

  • Dorong blok {`"_~"}.
  • Gandakan dengan _.
  • Jalankan salinan dengan ~.
  • Sekarang di dalam blok, `mengubah blok pertama menjadi representasi string-nya.
  • "_~" mendorong dua karakter dari sumber yang bukan bagian dari blok (dan karenanya hilang dari representasi string).
  • Dua string dicetak kembali ke belakang di akhir program.

Dalam quine dasar `itu tidak perlu, karena jika Anda hanya meninggalkan blok apa adanya, itu dicetak semua sama di akhir program.

Output dari program saya Padalah versi modifikasi dari cuplikan ini. Pertama, saya telah menambahkan a +ke blok, yang menggabungkan dua string menjadi satu string yang berisi seluruh sumber. Perhatikan bahwa ini akan benar apa pun yang saya lakukan di dalam blok, karena itu semua akan ditambahkan ke representasi string yang diperoleh `. Sekarang saya cukup meletakkan program / snippet Qdi dalam blok setelah +, sehingga dapat memodifikasi string sumber sebelum dicetak. Sekali lagi, karena Qmasuk ke dalam blok, itu akan menjadi bagian dari string sumber tersebut.

Singkatnya, Pcetak

{`"_~"+Q}_~

Sekarang, untuk bagaimana saya membangun output ini di P:

{`"_~"+}         "Push the block without Q.";
        `        "Turn it into a string. This is shorter than writing a string right away,
                  because I'd have to escape the quotes, and I'd need two quotes instead of
                  one backtick.";
         )       "Pop off the last character (the brace) and push it on the stack.";
          q      "Read input Q.";
           \     "Swap Q with the brace.";
            "_~" "Push the final two characters.";

Keempat string dicetak secara otomatis (back-to-back) di akhir program.


1
Yah, ini cepat! Dan tentu saja sulit dikalahkan. Penjelasannya juga bagus.
Zgarb

Di mana Anda mengetahui bahwa W% terbalik? dl.dropboxusercontent.com/u/15495351/cjam.pdf tidak memilikinya
Faraz Masroor

Apakah ada daftar metode yang lebih lengkap?
Faraz Masroor

@FarazMasroor sourceforge.net/p/cjam/wiki/Basic%20operators/#percent (no. 3) ... ini adalah fitur yang dipinjam dari GolfScript dan pada titik tertentu seseorang mengatakan kepada saya bahwa itulah cara kerjanya di GolfScript. Tampaknya idiom yang umum bahwa itu adalah pengetahuan implisit aneh setiap pengguna CJam / GS tetapi yang sebenarnya tidak dijelaskan di banyak tempat. (Untuk lebih lanjut, operator yang tidak terdokumentasi dengan baik, lihat sourceforge.net/p/cjam/wiki/Operators )
Martin Ender

3

Ekspresi Haskell → Ekspresi Haskell, 41 byte

((++)<*>show).('(':).(++")$(++)<*>show$")

Cobalah online!

Bagaimana itu bekerja

P $ "Q"= ((++)<*>show).('(':).(++")$(++)<*>show$") $ "Q"dibangun "R"oleh

  1. (++")$(++)<*>show$"): menambahkan string ")$(++)<*>show$",
  2. ('(':): mengawali karakter '(', dan
  3. (++)<*>show(= \x->x++show x): menambahkan versi yang dikutip itu,

menghasilkan "R"= "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\"".

R= (Q)$(++)<*>show$"(Q)$(++)<*>show$"bekerja oleh

  1. mengambil tali "(Q)$(++)<*>show$",
  2. (++)<*>show: menambahkan versi yang dikutip itu,
  3. berlaku Quntuk itu,

menghasilkan Q "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\""= Q "R".

(Paren di sekitarnya Qdiperlukan karena Qmungkin mengandung $semudah seperti Ritu, dan $sayangnya asosiatif benar.)

Demo

λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "id"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ (id)$(++)<*>show$"(id)$(++)<*>show$"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "reverse"
(reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
λ> putStrLn $ (reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
"$wohs>*<)++($)esrever("$wohs>*<)++($)esrever(
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "length"
(length)$(++)<*>show$"(length)$(++)<*>show$"
λ> print $ (length)$(++)<*>show$"(length)$(++)<*>show$"
44

Tidak hanya $membutuhkan tanda kurung, tetapi juga trailing let, doatau ekspresi lambda.
Ørjan Johansen

@ ØrjanJohansen Benar, tapi saya bisa mendefinisikan subset bahasa yang melarang lambda yang tidak di-unmisial / let/ if/ case/ dojika saya tidak memancarkannya sendiri. Mungkin sebaiknya aku tidak harus melakukannya.
Anders Kaseorg

2

Sumber = Target = JavaScript, 66

console.log("function a(){console.log("+prompt()+"(a+'a()'))}a()")

Asumsi untuk Q:

  • Q harus berupa fungsi anonim JavaScript string-to-string.

Contoh:

  • Membalikkan . Q =function(s) { return s.split('').reverse().join(''); }

Dalam hal ini, P(Q)(atau R) akan menjadi function a(){console.log(function(s) { return s.split('').reverse().join(''); }(a+'a()'))}a():, dan dengan menjalankannya, kita akan mendapatkan: )(a}))')(a'+a(} ;)''(nioj.)(esrever.)''(tilps.s nruter { )s(noitcnuf(gol.elosnoc{)(a noitcnufyang persis sama denganQ(R) .

  • Identitas . Q =function(s) { return s; }

dalam hal ini, P(Q)(atau R) akan menjadi: function a(){console.log(function(s) { return s; }(a+'a()'))}a()yang merupakan JavaScript Quine . Tidak perlu dikatakan, Q(R)akan sama, karena Q adalah fungsi Identitas.


Beberapa catatan:

STDIN dalam JavaScript secara tradisional prompt(), namun, saya membiarkan diri saya menahan diri dari tradisi alert()sebagai STDOUT, untuk membuat proses menjalankan output sebagai program menggunakan copy-paste lebih mudah. (Saya sadar bahwa saya dapat menyimpan hingga 12 karakter saat mengubah ke alert()).

Saya juga dapat membuat segalanya jauh lebih pendek di ES6, tetapi saya ingin tetap menggunakan JavaScript Asli untuk saat ini. Saya sedang mempertimbangkan mengirimkan jawaban S = Scala, T = ECMA6 di masa depan, hanya untuk pengalaman.

Saya juga menyadari bahwa JavaScript hampir tidak pernah bisa mengalahkan CJam dalam , tetapi saya harus menerima tantangan ini! Itu masam yang menyenangkan.


Terima kasih! Memang akan keren memiliki entri dengan sumber dan bahasa target yang berbeda.
Zgarb

2

Jeli7 , 9 byte

“ṚƓ^ṾṂ’³3

Cobalah online!

Q adalah fungsi 7 (yaitu yang tidak melihat di luar elemen stack atas, dan apakah I / O melalui stack), dan diberikan sebagai argumen baris perintah.

Penjelasan

Program 7

Konstruktor quine universal di 7 yang saya gunakan di sini adalah:

717162234430…3

Hal pertama yang perlu diperhatikan adalah bahwa leading 7 sama dengan leading whitespace, dan tidak berpengaruh pada program. Satu-satunya alasan ada di sana adalah untuk mematuhi aturan PPCG terhadap quine literal-only (ini dikodekan oleh yang kedua 1dalam program daripada dirinya sendiri).

Sisa dari program ini adalah elemen tumpukan tunggal (memiliki keseimbangan 7s dan 6s), yang melakukan hal berikut saat dijalankan:

717162234430…3
 1716           Push a stack element "7" onto the stack
     2          Copy it
      23        Pop and output one of the copies (selecting format 7)
        4430    Prepend it to the top of stack
             3  Output it

Dengan kata lain, elemen tumpukan ini adalah program yang mencetak bagian atas tumpukan, dengan 7prepended, dalam format output 7 (yang berarti "mencetak secara harfiah, menggunakan pengkodean yang sama dengan kode sumber", dan dengan demikian jelas merupakan pengkodean terbaik untuk quines). Cukup beruntung di sini bahwa kita dapat menggunakan kembali literal 7untuk dua tujuan (format output, dan spasi putih terkemuka). Jelas, dengan memasukkan sesuatu sebelum final 3, kita dapat menampilkan fungsi 7+ input, daripada hanya memproduksi 7dan masukan secara langsung.

Bagaimana elemen tumpukan ini mendapatkan kode sumbernya sendiri? Nah, ketika akhir program tercapai, 7 evals elemen tumpukan atas secara default. Namun, itu sebenarnya tidak muncul dari tumpukan dalam proses, sehingga elemen tumpukan literal yang evaldipimpin masih ada. (Dengan kata lain, program ini tidak membaca sumbernya sendiri - sebagaimana dibuktikan oleh fakta bahwa ia tidak dapat melihat 7pada awal program, yang merupakan pemisah elemen tumpukan daripada bagian dari literal - melainkan, itu sebagian besar terdiri dari literal yang evaldipimpin secara default.)

Program Jelly

Ini mungkin salah satu dari program Jelly yang paling mirip Jelly yang pernah saya tulis; itu terdiri dari tiga nilads ( “ṚƓ^ṾṂ’, ³, 3), yang hanya output dalam urutan karena tidak ada operasi dilakukan pada mereka. The 3cukup jelas, hanya menjadi integer konstan. Ini ³juga sederhana jika Anda tahu Jelly: itu notasi eksplisit Jelly untuk argumen baris perintah pertama (yang mana Jelly biasanya mengambil inputnya). Sisa dari program Jelly mewakili sebagian besar 7 konstruktor quine universal saya: dengan mengeksploitasi fakta bahwa semua perintah dalam 7 dapat direpresentasikan menggunakan digit ASCII, kita dapat menafsirkan717162234430bukan sebagai serangkaian perintah, atau bahkan sebagai angka oktal (seperti itu secara konseptual), tetapi sebagai angka desimal, yang berarti bahwa kita tidak memerlukan format khusus untuk output. Angka desimal itu menjadi “ṚƓ^ṾṂ’dalam notasi bilangan bulat terkompresi Jelly.

Contoh

Jika kami berikan 24053sebagai program Q, kami akan mendapatkan hasil sebagai berikut:

717162234430240533

Cobalah online!

2405 menggabungkan elemen tumpukan atas untuk dirinya sendiri:

2405   Stack   Explanation
       x
2      x|x     Duplicate top of stack
 4     x||x    Swap two stack elements, with an empty element between
  0    x|(X)   Escape the top stack element, then concatenate the top two
   5   xx      Execute the top stack element

(Langkah terakhir mungkin terlihat sedikit membingungkan; apa yang terjadi adalah keluar dari elemen stack mengubah setiap perintah di dalamnya dari "jalankan perintah ini" menjadi "tambahkan perintah ini ke atas tumpukan", sehingga setiap perintah menambahkan sendiri ke aslinya elemen tumpukan atas saat dijalankan.)

Dengan demikian, menjalankan program yang dihasilkan R memberi kita dua salinan R:

7171622344302405371716223443024053

2

CJam → CJam, 13 byte

{`"_~"+7}_~qt

Cobalah online!

Input Qharus berupa potongan kode yang memodifikasi satu-satunya string dalam tumpukan. Qdibaca dari stdin.

Contoh

Memasukkan:

S*W%

Ini menambahkan ruang antara setiap dua karakter, dan membalikkan string.

Keluaran:

{`"_~"+S*W%}_~

Output dari quine umum:

~ _ } % W * S + " ~ _ " ` {

Penjelasan

{`"_~"+7}_~      e# Evaluate a generalized quine in CJam that only appends a 7.
q                e# Read the input.
t                e# Replace the 7th character (0-based) with the input.

Pertama-tama mengevaluasi quine, jadi kita bisa mendapatkan representasi string-nya tanpa tanda kutip ganda yang tidak perlu. Kemudian ganti muatan dengan input.

Bisa jadi di {`"_~"+ }_~7qtmana ruang adalah tempat penampung muatan. Tetapi mengubah payload untuk 7menghemat satu byte.


1

ArangPerl (5), 29 33 byte

A$_=q(αA);evalβαS"\α$_β\n";printβ

Cobalah online!

Program Perl Q harus mengembalikan potongan yang mengambil input sebagai string ke sisi kanannya dan memberikan output dalam variabel $_. (Fungsi Perl sewenang-wenang dapat dikonversi ke formulir ini melalui membungkusnya sebagai sub x {…}; $_=x. Namun dalam kebanyakan kasus, sintaksis Perl berarti tidak diperlukan pembungkus.)

Penjelasan

Perl

Beginilah bentuk konstruktor universal qu quine:

$_=q(…"\$_=q($_);eval";print);eval

(Dalam kebanyakan kasus Anda ingin golf turun ini $_=q(say…"\$_=q($_);eval");eval, tapi saya tidak yakin Anda dapat memasukkan kode Perl sewenang-wenang ke sana.)

Dengan kata lain, kami memiliki pembungkus luar $_=q(…);evalyang memberikan string ke $_dan kemudian mengevaluasinya. Di dalam bungkus adalah "\$_=q($_);eval", yaitu rekonstruksi bungkus bersama dengan isinya melalui menggunakan nilai yang kami simpan $_, ditambah kode Q yang ditentukan oleh pengguna, ditambah printuntuk mencetak output. (Sayangnya kami tidak dapat menggunakan say; itu menambah baris baru, dan itu relevan dalam quines.)

Arang

"Titik" dari jawaban ini adalah untuk menghasilkan quines yang digeneralisasi di Perl, jadi setelah saya memiliki strategi bermain golf untuk melakukan itu (yang saya gunakan dalam banyak jawaban lain), sudah waktunya untuk menulis program P, yang pada dasarnya hanya menggantikan string ke dalam templat. Apa yang saya inginkan di sini adalah bahasa yang bagus untuk mencetak string konstan (idealnya mengompresnya sedikit), dan memasukkan input pengguna ke dalamnya.

Setelah mencoba beberapa, saya memilih Charcoal, yang belum pernah saya gunakan sebelumnya (dan yang benar-benar bisa dilakukan dengan beberapa dokumentasi); itu dirancang untuk seni ASCII tetapi mampu menulis string dalam satu dimensi juga. Karakter ASCII dicetak secara harfiah dalam Charcoal, yang berarti bahwa pencetakan string konstan tidak memerlukan boilerplate, dan kita dapat menggunakan perintah untuk menginterpolasi string yang diambil dari input pengguna ke dalam program.

Mungkin saja (sedikit) lebih pendek. Konstruktor quine universal quine berisi dua bagian berulang yang cukup panjang. Dengan demikian kita dapat menggunakan perintah untuk menetapkan mereka ke variabel (misalnya A…αmenetapkan ke variabel α), dan cukup menginterpolasi variabel ke dalam string yang kita cetak melalui menggunakan nama mereka. Itu menghemat beberapa byte hanya dengan menulis string secara harfiah.

Sayangnya, Charcoal juga menambahkan baris baru ke program, tapi itu bukan masalah besar; itu hanya biaya dua byte untuk \nmenambahkan baris baru ke input Q juga.

Contoh

Jika kita memberikan input $_=reverse(yang membalikkan string), kita mendapatkan output berikut:

$_=q($_=reverse"\$_=q($_);eval\n";print);eval

Cobalah online!

yang merupakan quine-sama yang mencetak sumbernya mundur, seperti yang diharapkan.


1

JellyUnderload , 15 byte

“(a(:^)*“S):^”j

Cobalah online!

Mengambil fungsi masukan Underload Q sebagai argumen seperti perintah. Q harus mengambil input dari stack dan mendorong output ke stack, tanpa berusaha memeriksa elemen stack yang lebih dalam (karena mereka tidak akan ada).

Penjelasan

Underload

Konstruktor quine universal Underload yang digunakan di sini adalah:

(a(:^)*…S):^

Sebagian besar program adalah satu literal. Kami mengikutinya dengan :^, yang menyalinnya, lalu mengevaluasi satu salinan (meninggalkan salinan lainnya di tumpukan).

Ketika literal mulai mengevaluasi, kita menjalankan a(escape, yang membawanya kembali ke bentuk yang sama dengan programA asli), dan (:^)*(yang menambahkan :^), sehingga merekonstruksi kode sumber seluruh program. Kami kemudian dapat menjalankan fungsi Q untuk mengubah ini dengan cara yang sewenang-wenang, dan mencetak hasilnya denganS .

Jelly

Saya tidak dapat menggunakan Charcoal saat ini karena penerjemah Underload yang valid mogok di akhir program jika program berakhir dengan baris baru. (Beberapa penerjemah Underload, seperti yang ada di TIO, tidak menegakkan aturan ini, tapi saya ingin menjadi portabel dengan baik.) Sayangnya, Charcoal secara alami menambahkan garis baru ke outputnya. Sebaliknya, saya menggunakan Jelly, yang hampir sama singkatnya dalam kasus-kasus sederhana seperti ini; program terdiri dari daftar literal dengan dua elemen ( ““”), dan bergabung dengan mereka pada input ( j), sehingga memasukkan input pengguna ke dalam program.

Contoh

Menggunakan input :S^(cetak salinan, lalu evaluasi yang asli), kami mendapatkan program Underload berikut:

(a(:^)*:S^S):^

Cobalah online!

Ini mencetak dirinya sendiri berkali-kali, dengan cara yang cukup menarik: setelah melakukan perilaku quine normal, ia kemudian berjalan evalpada salinan dari apa yang dihasilkannya. Itu menyebabkan seluruh program yang direkonstruksi berjalan lagi, tanpa batas waktu (Underload bersifat ekor-rekursif). Mengutip diri sendiri dan melakukan evalsebenarnya adalah satu-satunya cara untuk melakukan loop tanpa batas di Underload.


Charcoal tidak menambahkan baris baru lagi (yay)
ASCII

1

RProgN 2 , 11 byte

'{`{.%s}{'F

Penjelasan Program

'{`{.%s}{'F
'{`{.%s}{'  # Push the string "{`{.%s}{" to the stack.
          F # Format the input with the top of the stack as a template. Which produces {`{.<INPUT>}{

Quine Explination

Quine yang diproduksi sederhana, namun menggunakan fungsionalitas fungsi handler yang tidak tertandingi dalam RProgN2 untuk membuat quine pendek dan manis, yang disebut quine "Looping". Ini adalah konsep yang sangat mirip dengan <> <quine.

{`{.}{
{`{.}   # Push the function {`{.} to the stack.
     {  # Try to define a new function, fail, loop back to index 1. (Which in turn, skips the function definition.)
 `{     # Push the string "{" to the stack.
   .    # Concatenate the top two values of the stack, which stringifies the function, then appends { to it.
    }   # Try to terminate a function, fail quietly, and terminate the program.

Tentu saja, karena struktur quine ini, apa pun kecuali no-ops yang benar (Yang tidak dapat dikompilasi) dapat ditempatkan setelah fungsi gabungan, dan

Beberapa quines

  • {`{.i}{: Keluaran {}i.{`{. ihanya fungsi "terbalik", jadi output program ini sendiri terbalik.
  • {`{.S§.}{: Keluaran ..S`{{{}§. Smengubah string menjadi setumpuk karakter, §mengurutkan tumpukan secara leksografis, lalu .menyatukannya kembali, mengeluarkannya sendiri.

Cobalah online!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.