Bisakah Anda menggunakan Meta Quine?


25

Mirip dengan teka-teki quine lainnya (lebih khusus, yang ini ), tulis sebuah program yang menghasilkan sumber untuk dirinya sendiri.

Inilah sentuhan baru: Kode yang dihasilkan TIDAK harus identik dengan sumbernya. Alih-alih, itu harus menghasilkan program yang berbeda yang akan membuat yang pertama.

Tantangan terkait dengan di atas mencapai itu dengan melompat di antara dua bahasa. Saya pikir ini akan dilakukan hanya dalam satu bahasa , tetapi dua (atau lebih) versi sumber harus berbeda secara signifikan (lihat aturan di bawah). Dengan batasan ini, jawaban karakter tunggal akan dianulir, sehingga membutuhkan sedikit pemikiran lagi untuk dimasukkan ke dalam pengiriman akhir.


ATURAN

  1. Kode Anda harus diproduksi hanya dalam satu bahasa. (Banyak pengiriman, satu untuk setiap bahasa dapat diterima.)
  2. Versi kode Anda yang berbeda harus berbeda secara sintaksis. Dengan kata lain, jika Anda menggambar pohon sintaksis abstrak untuk kode Anda, harus ada setidaknya satu node yang berbeda.
    • Memasok AST tidak akan diperlukan, tetapi jika Anda merasa cenderung untuk memberikan satu untuk setiap program Anda, itu akan membantu dalam menilai.
  3. Anda dapat menghasilkan sebanyak mungkin iterasi yang Anda inginkan, asalkan semuanya tetap berbeda secara sintaksis. (Lebih banyak akan membantu skor Anda, lihat di bawah.)

SKOR

Skor akhir Anda akan menjadi panjang rata-rata dari semua program Anda, dibagi dengan jumlah program.

Contoh 1:

A (sumber untuk B) = 50 karakter
B (sumber untuk A) = 75 karakter
Skor Akhir = 31,25

Contoh 2:

A (sumber untuk B) = 50 karakter
B (sumber untuk C) = 75 karakter
C (sumber untuk A) = 100 karakter
Skor Akhir = 25


18
Saya meta quine sekali.
mellamokb

1
@mellamokb har har ;-)
Gaffi

Ini sebenarnya hanya versi yang lebih umum dari tantangan quine ini , dan jawaban yang diberikan di sana juga akan menang di sini.
Berhenti menghidupkan counterclockwis

@leftaroundabout, persyaratan untuk perbedaan sintaksis membatalkan 'rotating quine', jadi ini tidak umum.
Stanby

2
Saya tidak pernah menyukai meta quine.
Stack Tracer

Jawaban:


35

Python, 0 (batas (68 + 3 n ) / (16 n ))

Jika dua pohon sintaksis abstrak berbeda jika mereka memiliki konstanta yang berbeda,

r='r=%r;n=(0x%XL+1)%%0x10...0L;print r%%(r,n)';n=(0xF...FL+1)%0x10...0L;print r%(r,n)

ada 16 n program dengan panjang maksimal 68 + 3n, memberikan skor asimptotik 0.

Jika Anda menginginkan program dengan struktur variabel, kami dapat mengimplementasikan adder biner pada n bit. Di sini, ada 2 n program dengan panjang O ( n 2 ). Masuk dalam siklus karena dijatuhkan carry bit.

s="""
print 's='+'"'+'"'+'"'+s+'"'+'"'+'"'
n=lambda m:reduce(lambda (s,c),y:(s+(c^y,),c&y),m,((),1))[0]
print s[:112]
t=n(t)
print "t=(%s,)+(0,)*%s"%(t[0],len(t)-1)
for i in range(len(t)-1):
    print i*' '+'for i in range(2):'
    print ' '+i*' '+['pass','t=n(t)'][t[i+1]]
print s[113:-1]
"""

print 's='+'"'+'"'+'"'+s+'"'+'"'+'"'
n=lambda m:reduce(lambda (s,c),y:(s+(c^y,),c&y),m,((),1))[0]
print s[:112]
t=(0,)+(0,)*10
for i in range(2):
 t=n(t)
 for i in range(2):
  t=n(t)
  for i in range(2):
   t=n(t)
   for i in range(2):
    t=n(t)
    for i in range(2):
     pass
     for i in range(2):
      t=n(t)
      for i in range(2):
       pass
       for i in range(2):
        pass
        for i in range(2):
         pass
         for i in range(2):
          t=n(t)
t=n(t)
print "t=(%s,)+(0,)*%s"%(t[0],len(t)-1)
for i in range(len(t)-1):
    print i*' '+'for i in range(2):'
    print ' '+i*' '+['pass','t=n(t)'][t[i+1]]
print s[113:-1]

Mungkinkah saya bingung? Sepertinya output identik dengan sumber (bukan tujuan dari tantangan ini)?
Gaffi

Lihat di blok bersarang. passakan berubah ke t=n(t)dan kembali, dalam semua kombinasi 2 ^ n.
Stanby

Saya melihat itu sekarang. Anda membingungkan saya dengan semua pengulangan!
Gaffi

22
untuk beberapa alasan, saya suka solusi golf yang sangat panjang dengan skor kecil.
Stanby

Wow, kamu benar-benar memilikinya! Sangat bagus.
Claudiu

4

Perl, skor 110,25

Saya harus akui, saya tidak begitu pandai bergaul. Saya 100% yakin bahwa ada ruang untuk perbaikan. Solusi didasarkan dari prinsip yang sama dari solusi Elemen di bawah ini.

Program pertama adalah 264 karakter.

$s='$a=chr(39);print"\$s=$a$s$a;";$s=reverse$s;for(1..87){chop$s}$s=reverse$s;print$s;$f++;if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}';$a=chr(39);print"\$s=$a$s$a;";$s=reverse$s;for(1..87){chop$s}$s=reverse$s;print$s;$f++;if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}

Program kedua adalah 177 karakter.

$s='$a=chr(39);print"\$s=$a$s$a;";$s=reverse$s;for(1..87){chop$s}$s=reverse$s;print$s;$f++;if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}';if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}

Saya sedang mengerjakan AST untuk entri ini (dan entri Elemen).


Elemen , skor 47.25

Program pertama adalah 105 karakter.

\ \3\:\$\'\[\\\\\`\(\`\]\#\2\1\'\[\(\#\]\`\ \3\:\$\'\[\\\\\`\(\`\]\#\` 3:$'[\\`(`]#21'[(#]` 3:$'[\\`(`]#`

Program kedua adalah 84 karakter.

\ \3\:\$\'\[\\\\\`\(\`\]\#\2\1\'\[\(\#\]\`\ \3\:\$\'\[\\\\\`\(\`\]\#\` 3:$'[\\`(`]#`

Saya yakin ada banyak ruang untuk perbaikan.

Dalam program pertama ada satu string (di mana setiap karakter lolos, meskipun banyak redundansi) diikuti oleh bagian yang dapat dieksekusi A dan B. Bagian A melakukan beberapa hal: mencetak string dan keluar dari setiap karakter, mencetak setengah terakhir dari string (yang merupakan sumber untuk bagian B), dan kemudian mencegah bagian B yang mengikutinya melakukan apa pun.

Program kedua adalah string yang sama diikuti oleh bagian B. Bagian B didasarkan dari quine sederhana; itu mencetak string yang didahului oleh versi yang lolos darinya. Ini berarti mencetak string, dan kedua bagian A dan B.


Saya pikir ini secara definitif, tanpa keraguan, membuktikan validitas Elemen sebagai bahasa pemrograman. Sangat mudah digunakan sehingga saya, yang tidak berpengalaman sehingga saya hanya berhasil menulis satu penerjemah lengkap untuk Elemen, telah mampu menjawab pertanyaan ini sebelum orang lain di seluruh planet ini yang terdiri dari 7.000.000.000 orang. Paradigma "satu karakter, satu fungsi, sepanjang waktu" berarti bahwa semua kode sama sekali tidak ambigu. Bahasa ini fleksibel: kecuali untuk []{}, perintah apa pun dapat ditempatkan di mana saja di seluruh program tanpa menyebabkan kesalahan sintaksis. Sempurna.
PhiNotPi

4
Sedikit bias, kan? ;-)
Gaffi

3

VBA: (251 + 216) / 2/2 = 116,75

251

Sub a()
r=vbCrLf:c="If b.Lines(4, 4) = c Then"&r &"b.InsertLines 8, d"&r &"b.DeleteLines 4, 4"&r &"End If":d="b.InsertLines 6, c"&r &"b.DeleteLines 4, 2"
Set b=Modules("Q")
If b.Lines(4, 4) = c Then
b.InsertLines 8, d
b.DeleteLines 4, 4
End If
End Sub

216

Sub a()
r=vbCrLf:c="If b.Lines(4, 4) = c Then"&r &"b.InsertLines 8, d"&r &"b.DeleteLines 4, 4"&r &"End If":d="b.InsertLines 6, c"&r &"b.DeleteLines 4, 2"
Set b=Modules("Q")
b.InsertLines 6,c
b.DeleteLines 4,2
End Sub

Ini dijalankan di MSAccess untuk memanfaatkan Moduleobjek. Modul ini dinamai "Q"untuk golf. Perbedaan dalam sintaksis berasal dari yang If ... Thenhilang dari versi yang lebih pendek.


Anda kemungkinan besar dapat beralih vbCrLFkevbCr
Taylor Scott

3

C ++, skor 0,734194

Kode sumber berikut mencetak meta quine pesanan 999 ke konsol (penjelasan di bawah):

#define X 1*(1+1)
#include<iostream>
#include<vector>
#define Q(S)auto q=#S;S
Q( \
  main() \
  { \
      using namespace std; \
      cout<<"#define X 1"; \
      int x=X==2?1000:X-1; \
      vector<int> factors; \
      for ( int p = 2; p <= x; ++p) \
      { \
        while ( x % p == 0 ) \
        { \
          factors.push_back( p ); \
          x /= p; \
        } \
      } \
      for ( int factor : factors ) \
      { \
        cout<<"*(1"; \
        for ( int i=1;i<factor;++i) \
          cout<<"+1"; \
        cout<<")"; \
      } \
      cout<<"\n#include<iostream>\n#include<vector>\n#define Q(S)auto q=#S;S\nQ("<<q<<")"; \
  })

Satu-satunya baris yang berubah adalah baris pertama. Nilai Xakan menjadi 1000, 999, 998, ..., 3, 2 dan kemudian akan mulai lagi. Namun, untuk mendapatkan pohon sintaks yang berbeda setiap kali, Xdiwakili dalam hal faktorisasi prima, di mana setiap prime ditulis sebagai jumlah 1s. AST berbeda, karena faktorisasi bilangan bulat utama berbeda untuk setiap nilai.

Program akan mencetak sendiri, kecuali bahwa baris pertama diubah dan garis miring terbalik, putus baris dan lekukan yang ada di dalamnya Q(...)akan dihapus.

Program berikut menghitung skor jawaban saya:

#include <iostream>

const int n = 1000;

int getProgramLength( int n )
{
  int sum = 442;
  for ( int p = 2; p*p <= n; ++p )
  {
    while ( n % p == 0 )
    {
      sum += 2 * ( 1 + p );
      n /= p;
    }
  }
  if ( n > 1 )
    sum += 2 * ( 1 + n );
  return sum;
}

int main()
{
  int sum = 0;
  for ( int i = 2; i <= n; ++i )
    sum += getProgramLength( i );
  std::cout << (double)sum/(n-1)/(n-1) << '\n';
}

Itu dicetak 0,734194 ke konsol. Jelas, 1000 dapat diganti dengan bilangan bulat yang lebih besar dan skor akan mendekati 0 sebagai batasnya. Bukti matematis yang melibatkan fungsi Riemann Zeta agak berbelit-belit. Saya meninggalkannya sebagai latihan untuk pembaca. ;)


2

JavaScript, 84.5 64 61

Dua program, keduanya panjang 169 128 122.

(function c(){alert(/*
2/*/1/**/);return ('('+c+')()').replace(/\/([/\*])/,function(m,a){return a=='*'?'/\/':'/\*'});
})()

Sebelum saya bermain golf, untuk kesenangan menonton Anda:

(function c() {
    var r = /\/([/\*])/;
    var f = function(m, a) { return a === '*' ? '/\/' : '/\*' };
    var p = '(' + c + ')();';
    p = p.replace(r, f);
    /* This is just a comment!
    console.log('Quine, part two!'); /*/
    console.log('Quine, part one!'); /**/
    return p;
})();

Mengembalikan program baru dan menampilkan bagian saat ini! Saya mungkin bisa membuatnya lebih pendek tanpa fungsi regex, tapi ... Saya tidak mau.


Tidak, keduanya berbeda secara sintaksis. Setelah Anda menambahkan baris baru, yaitu.
Ry-

2

J - (24 + 30) / 2/2 = 13,5 poin

Perhatikan bahwa string di J tidak di-escape, tapi kutipan-lolos Ă  la Pascal: 'I can''t breathe!'.

30$(,5#{.)'''30$(,5#{.)'         NB. program 1, 24 char
'30$(,5#{.)''''''30$(,5#{.)'''   NB. program 2, 30 char

Program 1 memiliki AST noun verb hook noundan program 2 memiliki AST noun. Program 2 adalah versi yang dikutip dari program 1, yang hanya akan mengembalikan program 1 saat dijalankan, jadi metode ini tidak dapat diperpanjang hingga tiga salinan dengan mudah: P

Program 1 beroperasi dengan mengambil salinan bagian kode dari sumber, dengan kutipan ditambahkan di bagian depan, dan menambahkan lima kutipan tersebut di akhir ( (,5#{.)). Kemudian, secara siklis mengambil 30 karakter dari string 16-karakter ini, yang menghasilkan Program 2 sebagai hasilnya.

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.