2 gatos em um Quine


30

Desafio

Faça dois programas, A e B, que são programas para gatos no mesmo idioma. Quando concatenado, AB (também no mesmo idioma) deve ser quine.

Por exemplo, suponha helloe worldambos sejam programas de gato na linguagem XYZ. Se helloworldfor um problema no idioma mencionado, sua solução é válida.

Para aqueles que não estão familiarizados com gatos e quines, um programa para gatos é aquele que imprime exatamente o que foi fornecido via stdin e um quine é um programa que imprime seu próprio código-fonte.

Pontuação e Regras

  • A contagem total de bytes do programa AB concatenado é sua pontuação. Como este é o código de golfe, a pontuação mais baixa vence.
  • As brechas padrão são proibidas
  • A entrada deve ser obtida de stdin e a saída deve ir para stdout.
  • Os programas cat não precisam levar argumentos; eles só precisam copiar stdin para stdout.
  • O quine deve funcionar quando o programa não recebe nenhuma entrada, mas não precisa funcionar corretamente (mas pode) para outras entradas.
  • O quine não precisa terminar, desde que imprima exatamente seu código-fonte uma vez, nada mais.
  • O quine precisa ter pelo menos um byte de comprimento.
  • A e B podem ser o mesmo programa.
  • O BA não precisa ser um programa ou mesmo um programa válido.

Eu não acho que você deve ter a A e B pode ser mesma regra programa
Muhammad Salman

2
@ MuhammadSalman Minha idéia original era ter um programa de gatos dobrado para se transformar em um quine. Eu só queria abrir a porta para soluções mais fáceis, porque não tinha certeza absoluta de que isso era possível. Parece que eu estava errado em ambos os aspectos, mas estou bem com isso.
Beefster

3
Você provavelmente deve adicionar que ABnão deve estar vazio, pois muitos idiomas têm um gato de 0 byte, permitindo uma correção de 0 byte.
DJMcMayhem

9
@DJMcMayhem um quine de 0 byte não seria um quine válido.
Nissa

4
O que é um programa para gatos?
Pedro A

Respostas:


32

V , 2 + 2 == 4 bytes

2i2i

Experimente o quine!

Experimente o gato!

A é2i

B também é2i

Como funciona?

Primeiro, algumas explicações de como o V funciona. Uma coisa notável que torna essa resposta possível é que, em V, o programa vazio é um programa para gatos. Este não é um caso especial, é inerente ao modo como o V opera. Na inicialização, todas as entradas são carregadas em um "buffer", cada comando modifica o buffer de alguma maneira e, quando o programa é concluído, o buffer é impresso implicitamente. Isso significa que qualquer sequência de NOPs também é um programa para gatos.

O icomando significa entrar no modo de inserção , o que significa que todos os caracteres a seguir iserão adicionados ao buffer. Com um número anterior, esse texto será duplicado n vezes.

Isso significa que, para o programa cat, nada será adicionado ao buffer e será impresso conforme foi lido. Em outras palavras:

        " (Implicitly) Load all input
2       " 2 times,
 i      " Insert the following text into the buffer...
        " (nothing)
        " (Implicitly) Print the buffer

Mas para o quine, há texto após o i:

2       " 2 times,
 i      " Insert the following text into the buffer...
  2i    "   "2i"
        " (Implicitly) Print the buffer

Insolente insolente

V , 0 bytes

Experimente online!

A é o programa vazio.

B também é o programa vazio.

: P


21
Em qualquer outro idioma: Oi, chegamos a um beco sem saída! . V: * publica padrão de qualidade * .
Erik the Outgolfer

13

Ruby, 71 bytes

2;puts (<<2*2+?2)[/.+2/m]||$<.read
2;puts (<<2*2+?2)[/.+2/m]||$<.read
2

Pode ser dividido em gatos da seguinte maneira:

2;puts (<<2*2+?2)[/.+2/m]||$<.read
2

e

;puts (<<2*2+?2)[/.+2/m]||$<.read
2

Os dois gatos são idênticos, exceto os dois principais, que não são opcionais nos três programas. The <<2é um herestring, o que significa que tudo que começa na próxima linha até um 2 final em sua própria linha é uma string, que concatenamos para si mesmo ( *2) e anexamos um 2. à direita. Nos gatos, o herestring é bem formado, mas vazio, para que a expressão regular não corresponda a ela e $<.readpassaremos à expressão e à saída STDOUT. Uma vez que concatemos os gatos, no entanto, a corda não terminará até a terceira linha; portanto, o regex corresponde e fazemos um curto-circuito e produzimos o quine.


11

Pitão, 29 bytes (5 + 24) 27 bytes (5 + 22)

pz=T0?TzjN*2]"pz=T0?TzjN*2]     # Quine
pz=T0                           # Cat A
     ?TzjN*2]"pz=T0?TzjN*2]     # Cat B

Foi divertido.
Experimente o quine aqui
Experimente o primeiro gato aqui
Experimente o segundo gato aqui

Explicações

Cat A
pz=T0
pz       Print the input.
  =T0    (Irrelevant for cat)

Cat B
?TzjN*2]"pz=T0?TzjN*2]
?Tz                      If T (10) is truthy, output the input.
   jN*2]"pz=T0?TzjN*2]   (Irrelevant for cat)

Quine
pz=T0?TzjN*2]"pz=T0?TzjN*2]
pz                            Print the (empty) input (without a newline).
  =T0                         Set T to 0.
     ?Tz                      If T (0) is truthy, output the input.
             "pz=T0?TzjN*2]   Otherwise, get this string...
          *2]                 ... take two copies...
        jN                    ... and join them with a quote.

11

C # (Compilador Visual C #) , 551 bytes

A: 95 bytes

class A{public static int i=2;static void Main(string[]args){System.Console.Write(args[0]);}}//

Experimente online!

B: 438 + 18 bytes

class A{public static int i=0;}
class B{static void Main(string[]args){if(A.i<1){System.Console.Write(args[0]);return;}var a=@"class A{{public static int i=2;static void Main(string[]args){{System.Console.Write(args[0]);}}}}//class A{{public static int i=0;}}
class B{{static void Main(string[]args){{if(A.i<1){{System.Console.Write(args[0]);return;}}var a=@{0}{1}{0};System.Console.Write(a,'{0}',a);}}}}";System.Console.Write(a,'"',a);}}

Experimente online!

A + B: 533 + 18 bytes

class A{public static int i=2;static void Main(string[]args){System.Console.Write(args[0]);}}//class A{public static int i=0;}
class B{static void Main(string[]args){if(A.i<1){System.Console.Write(args[0]);return;}var a=@"class A{{public static int i=2;static void Main(string[]args){{System.Console.Write(args[0]);}}}}//class A{{public static int i=0;}}
class B{{static void Main(string[]args){{if(A.i<1){{System.Console.Write(args[0]);return;}}var a=@{0}{1}{0};System.Console.Write(a,'{0}',a);}}}}";System.Console.Write(a,'"',a);}}

Experimente online!

A e B aceitam a entrada como argumento da linha de comando. A + B ignora qualquer entrada. 18 bytes em B e A + B são adicionados para o/p:StartupObject=B opção enviada ao MSBuild. É estritamente necessário em A + B, mas parecia trapacear também não o ter em B. Dessa forma, os sinalizadores do compilador para A + B são os sinalizadores do compilador para A (nenhum) mais os sinalizadores do compilador para B.

Explicação

O programa A é direto. A classe A contém uma variável estática (não usada) iinicializada 2e imprime seu primeiro argumento quando executado. o// final é importante para o código A + B, mas não faz nada em A.

O programa B é estranho no isolamento, mas essencialmente o mesmo. Ele cria uma Classe A que contém uma variável estática iinicializada e 0, em seguida, executa o método Main da Classe B, que faz o mesmo que o Programa A porque A.ié menor que 1 e retorna antes de qualquer coisa estranha. As novas linhas não são necessárias aqui, mas são importantes para A + B.

Quando combinado, o //Programa A comenta a declaração de Classe A do Programa B, mas, devido à nova linha, a Classe B é boa, permitindo A.ireferir-se ao 2valor do Programa A. O sinalizador do compilador faz com que o programa execute B.Main (), já que o A.Main () também existe. O resultado é que o Programa A + B não gera seu argumento, mas passa para o seguinte segmento de B.Main (), que é basicamente apenas o quine C # padrão .


1
"Os programas de gato ... necessidade de copiar stdin para stdout"
Jakob

9

Haskell , 116 + 20 = 187 175 174 136 bytes

Vários bytes salvos desde que Ørjan Johansen me mostrou interact

Cat 1

g=";main|idmain<-(++\"g=\"++show g++g)=interact idmain|1>0=interact id";main|idmain<-(++"g="++show g++g)=interact id

Experimente online!

Cat 2

main|1>0=interact id

Experimente online!

Quine

g=";main|idmain<-(++\"g=\"++show g++g)=interact idmain|1>0=interact id";main|idmain<-(++"g="++show g++g)=interact idmain|1>0=interact id

Experimente online!


O princípio básico em ação aqui é que, quando adicionamos o segundo gato ao primeiro, alteramos o nome da função com a qual estamos interagindo de apara idmain. Como interact idé um gato, queremos idmainuma função que retorne uma resposta. A solução óbvia seria usar const, no entanto, uma vez que podemos assumir que a entrada está vazia não está codificada e deve ser manuseada manualmente. Nosso próximo gato é bastante padrão, exceto que precisamos torná-lo um código válido quando inserido no final do outro gato, portanto, precisamos que ambos sejam instâncias de guardas de padrões.(++) funciona . A partir daqui, encontramos o código-fonte por meios bastante padrão, temos uma variável gque codifica o código-fonte e usamos um invólucro especial para imprimi-lo na forma de seqüência de caracteres e na forma de código. Há uma pequena exceção de que precisamos colocar nosso codificador na frente, porque já precisamos terminar interact id. Isso significa um extrag=

Estratégia alternativa, 43 + 105 = 186 148

Cat 1

g="";main|idmain<-(++g++show g)=interact id

Experimente online!

Cat 2

main|1>0=interact id where g="g=\"\";main|idmain<-(++g++show g)=interact idmain|1>0=interact id where g="

Experimente online!

Quine

g="";main|idmain<-(++g++show g)=interact idmain|1>0=interact id where g="g=\"\";main|idmain<-(++g++show g)=interact idmain|1>0=interact id where g="

Experimente online!


1
Você pode diminuir um pouco isso substituindo getContents+ putStrpor interact id. Experimente online! (A quine já não funciona com entrada não-vazia, o que permite o uso de uma (++ ...)secção para a idmain.)
Ørjan Johansen

@ ØrjanJohansen Obrigado! Eu não sabia interact, acho que é porque raramente faço coisas de IO com Haskell. Eu editei a postagem.
Wheat Wizard

8

Python 3, 286 bytes

Meu primeiro golfe em Python e minha primeira partida! Não é muito elegante, mas funciona.

Programa A (238 bytes)

from atexit import*;s="from atexit import*;s=%r;register(lambda:print(end='b'in globals()and s%%s or open(0).read()));b=0\nif's'not in vars():print(end=open(0).read())";register(lambda:print(end='b'in globals()and s%s or open(0).read()));

(sem nova linha à direita)

Programa B (48 bytes)

b=0
if's'not in vars():print(end=open(0).read())

(sem nova linha à direita)

Experimente Online

Agradecimentos

  • -24 bytes graças a Jo King
  • -82 bytes graças a Jo King

Você pode fazer end=open...e usar %rem vez de %snão ter que fazer o nova linha e citações
Jo rei

Legal, eu mudei para %r. Não sei o que você quer dizer sobre a nova linha.
Jakob

1
Em vez de %sformatar uma nova linha, você pode simplesmente fazer o literal \n. Você também pode usar ;para dividir instruções em vez de \n(exceto que ifprecisa estar em sua própria linha). %pode ser escapado na string fazendo %%. O único argumento necessário para formatar a string é a própria corda, tudo pode ser listrado
Jo rei

1
O programa B (e o texto) pode ser usado locals()para salvar 2 bytes.
Jonathan Allan

6

C ++ (clang) , 313 + 102 = 415 bytes

Programa A (termina em uma nova linha):

#include<cstdio>
#define Q(x,y)#x,B=#y;x
int c;auto I="#include<cstdio>",A=Q(int main(){if(c)printf("%s\n#define Q(x,y)#x\",\"#y;x\nint c;auto I=\"%s\",A=Q(%s,)\n#ifdef Q\nint n=++c;\n#else\n%s\n%s\n#endif",I,I,A,I,B);else while((c=getchar())>=0)putchar(c);},int c;int main(){while((c=getchar())>=0)putchar(c);})

Programa B (não termina em nova linha):

#ifdef Q
int n=++c;
#else
#include<cstdio>
int c;int main(){while((c=getchar())>=0)putchar(c);}
#endif

Não é muito furtivo e, como de costume, o C ++ não é ótimo para quining. Não ficarei surpreso se houver maneiras de raspar bytes aqui e ali com a mesma idéia. O único problema é mudar o comportamento de algo depois que ele é definido, e um inicializador de variável dinâmica com efeito colateral faz o truque. (Isso pode ser feito em C sem extensões do compilador?)

Experimente on-line: A , B , AB

(A única preocupação de portabilidade de que estou ciente é que o programa pressupõe <cstdio>colocar nomes no espaço de nomes global e em std.)



5

Python 3 , 100 + 37 = 137 bytes

Programa A:

s='s=%r;print(end=open(0).read())#print(end=open(0).read())\nprint(s%%s)';print(end=open(0).read())#

Experimente online!

Programa B:

print(end=open(0).read())
print(s%s)

Experimente online!

Make Quine AB

s='s=%r;print(end=open(0).read())#print(end=open(0).read())\nprint(s%%s)';print(end=open(0).read())#print(end=open(0).read())
print(s%s)

Experimente online!

Funciona apenas quando a entrada está vazia, caso contrário, ela adiciona a entrada à saída.


As aspas duplas devem ser simples.
Jonathan Allan

Falha é permitido?
Jakob

@Jakob A questão não diz que bater é não permitido e, normalmente, a saída para STDERR é ignorado
Jo rei

Ok, é justo. Atalhos inteligentes!
Jakob

4

Adido , 15 + 126 = 141 bytes

UMA:

AllInput[]|Echo

Experimente online!

B:

@{If[_,s.="AllInput[]|Echo@{If[_,s.=%s;;Printf[s,Repr!s],AllInput[]|Echo]es}|Call";;Printf[s,Repr!s],AllInput[]|Echo]es}|Call

Experimente online!

A + B:

AllInput[]|Echo@{If[_,s.="AllInput[]|Echo@{If[_,s.=%s;;Printf[s,Repr!s],AllInput[]|Echo]es}|Call";;Printf[s,Repr!s],AllInput[]|Echo]es}|Call

Experimente online!

Explicação

Cada um dos programas cat codifica AllInput[]|Echo, que é um programa cat simples. B é a principal fase quine; sozinha, é uma função vetorizada (por unária @) chamada sem entradas (sendo chamada como |Call). Assim, a primeira If[_,A,B]execução condicional B, que é simplesmenteAllInput[]|Echo .

Quando A + B é executado, o unário @se torna binário @devido à Echofusão com o lambda:

AllInput[]|Echo@{If[_, ...

Agora, isso significa que o lambda é executado antes de Echo. De volta ao condicional, essa função agora tem todo o STDIN como argumento. Portanto, If[_,A,B]executa A, que é a estrutura padrão de quine.


3

Stax , 16 + 12 = 28 bytes

Cat 1:

"yi|d|ca34b4lr"y

Execute e depure

"yi|d|ca34b4lr"y Full program, implicit input
"yi|d|ca34b4lr"  Push the string
               y Push raw input
                 Implicit output of top item

Cat 2:

i|d|ca34b4lr

Execute e depure

i|d|ca34b4lr Full program, implicit input
i            Don't parse input (prefix directive)
 |d          Push main stack depth, always zero
   |c        Cancel because top item is falsy, and implicitly print
     a34b4lr Never executed

Quine:

"yi|d|ca34b4lr"yi|d|ca34b4lr

Execute e depure

"yi|d|ca34b4lr"yi|d|ca34b4lr Full program
"yi|d|ca34b4lr"              Push the string
               y             Push input
                i            No-op
                 |d          Push main stack depth, i.e. 2
                   |c        Do nothing because top is truthy
                     a       Get the string to the top
                      34     Push 34 (charcode of ")
                        b    Copy both
                         4l  Listify top 4
                           r Reverse
                             Implicit output

3

Cat 1:

Lua , 41 bytes

a=io.read;while a(0)do io.write(a(1))end;

Experimente online!


Cat 2:

Lua , 70 bytes

if a then io.input(arg[0])end;a=io.read;while a(0)do io.write(a(1))end

Experimente online!


Quine:

Lua , 111 bytes

a=io.read;while a(0)do io.write(a(1))end
if a then io.input(arg[0])end;a=io.read;while a(0)do io.write(a(1))end

Experimente online!

io.input(arg[0]) no Cat 2 define o arquivo atual como entrada padrão e, como resultado, o gato imprime o código fonte


1
Bem-vindo ao PPCG
Muhammad Salman

Você pode salvar um byte no gato 1 removendo o último ponto e vírgula?
Muhammad Salman

1
Infelizmente, a leitura do arquivo atual é uma brecha padrão. Mas boa tentativa de qualquer maneira.
Beefster


0

JavaScript (Node.js) , 199 bytes


a=()=>console.log(require('fs').readFileSync(0)+'');a();var a=a||0;b=()=>console.log(require('fs').readFileSync(0)+'');!a?b():c=()=>console.log(`a=${a};a();var a=a||0;b=${b};!a?b():c=${c},c()`),c()

Experimente online!

Cat A, 57 bytes


a=()=>console.log(require('fs').readFileSync(0)+'');a();

Experimente online!

Cat B, 142 bytes

var a=a||0;b=()=>console.log(require('fs').readFileSync(0)+'');!a?b():c=()=>console.log(`a=${a};a();var a=a||0;b=${b};!a?b():c=${c},c()`),c()

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.