Können Sie Meta Quine?


25

Schreiben Sie ähnlich wie bei anderen Quine-Puzzles (genauer gesagt bei diesem ) ein Programm, das die Quelle für sich selbst erzeugt.

Hier ist die neue Wendung: Der erzeugte Code sollte NICHT mit der Quelle identisch sein. Stattdessen sollte ein anderes Programm ausgegeben werden, das das erste erstellt.

Die damit verbundene Herausforderung erreichte dies durch das Wechseln zwischen zwei Sprachen. Ich denke, dies würde in nur einer Sprache geschehen , aber die zwei (oder mehr) Versionen der Quelle sollten sich erheblich unterscheiden (siehe Regeln unten). Mit dieser Einschränkung wären Antworten mit einem einzelnen Zeichen nicht zulässig, so dass ein wenig mehr Überlegung für eine endgültige Einreichung erforderlich ist.


REGELN

  1. Ihr Code muss nur in einer Sprache verfasst sein. (Mehrere Einsendungen, eine für jede Sprache, sind vollkommen akzeptabel.)
  2. Ihre verschiedenen Codeversionen müssen syntaktisch unterschiedlich sein. Mit anderen Worten, wenn Sie einen abstrakten Syntaxbaum für Ihren Code erstellen, sollte sich mindestens ein Knoten von diesem unterscheiden.
    • Die Angabe eines AST ist nicht erforderlich. Wenn Sie jedoch bereit sind, für jedes Ihrer Programme einen AST bereitzustellen, kann dies bei der Beurteilung hilfreich sein.
  3. Sie können beliebig viele Iterationen erstellen, sofern alle syntaktisch unterschiedlich sind. (Mehr hilft Ihrem Ergebnis, siehe unten.)

WERTUNG

Ihre endgültige Punktzahl ist die durchschnittliche Länge aller Ihrer Programme, dividiert durch die Anzahl der Programme.

Beispiel 1:

A (Quelle für B) = 50 Zeichen
B (Quelle für A) = 75 Zeichen
Endergebnis = 31,25

Beispiel 2:

A (Quelle für B) = 50 Zeichen
B (Quelle für C) = 75 Zeichen
C (Quelle für A) = 100 Zeichen
Endnote = 25


18
Ich habe einmal Quine getroffen.
Mellamokb

1
@mellamokb har har ;-)
Gaffi

Dies ist eigentlich nur eine allgemeinere Version dieser Herausforderung, und die dort gegebenen Antworten werden auch hier gewinnen.
drehte sich nicht mehr gegen den Uhrzeigersinn am

@leftaroundabout, das Erfordernis für syntaktische Unterschiede macht ein 'rotierendes Quine' ungültig, daher ist dies nicht allgemeiner.
Stand

2
Niemals meta quine hat mir nicht gefallen.
Stack Tracer

Antworten:


35

Python, 0 (Grenze von (68 + 3 n ) / (16 n ))

Wenn zwei abstrakte Syntaxbäume unterschiedlich sind, wenn sie unterschiedliche Konstanten haben,

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

Es gibt 16 n Programme mit einer Länge von höchstens 68 + 3n, was einen asymptotischen Wert von 0 ergibt.

Wenn Sie Programme mit variabler Struktur wünschen, können wir einen binären Addierer mit n Bits implementieren . Hier gibt es 2 n Programme der Länge O ( n 2 ). Geht in einen Zyklus, weil das Übertragsbit gefallen ist.

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]

Könnte ich verwirrt sein? Es sieht so aus, als ob die Ausgabe mit der Quelle identisch ist (nicht das Ziel dieser Herausforderung).
Gaffi

Schau in den verschachtelten Block. wechselt in allen 2 ^ n Kombinationen passnach t=n(t)und zurück.
Stand vom

Das sehe ich jetzt. Du hast mich mit der ganzen Wiederholung verwechselt!
Gaffi

22
Aus irgendeinem Grund mag ich sehr lange Golflösungen mit winzigen Punktzahlen.
Stand

Wow, das hast du komplett besessen! Sehr schön.
Claudiu

4

Perl, Score von 110,25

Ich muss zugeben, dass ich nicht sehr gut mit Quinten umgehen kann. Ich bin mir zu 100% sicher, dass es Verbesserungspotenzial gibt. Die Lösung basiert auf demselben Prinzip wie die nachstehende Elementlösung.

Das erste Programm besteht aus 264 Zeichen.

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

Das zweite Programm besteht aus 177 Zeichen.

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

Ich arbeite an der AST für diesen Eintrag (und den Element-Eintrag).


Element , Punktzahl von 47,25

Das erste Programm besteht aus 105 Zeichen.

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

Das zweite Programm besteht aus 84 Zeichen.

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

Ich bin sicher, dass es viel Raum für Verbesserungen gibt.

Im ersten Programm gibt es eine Zeichenfolge (in der jedes Zeichen trotz großer Redundanz maskiert wird), gefolgt von den ausführbaren Teilen A und B. Teil A führt verschiedene Aktionen aus: druckt die Zeichenfolge und maskiert jedes Zeichen, druckt die letzte Hälfte der Zeichenfolge (die die Quelle für Teil B ist), und verhindert dann, dass der Teil B, der ihm folgt, etwas tut.

Das zweite Programm ist derselbe String, dem Teil B folgt. Teil B basiert auf einem einfachen Quine. Es wird eine Zeichenfolge ausgegeben, der eine maskierte Version vorangestellt ist. Dies bedeutet, dass die Zeichenfolge und die beiden Teile A und B gedruckt werden.


Ich denke, dies beweist zweifelsohne definitiv die Gültigkeit von Element als Programmiersprache. Es ist so einfach zu benutzen, dass ich, so unerfahren, dass ich nur einen vollständigen Dolmetscher für Element geschrieben habe, diese Frage vor jeder anderen Person auf diesem ganzen Planeten mit 7 Millionen Menschen beantworten konnte. Das Paradigma "Ein Zeichen, eine Funktion, die ganze Zeit" von Element bedeutet, dass der gesamte Code völlig eindeutig ist. Die Sprache ist vielseitig: bis auf[]{} kann jeder Befehl an einer beliebigen Stelle im gesamten Programm platziert werden, ohne dass ein Syntaxfehler auftritt. Es ist perfekt.
PhiNotPi

4
Ein bisschen voreingenommen, oder? ;-)
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

Dies wird in MSAccess ausgeführt , um das ModuleObjekt zu verwenden. Das Modul ist "Q"für das Golfen benannt. Der Unterschied in der Syntax ergibt sich aus dem If ... ThenFehlen der kürzeren Version.


Sie können höchstwahrscheinlich mit dem Wechsel vbCrLFzuvbCr
Taylor Scott

3

C ++, Score von 0,734194

Der folgende Quellcode gibt eine Meta-Quine in der Größenordnung von 999 auf der Konsole aus (Erläuterung unten):

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

Die einzige Zeile, die geändert wird, ist die erste Zeile. Der Wert vonX wird 1000, 999, 998, ..., 3, 2 sein und dann wird es erneut gestartet. Um jedoch jedes Mal unterschiedliche Syntaxbäume zu erhalten, Xwird in Bezug auf die Primfaktorisierung jede Primzahl als Summe von geschrieben1 s geschrieben wird. Die ASTs sind unterschiedlich, da die Primfaktorisierung von ganzen Zahlen für jeden Wert unterschiedlich ist.

Das Programm druckt sich selbst, mit der Ausnahme, dass die erste Zeile geändert wird und die darin enthaltenen Backslashes, Zeilenumbrüche und Einrückungen Q(...) entfernt werden.

Das folgende Programm berechnet die Punktzahl meiner Antwort:

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

Es druckte 0.734194 auf der Konsole. Offensichtlich kann 1000 durch größere ganze Zahlen ersetzt werden und die Punktzahl nähert sich 0 als Grenzwert. Der mathematische Beweis für Riemanns Zeta-Funktion ist etwas verworren. Ich überlasse es dem Leser als Übung. ;)


2

JavaScript, 84,5 64 61

Zwei Programme, beide Länge 169 128 122.

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

Bevor ich Golf gespielt habe, für Ihr Sehvergnügen:

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

Liefert das neue Programm und gibt den aktuellen Teil aus! Ich könnte es wahrscheinlich ohne die Funktion Regex kürzer machen, aber ... ich will nicht.


Nein, sie unterscheiden sich syntaktisch. Sobald Sie die Zeilenumbrüche hinzugefügt haben, ist dies der Fall.
Ry

2

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

Beachten Sie, dass Strings in J sind nicht die Backslash-entkommen, aber Zitat-escaped à la Pascal: 'I can''t breathe!'.

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

Programm 1 hat AST noun verb hook nounund Programm 2 hat AST noun. Programm 2 ist eine zitierte Version von Programm 1, die beim Ausführen nur Programm 1 zurückgibt, sodass diese Methode nicht so einfach auf drei Kopien erweitert werden kann: P

Programm 1 erstellt eine Kopie des Codeabschnitts der Quelle mit einem angehängten Zitat und fügt am Ende fünf dieser Zitate hinzu ( (,5#{.)). Anschließend werden zyklisch 30 Zeichen aus dieser 16-stelligen Zeichenfolge verwendet, was genau zu Programm 2 führt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.