Sai Meta Quine?


25

Simile ad altri puzzle di quine (più specificamente, questo ), scrivere un programma che produce la fonte per sé.

Ecco la nuova svolta: il codice prodotto NON deve essere identico alla fonte. Piuttosto, dovrebbe generare un programma diverso che creerà il primo.

La sfida collegata a quella sopra raggiunta è quella saltando tra due lingue. Sto pensando che questo sarebbe fatto in una sola lingua , ma le due (o più) versioni del sorgente dovrebbero essere significativamente diverse (vedi regole sotto). Con questo vincolo, le risposte a carattere singolo sarebbero vietate, richiedendo quindi un po 'più di pensiero in una sottomissione finale.


REGOLE

  1. Il tuo codice deve essere prodotto in una sola lingua. (Più invii, uno per ogni lingua è perfettamente accettabile.)
  2. Le diverse versioni del codice devono essere sintatticamente distinte. In altre parole, se dovessi disegnare un albero di sintassi astratto per il tuo codice, dovrebbe esserci almeno un nodo diverso.
    • Fornire un AST non sarà necessario, ma se ti senti incline a fornirne uno per ciascuno dei tuoi programmi, sarebbe utile per giudicare.
  3. Puoi produrre tutte le iterazioni che desideri, purché rimangano tutte sintatticamente distinte. (Altro aiuterà il tuo punteggio, vedi sotto).

PUNTEGGIO

Il tuo punteggio finale sarà la lunghezza media di tutti i tuoi programmi, diviso per il numero di programmi.

Esempio 1:

A (fonte per B) = 50 caratteri
B (fonte per A) = 75 caratteri
Punteggio finale = 31,25

Esempio 2:

A (fonte per B) = 50 caratteri
B (fonte per C) = 75 caratteri
C (fonte per A) = 100 caratteri
Punteggio finale = 25


18
Ho meta quine una volta.
mellamokb,

1
@mellamokb har har ;-)
Gaffi

Questa è in realtà solo una versione più generale di questa sfida, e anche le risposte fornite qui vinceranno qui.
cessò di girare in senso antiorario il

@leftaroundabout, il requisito per le differenze sintattiche invalida un "quine rotante", quindi questo non è più generale.
stand

2
Mai meta quine non mi è piaciuto.
Stack Tracer

Risposte:


35

Python, 0 (limite di (68 + 3 n ) / (16 n ))

Se due alberi di sintassi astratti sono diversi se hanno costanti diverse,

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

ci sono 16 n programmi di lunghezza al massimo 68 + 3n, che danno un punteggio asintotico di 0.

Se vuoi programmi con struttura variabile, possiamo implementare un sommatore binario su n bit. Qui ci sono 2 n programmi di lunghezza O ( n 2 ). Va in ciclo a causa della caduta del bit di trasporto.

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]

Potrei essere confuso? Sembra che l'output sia identico alla fonte (non l'obiettivo di questa sfida)?
Gaffi,

Cerca nel blocco nidificato. passcambierà in t=n(t)e indietro, in tutte le 2 ^ n combinazioni.
stand dal

Lo vedo ora. Mi hai confuso con tutta la ripetizione!
Gaffi,

22
per qualche motivo, mi piacciono le soluzioni di golf molto lunghe con punteggi minuscoli.
stand,

Caspita, lo possedevi completamente! Molto bella.
Claudiu

4

Perl, punteggio di 110,25

Devo ammetterlo, non sono molto bravo con le quines. Sono sicuro al 100% che ci sono margini di miglioramento. La soluzione si basa sullo stesso principio della soluzione Element di seguito.

Il primo programma è di 264 caratteri.

$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"}

Il secondo programma è di 177 caratteri.

$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"}

Sto lavorando su AST per questa voce (e la voce Element).


Elemento , punteggio di 47,25

Il primo programma è di 105 caratteri.

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

Il secondo programma è di 84 caratteri.

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

Sono sicuro che c'è molto margine di miglioramento.

Nel primo programma c'è una stringa (in cui ogni carattere è sfuggito, nonostante molta ridondanza) seguito dalle parti eseguibili A e B. La parte A fa diverse cose: stampa la stringa ed esce da ogni carattere, stampa l'ultima metà della stringa (che è l'origine della parte B), quindi impedisce alla parte B che la segue di fare qualsiasi cosa.

Il secondo programma è la stessa stringa seguita dalla parte B. La parte B si basa su un semplice quine; stampa una stringa preceduta da una versione di escape. Ciò significa che stampa la stringa e entrambe le parti A e B.


Penso che questo definitivamente, al di là di ogni dubbio, dimostri la validità di Element come linguaggio di programmazione. È così facile da usare che io, così inesperto che sono riuscito a scrivere un solo interprete completo per Element, sono stato in grado di rispondere a questa domanda prima di qualsiasi altra persona su questo intero pianeta di 7.000.000.000 di persone. Il paradigma "un carattere, una funzione, tutto il tempo" di Element significa che tutto il codice è completamente inequivocabile. La lingua è versatile: ad eccezione di []{}qualsiasi comando, può essere posizionato ovunque nell'intero programma senza causare un errore di sintassi. È perfetto.
PhiNotPi

4
Un po 'di parte, vero? ;-)
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

Questo viene eseguito in MSAccess per utilizzare l' Moduleoggetto. Il modulo è chiamato "Q"per il golf. La differenza nella sintassi deriva dalla If ... Thenmancanza della versione più breve.


molto probabilmente puoi cavartela cambiando vbCrLFinvbCr
Taylor Scott

3

C ++, punteggio di 0,734194

Il seguente codice sorgente stampa un meta quine dell'ordine 999 sulla console (spiegazione di seguito):

#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<<")"; \
  })

L'unica riga che cambia è la prima riga. Il valore di Xsarà 1000, 999, 998, ..., 3, 2 e quindi ricomincerà. Tuttavia, al fine di ottenere alberi di sintassi diversi ogni volta, Xè rappresentato in termini di scomposizione in fattori primi, in cui ogni numero primo è scritto come una somma di 1s. Gli AST sono diversi, perché la fattorizzazione in fattori primi degli interi è diversa per ogni valore.

Il programma si stamperà automaticamente, tranne per il fatto che la prima riga viene modificata e le barre rovesciate, le interruzioni di riga e i rientri all'interno Q(...)verranno rimossi.

Il seguente programma calcola il punteggio della mia risposta:

#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';
}

Ha stampato 0.734194 sulla console. Ovviamente, 1000 possono essere sostituiti da numeri interi più grandi e il punteggio si avvicinerà a 0 come limite. La dimostrazione matematica coinvolge la funzione Zeta di Riemann in qualche modo contorta. Lo lascio come esercizio al lettore. ;)


2

JavaScript, 84.5 64 61

Due programmi, entrambi di lunghezza 169 128 122.

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

Prima di giocare a golf, per il tuo piacere di visione:

(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;
})();

Restituisce il nuovo programma e restituisce la parte corrente! Probabilmente potrei accorciarlo senza la funzione regex, ma ... Non voglio.


No, sono sinteticamente distinti. Una volta aggiunte le nuove righe, vale a dire.
Ry,

2

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

Si noti che le stringhe in J non sono il backslash escape, ma quote-fuggiti à la Pascal: 'I can''t breathe!'.

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

Il programma 1 ha AST noun verb hook noune il programma 2 ha AST noun. Il programma 2 è una versione quotata del programma 1, che restituirà il programma 1 solo quando eseguito, quindi questo metodo non può essere esteso facilmente a tre copie: P

Il Programma 1 opera prendendo una copia della parte di codice della fonte, con una citazione aggiunta in primo piano e aggiungendo cinque di quelle citazioni alla fine ( (,5#{.)). Quindi, prende ciclicamente 30 caratteri da questa stringa di 16 caratteri, che fornisce esattamente il Programma 2 come risultato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.