Pouvez-vous Meta Quine?

25

Semblable à d'autres puzzles quine (plus spécifiquement, celui-ci ), écrivez un programme qui produit la source pour lui-même.

Voici la nouvelle tournure: le code produit ne doit PAS être identique à la source. Il devrait plutôt produire un programme différent qui créera le premier.

Le défi lié à ce qui précède l'a atteint en sautant entre deux langues. Je pense que celui-ci serait fait dans une seule langue , mais les deux versions (ou plus) de la source devraient être sensiblement différentes (voir les règles ci-dessous). Avec cette contrainte, les réponses à caractère unique seraient interdites, ce qui nécessiterait un peu plus de réflexion pour une soumission finale.


RÈGLES

  1. Votre code doit être produit dans une seule langue. (Plusieurs soumissions, une pour chaque langue sont parfaitement acceptables.)
  2. Vos différentes versions de code doivent être syntaxiquement distinctes. En d'autres termes, si vous deviez dessiner un arbre de syntaxe abstrait pour votre code, il devrait y avoir au moins un nœud différent.
    • La fourniture d' un AST ne sera pas nécessaire, mais si vous avez envie de fournir un pour chacun de vos programmes, il serait aider à juger.
  3. Vous pouvez produire autant d'itérations que vous le souhaitez, tant qu'elles restent toutes syntaxiquement distinctes. (Plus aidera votre score, voir ci-dessous.)

NOTATION

Votre score final sera la durée moyenne de tous vos programmes, divisée par le nombre de programmes.

Exemple 1:

A (source pour B) = 50 caractères
B (source pour A) = 75 caractères
Score final = 31,25

Exemple 2:

A (source pour B) = 50 caractères
B (source pour C) = 75 caractères
C (source pour A) = 100 caractères
Score final = 25

Gaffi
la source
18
J'ai méta quine une fois.
mellamokb
1
@mellamokb har har ;-)
Gaffi
Il s'agit en fait d'une version plus générale de ce défi quine, et les réponses qui y seront données gagneront ici aussi.
cessé de tourner dans le sens inverse des aiguilles d'une montre le
@leftaroundabout, l'exigence de différences syntaxiques invalide un «quine tournant», ce n'est donc pas plus général.
boothby
2
Jamais méta quine que je n'aimais pas.
Stack Tracer

Réponses:

35

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

Si deux arbres de syntaxe abstraite sont différents s'ils ont des constantes différentes,

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

il y a 16 n programmes de longueur au maximum 68 + 3n, donnant un score asymptotique de 0.

Si vous souhaitez des programmes à structure variable, nous pouvons implémenter un additionneur binaire sur n bits. Ici, il y a 2 n programmes de longueur O ( n 2 ). Va dans un cycle en raison de la chute du bit de transport.

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]
boothby
la source
Pourrais-je être confus? On dirait que la sortie est identique à la source (pas l'objectif de ce challenge)?
Gaffi
Regardez dans le bloc imbriqué. passchangera en t=n(t)et en arrière, dans toutes les 2 ^ n combinaisons.
boothby
Je vois ça maintenant. Vous m'avez confondu avec toute la répétition!
Gaffi
22
pour une raison quelconque, j'aime les solutions de golf très longues avec des scores minuscules.
stand
Wow, tu possédais complètement ça! Très agréable.
Claudiu
4

Perl, score de 110,25

Je dois admettre que je ne suis pas très bon avec les quines. Je suis certain à 100% qu'il y a place à amélioration. La solution est basée sur le même principe que la solution Element ci-dessous.

Le premier programme est de 264 caractères.

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

Le deuxième programme est de 177 caractères.

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

Je travaille sur l'AST pour cette entrée (et l'entrée Element).


Élément , score de 47,25

Le premier programme est de 105 caractères.

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

Le deuxième programme est de 84 caractères.

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

Je suis sûr qu'il y a encore beaucoup à faire.

Dans le premier programme, il y a une chaîne (dans laquelle chaque caractère est échappé, malgré beaucoup de redondance) suivie des parties exécutables A et B. La partie A fait plusieurs choses: imprime la chaîne et s'échappe de chaque caractère, imprime la dernière moitié de la chaîne (qui est la source de la partie B), puis empêche la partie B qui la suit de faire quoi que ce soit.

Le deuxième programme est la même chaîne suivie de la partie B. La partie B est basée sur un quine simple; il imprime une chaîne précédée d'une version d'échappement de celui-ci. Cela signifie qu'il imprime la chaîne et les deux parties A et B.

PhiNotPi
la source
Je pense que cela prouve définitivement, sans aucun doute, la validité d'Element en tant que langage de programmation. Il est si facile à utiliser que moi, si inexpérimenté que je n'ai réussi qu'à écrire un seul interprète complet pour Element, j'ai pu répondre à cette question avant toute autre personne sur cette planète entière de 7.000.000.000 de personnes. Le paradigme «un caractère, une fonction, tout le temps» de l'élément signifie que tout le code est complètement sans ambiguïté. Le langage est polyvalent: à l'exception de []{}, toute commande peut être placée n'importe où dans le programme entier sans provoquer d'erreur de syntaxe. Il est parfait.
PhiNotPi
4
Un peu biaisé, n'est-ce pas? ;-)
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

Il est exécuté dans MSAccess pour utiliser l' Moduleobjet. Le module est nommé "Q"pour le golf. La différence de syntaxe vient du If ... Thenmanque de la version plus courte.

Gaffi
la source
vous pouvez très probablement vous en sortir en passant vbCrLFàvbCr
Taylor Scott
3

C ++, score de 0,734194

Le code source suivant imprime une méta quine d'ordre 999 sur la console (explication ci-dessous):

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

La seule ligne qui change est la première ligne. La valeur de Xsera 1000, 999, 998, ..., 3, 2, puis il recommencera. Cependant, afin d'obtenir des arborescences de syntaxe différentes à chaque fois,X est représenté en termes de factorisation en nombre premier, où chaque nombre premier est écrit comme une somme de 1s. Les AST sont différents, car la factorisation principale des entiers est différente pour chaque valeur.

Le programme s'imprimera lui-même, sauf que la première ligne est modifiée et les contre-obliques, les sauts de ligne et les retraits qui se trouvent à l'intérieur Q(...) seront supprimés.

Le programme suivant calcule le score de ma réponse:

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

Il a imprimé 0.734194 sur la console. Évidemment, 1000 peut être remplacé par des entiers plus grands et le score approchera 0 comme sa limite. La preuve mathématique implique que la fonction Zeta de Riemann est quelque peu alambiquée. Je le laisse comme un exercice au lecteur. ;)

Ralph Tandetzky
la source
2

JavaScript, 84,5 64 61

Deux programmes, tous deux d'une longueur de 169 128 122.

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

Avant de jouer au golf, pour votre plus grand plaisir:

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

Renvoie le nouveau programme et sort la partie actuelle! Je pourrais probablement le raccourcir sans la fonction regex, mais ... je ne veux pas.

Ry-
la source
Non, ils sont distincts sur le plan statistique. Une fois que vous avez ajouté les sauts de ligne, c'est.
Ry-
2

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

Notez que les chaînes en J ne sont pas les anti-slash échappé, mais devis échappé à la Pascal: 'I can''t breathe!'.

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

Le programme 1 a AST noun verb hook nounet le programme 2 a ASTnoun . Le programme 2 est une version citée du programme 1, qui renverra simplement le programme 1 lors de son exécution, donc cette méthode ne peut pas être étendue à trois copies aussi facilement: P

Le programme 1 fonctionne en prenant une copie de la partie code de la source, avec une citation ajoutée à l'avant, et en ajoutant cinq de ces citations à la fin ( (,5#{.)). Ensuite, il prend cycliquement 30 caractères de cette chaîne de 16 caractères, ce qui donne exactement le programme 2 comme résultat.

algorithmshark
la source