¿Puedes Meta Quine?

25

Similar a otros acertijos de quine (más específicamente, este ), escriba un programa que produzca la fuente por sí mismo.

Aquí está el nuevo giro: el código producido NO debe ser idéntico a la fuente. Más bien, debería generar un programa diferente que creará el primero.

El desafío vinculado a lo anterior lo logró saltando entre dos idiomas. Estoy pensando que este se haría en un solo idioma , pero las dos (o más) versiones de la fuente deberían ser significativamente diferentes (ver las reglas a continuación). Con esta restricción, las respuestas de un solo carácter se rechazarían, lo que requeriría un poco más de reflexión para una presentación final.


REGLAS

  1. Su código debe ser producido en un solo idioma. (Múltiples presentaciones, una para cada idioma es perfectamente aceptable).
  2. Sus diferentes versiones de código deben ser sintácticamente distintas. En otras palabras, si fuera a dibujar un árbol de sintaxis abstracta para su código, debería haber al menos un nodo diferente.
    • No será necesario proporcionar un AST , pero si se siente inclinado a proporcionar uno para cada uno de sus programas, sería útil para juzgar.
  3. Puede producir tantas iteraciones como desee, siempre que todas sigan siendo sintácticamente distintas. (Más ayudará a su puntaje, ver más abajo).

TANTEO

Su puntaje final será la duración media de todos sus programas, dividida por el número de programas.

Ejemplo 1:

A (fuente de B) = 50 caracteres
B (fuente de A) = 75 caracteres
Puntuación final = 31.25

Ejemplo 2

A (fuente de B) = 50 caracteres
B (fuente de C) = 75 caracteres
C (fuente de A) = 100 caracteres
Puntuación final = 25

Gaffi
fuente
18
Me meta quine una vez.
mellamokb
1
@mellamokb har har ;-)
Gaffi
En realidad, esta es solo una versión más general de este desafío quine, y las respuestas dadas allí también ganarán aquí.
dejó de girar en contra del reloj el
@leftaroundabout, el requisito de diferencias sintácticas invalida una 'quine giratoria', por lo que esto no es más general.
Boothby
2
Nunca meta quine no me gustó.
Stack Tracer

Respuestas:

35

Python, 0 (límite de (68 + 3 n ) / (16 n ))

Si dos árboles de sintaxis abstractas son diferentes si tienen constantes diferentes,

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

Hay 16 n programas de duración como máximo 68 + 3n, dando una puntuación asintótica de 0.

Si desea programas con estructura variable, podemos implementar un sumador binario en n bits. Aquí, hay 2 n programas de longitud O ( n 2 ). Entra en un ciclo debido a la caída del bit de transporte.

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
fuente
¿Puedo estar confundido? Parece que la salida es idéntica a la fuente (¿no es el objetivo de este desafío)?
Gaffi
Mira en el bloque anidado. passcambiará ay de t=n(t)regreso, en todas las combinaciones de 2 ^ n.
stand
Ya veo eso ahora. Me confundiste con toda la repetición!
Gaffi
22
Por alguna razón, me gustan las soluciones de golf muy largas con puntajes pequeños.
stand
¡Wow, lo poseías por completo! Muy agradable.
Claudiu
4

Perl, puntaje de 110.25

Tengo que admitir que no soy muy bueno con quines. Estoy 100% seguro de que hay margen de mejora. La solución se basa en el mismo principio de la solución Element a continuación.

El primer programa tiene 264 caracteres.

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

El segundo programa tiene 177 caracteres.

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

Estoy trabajando en el AST para esta entrada (y la entrada Element).


Elemento , puntaje de 47.25

El primer programa tiene 105 caracteres.

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

El segundo programa tiene 84 caracteres.

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

Estoy seguro de que hay mucho margen de mejora.

En el primer programa hay una cadena (en la que se escapa cada carácter, a pesar de la redundancia) seguida de las partes ejecutables A y B. La Parte A hace varias cosas: imprime la cadena y escapa de cada carácter, imprime la última mitad de la cadena (que es la fuente de la parte B), y luego evita que la parte B que le sigue haga algo.

El segundo programa es la misma cadena seguida de la parte B. La Parte B se basa en una quine simple; imprime una cadena precedida por una versión escapada de ella. Esto significa que imprime la cadena, y ambas partes A y B.

PhiNotPi
fuente
Creo que esto definitivamente, más allá de cualquier duda, prueba la validez de Element como lenguaje de programación. Es tan fácil de usar que yo, tan inexperto que solo he logrado escribir un intérprete completo para Element, he podido responder esta pregunta antes que cualquier otra persona en este planeta de 7,000,000,000 de personas. El paradigma de "un personaje, una función, todo el tiempo" de Element significa que todo el código es completamente inequívoco. El lenguaje es versátil: a excepción de []{}, cualquier comando se puede colocar en cualquier parte del programa completo sin causar un error de sintaxis. Es perfecto.
PhiNotPi
44
Un poco parcial, ¿estamos? ;-)
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

Esto se ejecuta en MSAccess para hacer uso del Moduleobjeto. El módulo lleva el nombre "Q"del golf. La diferencia en la sintaxis proviene de la If ... Thenfalta de la versión más corta.

Gaffi
fuente
puede muy probablemente salirse con cambiar vbCrLFavbCr
Taylor de Scott
3

C ++, puntaje de 0.734194

El siguiente código fuente imprime una meta quine de orden 999 en la consola (explicación a continuación):

#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 única línea que cambia es la primera línea. El valor de Xserá 1000, 999, 998, ..., 3, 2 y luego comenzará de nuevo. Sin embargo, para obtener diferentes árboles de sintaxis cada vez, Xse representa en términos de su factorización prima, donde cada primo se escribe como una suma de 1s. Los AST son diferentes, porque la factorización prima de los enteros es diferente para cada valor.

El programa se imprimirá solo, excepto que la primera línea se cambia y las barras invertidas, los saltos de línea y las hendiduras que se encuentran dentro Q(...)se eliminarán.

El siguiente programa calcula el puntaje de mi respuesta:

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

Imprimió 0.734194 en la consola. Obviamente, 1000 pueden ser reemplazados por enteros más grandes y la puntuación se acercará a 0 como su límite. La prueba matemática implica que la función Zeta de Riemann es algo complicada. Lo dejo como ejercicio para el lector. ;)

Ralph Tandetzky
fuente
2

JavaScript, 84.5 64 61

Dos programas, ambos de duración 169 128 122.

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

Antes de jugar al golf, para su placer visual:

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

¡Devuelve el nuevo programa y genera la parte actual! Probablemente podría acortarlo sin la función regex, pero ... no quiero hacerlo.

Ry-
fuente
No, son sintácticamente distintos. Una vez que agregue las nuevas líneas, eso es.
Ry-
2

J - (24 + 30) / 2/2 = 13.5 pts

Tenga en cuenta que las cadenas en J no son los escapados, pero Cotización en escaparon a la Pascal: 'I can''t breathe!'.

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

El programa 1 tiene AST noun verb hook nouny el programa 2 tiene AST noun. El programa 2 es una versión citada del programa 1, que solo devolverá el programa 1 cuando se ejecute, por lo que este método no se puede extender a tres copias tan fácilmente: P

El programa 1 funciona tomando una copia de la parte del código de la fuente, con una cita adjunta al frente, y agregando cinco de esas citas al final ( (,5#{.)). Luego, toma cíclicamente 30 caracteres de esta cadena de 16 caracteres, lo que da exactamente el Programa 2 como resultado.

Algoritmo de tiburón
fuente