Você pode Meta Quine?

25

Semelhante a outros quebra-cabeças quine (mais especificamente, este ), escreva um programa que produza a fonte por si mesmo.

Aqui está a nova reviravolta: O código produzido NÃO deve ser idêntico à fonte. Em vez disso, ele deve gerar um programa diferente que criará o primeiro.

O desafio vinculado acima conseguiu isso saltando entre dois idiomas. Eu estou pensando que este seria feito em apenas um idioma , mas as duas (ou mais) versões da fonte devem ser significativamente diferentes (consulte as regras abaixo). Com essa restrição, as respostas de um único caractere seriam proibidas, exigindo, assim, um pouco mais de reflexão para uma submissão final.


REGRAS

  1. Seu código deve ser produzido em apenas um idioma. (Vários envios, um para cada idioma é perfeitamente aceitável.)
  2. Suas diferentes versões de código devem ser sintaticamente distintas. Em outras palavras, se você desenhar uma árvore de sintaxe abstrata para seu código, deve haver pelo menos um nó diferente.
    • Fornecimento de uma AST não será necessário, mas se você se sentir inclinado a fornecer um para cada um de seus programas, ele iria ajudar no julgamento.
  3. Você pode produzir quantas iterações desejar, desde que todas permaneçam sintaticamente distintas. (Mais ajudará sua pontuação, veja abaixo.)

PONTUAÇÃO

Sua pontuação final será a duração média de todos os seus programas, dividida pelo número de programas.

Exemplo 1:

A (fonte para B) = 50 caracteres
B (fonte para A) = 75 caracteres
Pontuação final = 31,25

Exemplo 2:

A (fonte para B) = 50 caracteres
B (fonte para C) = 75 caracteres
C (fonte para A) = 100 caracteres
Pontuação final = 25

Gaffi
fonte
18
Eu meta quine uma vez.
precisa saber é o seguinte
1
@mellamokb har har ;-)
Gaffi
Na verdade, essa é apenas uma versão mais geral desse desafio do quine, e as respostas dadas lá também ganharão aqui.
deixou de girar no sentido contrário
@leftaroundabout, o requisito para diferenças sintáticas invalida um 'quine rotativo', então isso não é mais geral.
usar o seguinte código
2
Nunca meta quine que eu não gostei.
Pilha Tracer

Respostas:

35

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

Se duas árvores de sintaxe abstrata forem diferentes se tiverem 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)

existem 16 n programas de duração no máximo 68 + 3n, resultando em pontuação assintótica de 0.

Se você deseja programas com estrutura variável, podemos implementar um somador binário em n bits. Aqui, existem 2 n programas de comprimento O ( n 2 ). Entra em um ciclo devido à queda do 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
fonte
Posso estar confuso? Parece que a saída é idêntica à fonte (não é o objetivo deste desafio)?
Gaffi
Olhe no bloco aninhado. passmudará para t=n(t)e para trás, em todas as 2 ^ n combinações.
Boothby
Eu vejo isso agora. Você me confundiu com toda a repetição!
Gaffi
22
por alguma razão, gosto de soluções de golfe muito longas com pontuações minúsculas.
usar o seguinte código
Uau, você era o dono disso! Muito agradável.
Claudiu
4

Perl, pontuação de 110,25

Eu tenho que admitir, eu não sou muito bom com quines. Estou 100% certo de que há espaço para melhorias. A solução é baseada no mesmo princípio da solução Element abaixo.

O primeiro programa tem 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"}

O segundo programa tem 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"}

Estou trabalhando no AST para esta entrada (e a entrada Elemento).


Elemento , pontuação de 47,25

O primeiro programa tem 105 caracteres.

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

O segundo programa tem 84 caracteres.

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

Tenho certeza de que há muito espaço para melhorias.

No primeiro programa, há uma string (na qual todo caractere é escapado, apesar de muita redundância), seguida pelas partes executáveis ​​A e B. A parte A faz várias coisas: imprime a string e escapa de cada caractere, imprime a última metade da string (que é a fonte da parte B) e impede que a parte B que a segue faça qualquer coisa.

O segundo programa é a mesma sequência seguida pela parte B. A parte B é baseada em uma simples coluna; imprime uma string precedida por uma versão escapada dela. Isso significa que ele imprime a sequência e as duas partes A e B.

PhiNotPi
fonte
Eu acho que isso definitivamente, sem qualquer dúvida, prova a validade do Element como uma linguagem de programação. É tão fácil de usar que eu, tão inexperiente que só consegui escrever um intérprete completo para a Element, fui capaz de responder a essa pergunta antes de qualquer outra pessoa neste planeta inteiro de 7 milhões de milhões de pessoas. O paradigma "um caractere, uma função, o tempo todo" do elemento significa que todo o código é completamente inequívoco. A linguagem é versátil: exceto por []{}, qualquer comando pode ser colocado em qualquer lugar do programa inteiro sem causar um erro de sintaxe. É perfeito.
PhiNotPi
4
Um pouco tendencioso, não é? ;-)
Gaffi 15/04
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

Isso é executado no MSAccess para fazer uso do Moduleobjeto. O módulo é nomeado "Q"para o golfe. A diferença na sintaxe vem da If ... Thenfalta da versão mais curta.

Gaffi
fonte
você pode provavelmente começar afastado com a mudança vbCrLFparavbCr
Taylor Scott
3

C ++, pontuação de 0,734194

O código-fonte a seguir imprime uma meta quine da ordem 999 no console (explicação abaixo):

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

A única linha que muda é a primeira linha. O valor de Xserá 1000, 999, 998, ..., 3, 2 e, em seguida, será iniciado novamente. No entanto, a fim de obter diferentes árvores de sintaxe a cada vez, Xé representado em termos de sua fatoração primária, onde cada primo é escrito como uma soma de 1s. Os ASTs são diferentes, porque a fatoração primária de números inteiros é diferente para cada valor.

O programa será impresso automaticamente, exceto que a primeira linha é alterada e as barras invertidas, quebras de linha e recuos internos Q(...)serão removidas.

O programa a seguir calcula a pontuação da minha resposta:

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

Ele imprimiu 0,734194 no console. Obviamente, 1000 podem ser substituídos por números inteiros maiores e a pontuação se aproximará de 0 como seu limite. A prova matemática envolve a função Zeta de Riemann, que é um tanto complicada. Deixo isso como um exercício para o leitor. ;)

Ralph Tandetzky
fonte
2

JavaScript, 84,5 64 61

Dois programas, ambos com comprimento 169 128 122.

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

Antes de jogar, para seu prazer:

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

Retorna o novo programa e produz a peça atual! Eu provavelmente poderia torná-lo mais curto sem a função regex, mas ... eu não quero.

Ry-
fonte
Não, eles são sintaticamente distintos. Depois de adicionar as novas linhas, é isso.
Ry-
2

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

Note que strings em J não são a escapado barra invertida-, mas citação-escapou à la Pascal: 'I can''t breathe!'.

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

O programa 1 possui AST noun verb hook noune o programa 2 possui AST noun. O programa 2 é uma versão citada do programa 1, que retornará o programa 1 apenas quando executado, portanto, esse método não pode ser estendido para três cópias com facilidade: P

O Programa 1 opera tirando uma cópia da parte do código da fonte, com uma citação anexada à frente e adicionando cinco dessas aspas ao final ( (,5#{.)). Em seguida, ele usa ciclicamente 30 caracteres dessa seqüência de 16 caracteres, o que fornece exatamente o Programa 2 como resultado.

algoritmshark
fonte