Gerador de Quine Generalizado


19

O desafio

Neste desafio, você especifica um idioma de origem S e um idioma de destino T . Sua tarefa é escrever o seguinte programa Pno idioma S. Se um programa válido Qno idioma Tfor fornecido como entrada P, ele produzirá um programa válido Rno idioma Tque não recebe entradas e saídas Q(R), ou seja, o programa Qaplicado ao código fonte de R. Além disso , você deve apresentar em sua resposta um programa de exemplo não trivial Q(quanto mais interessante, melhor, embora você não marque pontos), o programa resultante Re a saída de R. Este é o código-golfe, então o código mais curto para Pvitórias.

Em outras palavras, esse é um desafio sobre escrever um "construtor universal de quine" que possa criar tipos arbitrários de quines generalizados.

Esclarecimentos

  • Seus idiomas de origem e destino podem ser idênticos.
  • O programa Pdeve pegar uma string como entrada (de STDIN ou equivalente) e gerar uma string (para STDOUT ou equivalente), como todos os programas de saída R.
  • Os programas de entrada Qtambém devem transformar uma sequência em outra, mas sua forma é mais flexível: eles podem ser funções de sequência a sequência, trechos de código que modificam uma variável com um determinado nome, trechos que modificam a pilha de dados se o idioma de destino você também pode restringir ainda mais a forma dos Q, afirmando que, por exemplo, eles podem não conter comentários. No entanto, você deve poder implementar qualquer função cadeia a cadeia computável como um programa de entrada Qe deve declarar explicitamente como eles funcionam e quais restrições adicionais você impõe a eles.
  • O programa de saída Rdeve realmente ser um quine (generalizado), portanto, não deve ler nenhuma entrada (entrada do usuário, arquivos etc.), a menos que o Qfaça.
  • As brechas padrão não são permitidas.

Um exemplo

Suponha que eu escolha Python como idioma de origem e Haskell como idioma de destino, além de exigir que o programa de entrada seja uma definição de uma linha de uma String -> Stringfunção denominada f. Se eu der o programa de reversão de string

f x = reverse x

como entrada para o meu programa Python P, ele produzirá o código fonte de outro programa Haskell R. Este programa imprime em STDOUT o código fonte R, mas invertido. Se Pfor dada a função de identidade

f x = x

como entrada, o programa de saída Ré um quine.

Respostas:


7

Origem = Destino = CJam, 19 17 16 bytes

{`"_~"+}`)q\"_~"

Isso pressupõe que o programa de entrada Q(fornecido no STDIN) seja um trecho de CJam que espera uma string no topo da pilha e deixa outra string no topo da pilha.

Teste aqui.

Exemplos

  1. A identidade seria apenas um trecho vazio, deixando STDIN impressões vazias

    {`"_~"+}_~
    

    Qual é o quine padrão, com um adicional +.

  2. Para inverter uma string no CJam, você pode usar W%, colocando isso em STDIN, isso gera:

    {`"_~"+W%}_~
    

    que podemos correr para obter

    ~_}%W+"~_"`{
    
  3. Como um terceiro exemplo, digamos que nós usamos um trecho que intercala uma string com espaços: ' *. Correndo Pcom isso como entrada, obtemos

    {`"_~"+' *}_~
    

    que por sua vez imprime

    { ` " _ ~ " + '   * } _ ~  
    
  4. Agora também funciona se Qcontiver quebras de linha (embora isso nunca seja necessário no CJam). Aqui está um programa com uma quebra de linha, que remove todas as quebras de linha de uma string (de maneira desnecessariamente complicada - divida em linhas e junte-se):

    N/
    ""
    *
    

    Isso resulta no seguinte R:

    {`"_~"+N/
    ""
    *}_~
    

    que por sua vez imprime

    {`"_~"+N/""*}_~
    

Explicação

Vamos dar uma olhada na saída produzida primeiro:

O padrão CJam quine é

{`"_~"}_~

Funciona da seguinte maneira:

  • Empurre o bloco {`"_~"}.
  • Duplique com _.
  • Execute a cópia com ~.
  • Agora dentro do bloco, `transforma o primeiro bloco em sua representação de cadeia.
  • "_~" empurra os dois caracteres da fonte que não fazem parte do bloco (e, portanto, faltam na representação da string).
  • As duas cadeias são impressas de costas para trás no final do programa.

Na rotina básica, isso `é desnecessário, porque se você deixar o bloco como está, ele será impresso da mesma forma no final do programa.

A saída do meu programa Pé uma versão modificada deste trecho. Primeiro, adicionei um +ao bloco, que concatena as duas cadeias em uma cadeia contendo a fonte inteira. Observe que isso será verdade, não importa o que eu faça dentro do bloco, porque tudo isso será adicionado à representação de string obtida com `. Agora eu posso simplesmente colocar o programa / snippet Qdentro do bloco após o +, para que ele possa modificar a string de origem antes de ser impressa. Novamente, uma vez que Qentra no bloco, ele fará parte da referida string de origem.

Em resumo, as Pimpressões

{`"_~"+Q}_~

Agora, como eu construo essa saída em P:

{`"_~"+}         "Push the block without Q.";
        `        "Turn it into a string. This is shorter than writing a string right away,
                  because I'd have to escape the quotes, and I'd need two quotes instead of
                  one backtick.";
         )       "Pop off the last character (the brace) and push it on the stack.";
          q      "Read input Q.";
           \     "Swap Q with the brace.";
            "_~" "Push the final two characters.";

As quatro seqüências são impressas automaticamente (lado a lado) no final do programa.


11
Bem, isso foi rápido! E certamente difícil de bater. A explicação também é legal.
Zgarb 11/11

Onde você aprendeu que W% reverte? dl.dropboxusercontent.com/u/15495351/cjam.pdf não tê-lo
Faraz Masroor

Existe uma lista mais completa de métodos?
Faraz Masroor 07/04

@FarazMasroor sourceforge.net/p/cjam/wiki/Basic%20operators/#percent (nº 3) ... é um recurso emprestado do GolfScript e em algum momento alguém me disse que é assim que funciona no GolfScript. Parece ser um idioma tão comum que é um conhecimento implícito estranho que todo usuário de CJam / GS possui, mas que na verdade não é explicado em muitos lugares. (Para mais, e não operadores bem documentados, consulte sourceforge.net/p/cjam/wiki/Operators )
Martin Ender

3

Expressões haskell → Expressões haskell, 41 bytes

((++)<*>show).('(':).(++")$(++)<*>show$")

Experimente online!

Como funciona

P $ "Q"= ((++)<*>show).('(':).(++")$(++)<*>show$") $ "Q"constrói "R"por

  1. (++")$(++)<*>show$"): anexando a string ")$(++)<*>show$",
  2. ('(':): anexando o caractere '('e
  3. (++)<*>show(= \x->x++show x): anexando uma versão citada disso,

resultando em "R"= "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\"".

R= (Q)$(++)<*>show$"(Q)$(++)<*>show$"trabalha por

  1. pegando a corda "(Q)$(++)<*>show$",
  2. (++)<*>show: anexando uma versão citada disso,
  3. aplicando Qa isso,

resultando em Q "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\""= Q "R".

(Os parâmetros Qsão necessários porque Qpodem conter $tão facilmente quanto o Rfazem e, $infelizmente, são associativos.)

Demo

λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "id"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ (id)$(++)<*>show$"(id)$(++)<*>show$"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "reverse"
(reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
λ> putStrLn $ (reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
"$wohs>*<)++($)esrever("$wohs>*<)++($)esrever(
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "length"
(length)$(++)<*>show$"(length)$(++)<*>show$"
λ> print $ (length)$(++)<*>show$"(length)$(++)<*>show$"
44

Não apenas $precisa dos parênteses, mas também à direita let, doou expressões lambda.
Ørjan Johansen

@ ØrjanJohansen Certo, mas eu poderia ter definido um subconjunto de idiomas que não permite lambda não parênteses / let/ if/ case/ dose eu não os emitir. Talvez seja tão bom que eu não precisei.
Anders Kaseorg

2

Fonte = Destino = JavaScript, 66

console.log("function a(){console.log("+prompt()+"(a+'a()'))}a()")

Pressupostos para Q:

  • Q deve ser uma função anônima JavaScript string a string.

Exemplos:

  • Reverso . Q =function(s) { return s.split('').reverse().join(''); }

Nesse caso, P(Q)(ou R) será: function a(){console.log(function(s) { return s.split('').reverse().join(''); }(a+'a()'))}a()e, executando-o, obteremos: )(a}))')(a'+a(} ;)''(nioj.)(esrever.)''(tilps.s nruter { )s(noitcnuf(gol.elosnoc{)(a noitcnufque é exatamente o mesmo que Q(R).

  • Identidade . Q =function(s) { return s; }

nesse caso, P(Q)(ou R) será: function a(){console.log(function(s) { return s; }(a+'a()'))}a()que é um JavaScript Quine . Escusado será dizer Q(R)que será o mesmo, pois Q é a função de identidade.


Algumas notas:

STDIN em JavaScript é tradicionalmente prompt(), no entanto, eu me permiti abster-me da tradição de alert()STDOUT, a fim de facilitar o processo de execução da saída como um programa usando copiar e colar. (Percebo que posso salvar até 12 caracteres ao mudar para alert()).

Também posso tornar as coisas muito mais curtas no ES6, mas quero continuar com o JavaScript nativo por enquanto. Estou pensando em enviar uma resposta S = Scala, T = ECMA6 no futuro, apenas para a experiência.

Também sei que o JavaScript quase nunca consegue vencer o CJam no , mas tive que aceitar esse desafio! Foi grosseiramente divertido.


Obrigado! Seria realmente legal ter uma entrada com diferentes idiomas de origem e de destino.
Zgarb 18/11/19

2

Geléia7 , 9 bytes

“ṚƓ^ṾṂ’³3

Experimente online!

Q é uma função 7 (ou seja, que não olha para além do elemento superior da pilha e faz E / S via pilha) e é fornecida como um argumento da linha de comando.

Explicação

O programa 7

O construtor universal de quine em 7 que eu uso aqui é:

717162234430…3

A primeira coisa a se notar é que o 7 inicial é o equivalente ao espaço em branco inicial e não afeta o programa. A única razão para existir é obedecer às regras do PPCG contra quines somente literais (é codificado pelo segundo 1no programa e não por ele próprio).

O resto do programa é um único elemento pilha (ela tem equilibrado 7s e 6s), que faz o seguinte quando executado:

717162234430…3
 1716           Push a stack element "7" onto the stack
     2          Copy it
      23        Pop and output one of the copies (selecting format 7)
        4430    Prepend it to the top of stack
             3  Output it

Em outras palavras, esse elemento da pilha é um programa que imprime a parte superior da pilha, com o 7formato de saída 7 anexado (que significa "imprimir literalmente, usando a mesma codificação que o código-fonte") e, portanto, é claramente a melhor codificação para quines). É bastante sorte aqui podermos reutilizar o literal 7para dois propósitos (o formato de saída e o espaço em branco à esquerda). Claramente, inserindo algo logo antes da final 3, podemos gerar uma função de 7+ a entrada, em vez de apenas produzir 7e entrada diretamente.

Como esse elemento de pilha obtém seu próprio código-fonte? Bem, quando o final do programa é alcançado, 7 evalé o elemento da pilha superior por padrão. No entanto, ele não é realmente retirado da pilha no processo, portanto o literal do elemento da pilha que foi evalconduzido ainda está lá. (Em outras palavras, o programa não está lendo sua própria fonte - como evidenciado pelo fato de não poder ver o 7arquivo no início do programa, que é um separador de elementos da pilha e não parte de um literal - mas sim consiste principalmente de um literal que é evalliderado por padrão.)

O programa Jelly

Este é talvez um dos programas Jelly menos parecidos com o que eu já escrevi; ele é composto por três nilads ( “ṚƓ^ṾṂ’, ³, 3), que são emitidos apenas em sequência porque não há operações são realizadas em cima delas. O 3é bastante óbvio, apenas sendo uma constante inteira. A ³também é simples se você sabe Jelly: é notação explícita de geléia para o primeiro argumento de linha de comando (que é onde Jelly normalmente leva sua entrada). O restante do programa Jelly representa a maior parte do meu construtor universal de 7 quine: explorando o fato de que todos os comandos no 7 podem ser representados usando dígitos ASCII, podemos interpretar717162234430não como uma série de comandos, ou mesmo como um número octal (como é conceitualmente), mas como um número decimal, o que significa que não precisamos de nenhuma formatação especial para a saída. Esse número decimal se torna “ṚƓ^ṾṂ’na notação inteira comprimida de Jelly.

Exemplo

Se dermos 24053como programa Q, obteremos a seguinte saída:

717162234430240533

Experimente online!

2405 concatena o elemento da pilha superior para si mesmo:

2405   Stack   Explanation
       x
2      x|x     Duplicate top of stack
 4     x||x    Swap two stack elements, with an empty element between
  0    x|(X)   Escape the top stack element, then concatenate the top two
   5   xx      Execute the top stack element

(A última etapa pode parecer um pouco confusa; o que está acontecendo é que escapar de um elemento da pilha converte cada comando nele de "execute este comando" para "anexar esse comando ao topo da pilha", de modo que cada comando se anexa ao original elemento da pilha superior à medida que é executado.)

Como tal, a execução do programa resultante R fornece duas cópias de R:

7171622344302405371716223443024053

2

CJam → CJam, 13 bytes

{`"_~"+7}_~qt

Experimente online!

A entrada Qdeve ser um trecho de código que modifica a única sequência na pilha. Qé lido de stdin.

Exemplo

Entrada:

S*W%

Ele adiciona um espaço entre cada dois caracteres e inverte a string.

Resultado:

{`"_~"+S*W%}_~

Saída da solução generalizada:

~ _ } % W * S + " ~ _ " ` {

Explicação

{`"_~"+7}_~      e# Evaluate a generalized quine in CJam that only appends a 7.
q                e# Read the input.
t                e# Replace the 7th character (0-based) with the input.

Primeiro, ele avalia o quine, para que possamos obter sua representação de string sem aspas duplas desnecessárias. Em seguida, substitua a carga útil pela entrada.

Pode ser {`"_~"+ }_~7qtonde o espaço é o espaço reservado para a carga útil. Mas alterar a carga útil para 7economizar um byte.


1

CarvãoPerl (5), 29 33 bytes

A$_=q(αA);evalβαS"\α$_β\n";printβ

Experimente online!

O programa Perl Q deve retornar um trecho que leva a entrada como uma string para o lado direito e fornece saída na variável $_. (As funções arbitrárias de Perl podem ser convertidas para esse formulário, agrupando-as como sub x {…}; $_=x. Na maioria dos casos, porém, a sintaxe de Perl significa que nenhuma quebra é necessária.)

Explicação

The Perl

Aqui está a aparência do construtor universal Perl quine:

$_=q(…"\$_=q($_);eval";print);eval

(Na maioria dos casos, você gostaria disso $_=q(say…"\$_=q($_);eval");eval, mas não tenho certeza de que você pode inserir um código Perl arbitrário nele).

Em outras palavras, temos um invólucro externo $_=q(…);evalque atribui uma string $_e a avalia. Dentro do invólucro está "\$_=q($_);eval", ou seja, uma reconstrução do invólucro junto com seu conteúdo, usando o valor armazenado $_, mais o código Q especificado pelo usuário, mais printpara imprimir a saída. (Infelizmente, não podemos usá- saylo; ele adiciona uma nova linha, e isso é relevante em quines.)

O carvão

O "ponto" desta resposta era produzir quines generalizadas em Perl, então, quando eu tive uma estratégia de golfe para fazer isso (uma que eu já usei em muitas outras respostas), era hora de escrever o programa P, que basicamente substitui uma string em um modelo. O que eu queria aqui era uma linguagem que fosse boa para imprimir seqüências constantes (idealmente comprimindo-as um pouco) e interpolar a entrada do usuário nelas.

Depois de experimentar alguns, decidi pelo carvão vegetal, que nunca havia usado antes (e que poderia realmente fazer com alguma documentação); Ele foi projetado para a arte ASCII, mas também é capaz de escrever strings em uma dimensão. Os caracteres ASCII são impressos literalmente em carvão vegetal, o que significa que a impressão de seqüências constantes não requer clichê, e podemos usar o comando para interpolar uma sequência retirada da entrada do usuário no programa.

É possível ir (um pouco) mais curto, no entanto. O construtor de quine universal Perl contém duas seções repetidas bastante longas. Assim, podemos usar o comando para atribuí-los a variáveis ​​(por exemplo, A…αatribui à variável α) e simplesmente interpolar as variáveis ​​na string que estamos imprimindo usando seus nomes. Isso economiza alguns bytes ao escrever apenas a string literalmente.

Infelizmente, o Charcoal também acrescenta uma nova linha ao programa, mas isso não é grande coisa; simplesmente custa dois bytes para que um \nadicione essa nova linha à entrada de Q também.

Exemplo

Se dermos a entrada $_=reverse(que inverte uma string), obtemos a seguinte saída:

$_=q($_=reverse"\$_=q($_);eval\n";print);eval

Experimente online!

que é semelhante a um quine que imprime sua fonte para trás, como esperado.


1

GeléiaSubcarga , 15 bytes

“(a(:^)*“S):^”j

Experimente online!

Pega a função Underload de entrada Q como um argumento semelhante a um comando. O Q deve receber a entrada da pilha e enviar a saída para a pilha, sem tentar inspecionar elementos mais profundos da pilha (pois eles não existirão).

Explicação

The Underload

O construtor de quino universal Underload usado aqui é:

(a(:^)*…S):^

A maior parte do programa é um único literal. Seguimos que :^, que copia e avalia uma cópia (deixando a outra cópia na pilha).

Quando o literal começa a avaliar, executamos a(escape, que o traz de volta à mesma forma que o programa original A) e (:^)*(que acrescenta :^), reconstruindo assim o código fonte do programa inteiro. Podemos então executar a função Q para transformar isso de maneira arbitrária e imprimir o resultado com S.

The Jelly

Não posso usar o Charcoal neste momento porque um intérprete de Underload validador falha no final do programa se o programa terminar com uma nova linha. (Alguns intérpretes do Underload, como o do TIO, não impõem essa regra, mas eu queria ser adequadamente portátil.) Infelizmente, o Charcoal naturalmente adiciona novas linhas à saída. Em vez disso, usei o Jelly, que é quase tão conciso em casos simples como esse; o programa consiste em uma lista literal com dois elementos ( ““”) e os une à entrada ( j), interpolando assim a entrada do usuário no programa.

Exemplo

Usando a entrada :S^(imprima uma cópia e avalie o original), obtemos o seguinte programa Underload:

(a(:^)*:S^S):^

Experimente online!

Isso se imprime infinitamente várias vezes, de uma maneira bastante interessante: depois de executar o comportamento normal do quine, ele é executado evalem uma cópia do que sai . Isso faz com que todo o programa reconstruído seja executado novamente indefinidamente (Underload é recursivo da cauda). Fazer a si mesmo e fazer um evalé realmente a única maneira de fazer um loop infinito no Underload.


Carvão não adiciona mais novas linhas à direita (yay)
somente ASCII

1

RProgN 2 , 11 bytes

'{`{.%s}{'F

Explicação do Programa

'{`{.%s}{'F
'{`{.%s}{'  # Push the string "{`{.%s}{" to the stack.
          F # Format the input with the top of the stack as a template. Which produces {`{.<INPUT>}{

Explicação Quine

O quine produzido é simples, mas usa a funcionalidade de manipuladores de funções incomparáveis ​​no RProgN2 para criar um quine curto e agradável, chamado quine "Looping". É um conceito surpreendentemente semelhante a um <> <quine.

{`{.}{
{`{.}   # Push the function {`{.} to the stack.
     {  # Try to define a new function, fail, loop back to index 1. (Which in turn, skips the function definition.)
 `{     # Push the string "{" to the stack.
   .    # Concatenate the top two values of the stack, which stringifies the function, then appends { to it.
    }   # Try to terminate a function, fail quietly, and terminate the program.

Obviamente, devido à estrutura desse quine, qualquer coisa, exceto as verdadeiras no-ops (que não são rigorosas) pode ser colocada após a função concatenada, e

Algumas quines

  • {`{.i}{: Saídas {}i.{`{. ié apenas a função "inversa"; portanto, este programa gera uma saída invertida.
  • {`{.S§.}{: Saídas ..S`{{{}§. Sconverte a sequência em uma pilha de caracteres, §classifica a pilha lexograficamente e, em seguida, .junta-a novamente, produzindo-se classificada.

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.