2 gatti in un Quine


30

Sfida

Crea due programmi, A e B, che sono entrambi programmi per gatti nella stessa lingua. Se concatenato, AB (anche nella stessa lingua) dovrebbe essere un quine.

Ad esempio, supponiamo helloche worldsiano entrambi programmi per gatti nella lingua XYZ. Se helloworldè un quine in detta lingua, allora la tua soluzione è valida.

Per quelli di voi che non hanno familiarità con gatti e quines, un programma cat è uno che stampa esattamente ciò che gli è stato dato tramite stdin e un quine è un programma che stampa il proprio codice sorgente.

Punteggio e regole

  • Il conteggio dei byte totali del programma AB concatenato è il tuo punteggio. Poiché si tratta di codice golf, vince il punteggio più basso.
  • Sono vietate le scappatoie standard
  • L'input deve essere preso dallo stdin e l'output deve andare allo stdout.
  • Non è necessario che i programmi cat prendano argomenti; devono solo copiare stdin in stdout.
  • Il quine dovrebbe funzionare quando al programma non viene fornito alcun input, ma non deve funzionare correttamente (ma potrebbe) per altri input.
  • Non è necessario terminare il quine, a condizione che stampi esattamente il suo codice sorgente una volta, niente di più.
  • Il quine deve essere lungo almeno un byte.
  • A e B possono essere lo stesso programma.
  • BA non ha bisogno di essere un quine o anche un programma valido.

Non credo che dovresti avere A e B possono essere la stessa regola del programma
Muhammad Salman,

2
@MuhammadSalman La mia idea originale era di raddoppiare un programma per gatti per trasformarlo in un quine. Volevo solo aprire la porta a soluzioni più semplici perché non ero del tutto sicuro che fosse possibile. Sembra che mi sia sbagliato su entrambi i fronti, ma sto bene.
Beefster

3
Probabilmente dovresti aggiungere che ABdeve essere non vuoto, poiché molte lingue hanno un gatto a 0 byte che consente un quine di 0 byte.
DJMcMayhem

9
@DJMcMayhem, tuttavia, un quine di 0 byte non sarebbe un quine valido.
Nissa,

4
Cos'è un programma per gatti?
Pedro A

Risposte:


32

V , 2 + 2 == 4 byte

2i2i

Prova il quine!

Prova il gatto!

A è2i

B è anche2i

Come funziona?

Prima di tutto, alcune spiegazioni su come funziona V. Una cosa notevole che rende possibile questa risposta è che in V, il programma vuoto è un programma cat. Questo non è un caso speciale, è inerente al modo in cui V opera. All'avvio, tutto l'input viene caricato in un "buffer", ogni comando modifica il buffer in qualche modo, e quindi quando il programma viene eseguito, il buffer viene stampato implicitamente. Ciò significa che qualsiasi stringa di NOP è anche un programma cat.

Il icomando indica entra in modalità inserimento , il che significa che ogni carattere che segue un iverrà aggiunto nel buffer. Con un numero che lo precede, quel testo verrà duplicato n volte.

Ciò significa che per il programma cat, nulla verrà aggiunto al buffer e verrà stampato come è stato letto. In altre parole:

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

Ma per il quine, c'è del testo dopo il i:

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

Sfacciata non risposta

V , 0 byte

Provalo online!

A è il programma vuoto.

B è anche il programma vuoto.

: P


21
Ogni altra lingua: Oy, abbiamo raggiunto un vicolo cieco! . V: * pubblica quine standard * .
Erik the Outgolfer,

13

Rubino, 71 byte

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

Può essere suddiviso in gatti come segue:

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

e

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

I due gatti sono identici ad eccezione del 2 principale, che è una no-op in tutti e tre i programmi. La <<2è una herestring, il che significa che tutto a partire dalla riga successiva fino terminante 2 su una riga è una stringa, che concateniamo a se stesso ( *2) e aggiungere un trascinamento 2. Nei gatti la herestring è ben formato ma vuota, quindi l'espressione regolare non corrisponderà e passeremo $<.readall'espressione e genereremo STDOUT. Una volta concatenati ai gatti, tuttavia, la stringa non termina fino alla terza riga, quindi regex si abbina e cortocircuita ed emette il quine.


11

Pyth, 29 byte (5 + 24) 27 byte (5 + 22)

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

È stato divertente.
Prova qui il quine
Prova qui il primo gatto Prova qui
il secondo gatto

spiegazioni

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 # (compilatore Visual C #) , 551 byte

A: 95 byte

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

Provalo online!

B: 438 + 18 byte

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

Provalo online!

A + B: 533 + 18 byte

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

Provalo online!

A e B accettano input come argomento della riga di comando. A + B ignora qualsiasi input. Vengono aggiunti 18 byte su B e A + B per l' /p:StartupObject=Bopzione inviata a MSBuild. È strettamente necessario solo su A + B, ma sembrava ingannevole non averlo anche in B. In questo modo, i flag del compilatore per A + B sono i flag del compilatore per A (nessuno) più i flag del compilatore per B.

Spiegazione

Il programma A è semplice. La classe A contiene una variabile statica (inutilizzata) iinizializzata su 2e stampa il suo primo argomento quando eseguita. Alla //fine è importante per il codice A + B, ma non fa nulla in A stesso.

Il programma B è strano in isolamento, ma essenzialmente lo stesso. Crea una Classe A contenente una variabile statica iinizializzata su 0, quindi esegue il metodo Main di Classe B, che fa lo stesso del Programma A perché A.iè inferiore a 1 e restituisce prima di qualsiasi cosa strana. Le newline non sono necessarie qui, ma sono importanti per A + B.

Se combinato, il //dal Programma A commenta la dichiarazione di Classe A del Programma B, ma a causa della nuova riga Classe B va bene, consentendo invece A.idi fare riferimento al 2valore del Programma A. Il flag del compilatore fa funzionare il programma B.Main () poiché esiste anche A.Main (). Il risultato è che il programma A + B non genera il suo argomento, ma va invece al seguente segmento di B.Main (), che è fondamentalmente solo il quine C # standard .


1
"i programmi per gatti ... devono copiare stdin in stdout"
Jakob,

9

Haskell , 116 + 20 = 187 175 174 136 byte

Un sacco di byte salvati da quando Ørjan Johansen mi ha mostrato interact

Gatto 1

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

Provalo online!

Gatto 2

main|1>0=interact id

Provalo 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

Provalo online!


Il principio di base al lavoro qui è che quando aggiungiamo il secondo gatto per la prima cambiamo il nome della funzione che interagiscono con da aa idmain. Dal momento che interact idè un gatto vogliamo idmainper me una funzione che restituisce un quine. La soluzione ovvia sarebbe quella di utilizzare const, tuttavia poiché possiamo supporre che anche l'input sia vuoto (++)funziona. Da qui troviamo il codice sorgente con mezzi piuttosto standard, abbiamo una variabile gche codifica il codice sorgente e utilizziamo un wrapper speciale per stamparlo in forma di stringa e codice. C'è una leggera eccezione che dobbiamo mettere in primo piano il nostro encoder perché dobbiamo già terminare interact id. Questo significa un extrag=non è codificato e deve essere gestito manualmente. Il nostro prossimo gatto è piuttosto standard tranne per il fatto che dobbiamo renderlo un codice valido quando viene attaccato all'estremità dell'altro gatto, quindi abbiamo bisogno che entrambi i gatti siano istanze di guardie di schemi.

Strategia alternativa, 43 + 105 = 186 148

Gatto 1

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

Provalo online!

Gatto 2

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

Provalo 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="

Provalo online!


1
Puoi accorciarlo un po 'sostituendo getContents+ putStrcon interact id. Provalo online! (Il quine non funziona più con input non vuoti, il che consente di utilizzare una (++ ...)sezione per il idmain.)
Ørjan Johansen

@ ØrjanJohansen Grazie! Non lo sapevo interact, credo sia perché raramente faccio cose IO con Haskell. Ho modificato il post.
Wheat Wizard

8

Python 3, 286 byte

Il mio primo golf Python e il mio primo quine! Non molto elegante, ma funziona.

Programma A (238 byte)

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

(nessuna nuova riga finale)

Programma B (48 byte)

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

(nessuna nuova riga finale)

Provalo online

Ringraziamenti

  • -24 byte grazie a Jo King
  • -82 byte grazie a Jo King

Puoi fare end=open...e usare %rinvece di %snon dover fare la nuova riga e le citazioni
Jo King

Bene, sono passato a %r. Non sono sicuro di cosa tu voglia dire della newline.
Jakob,

1
Invece di %sformattare una nuova riga, puoi semplicemente fare il letterale \n. È inoltre possibile utilizzare ;per dividere le istruzioni anziché \n(tranne per il fatto che ifdevono essere sulla propria riga). %può essere evitato nella stringa facendo %%. L'unico argomento necessario per formattare la stringa è la stringa stessa, tutto il resto può essere sottoposto a striping
Jo King

1
Il programma B (e il relativo testo) può utilizzare locals()per salvare 2 byte.
Jonathan Allan,

6

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

Programma A (termina con una nuova riga):

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

Programma B (non termina con la nuova riga):

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

Non terribilmente subdolo, e come al solito il C ++ non è eccezionale per il quining. Non sarò sorpreso se ci sono modi per radere byte qua e là sulla stessa idea. L'unico piccolo problema sta cambiando il comportamento di qualcosa dopo che è stato definito, e un inizializzatore variabile dinamico con effetto collaterale fa il trucco. (È possibile farlo anche in C senza estensioni del compilatore?)

Provalo online: A , B , AB

(L'unica preoccupazione di portabilità di cui sono a conoscenza è che il programma presuppone che <cstdio>inserisca i nomi sia nello spazio dei nomi globale che in std.)



5

Python 3 , 100 + 37 = 137 byte

Programma A:

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

Provalo online!

Programma B:

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

Provalo online!

Crea 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)

Provalo online!

Funziona solo quando l'input è vuoto, altrimenti antepone l'input all'output.


Le doppie virgolette dovrebbero essere singole.
Jonathan Allan,

L'arresto è consentito?
Jakob,

@Jakob La domanda non dice che l'arresto anomalo non è consentito e in genere l'output su STDERR viene ignorato
Jo King

Ok, abbastanza giusto. Scorciatoie intelligenti!
Jakob,

4

Attache , 15 + 126 = 141 byte

UN:

AllInput[]|Echo

Provalo 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

Provalo 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

Provalo online!

Spiegazione

Ciascuno dei programmi cat codifica AllInput[]|Echo, che è un semplice programma cat. B è la principale fase chinica; da solo, è una funzione vettorializzata (tramite unaria @) chiamata senza input (chiamata come |Call). Pertanto, If[_,A,B]viene eseguito il primo condizionale B, che è semplicemente AllInput[]|Echo.

Quando viene eseguito A + B , unario @diventa binario a @causa della Echofusione con lambda:

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

Ora, questo significa che la lambda viene eseguita prima di Echo. Tornando al condizionale, questa funzione ora ha tutto STDIN come argomento. Quindi, If[_,A,B]esegue A, che è il framework quine standard.


3

Stax , 16 + 12 = 28 byte

Gatto 1:

"yi|d|ca34b4lr"y

Esegui ed esegui il debug

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

Gatto 2:

i|d|ca34b4lr

Esegui ed esegui il debug

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

Esegui ed esegui il debug

"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

Gatto 1:

Lua , 41 byte

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

Provalo online!


Gatto 2:

Lua , 70 byte

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

Provalo online!


Quine:

Lua , 111 byte

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

Provalo online!

io.input(arg[0]) in Cat 2 imposta il file corrente come input standard e, di conseguenza, il gatto stampa il codice sorgente


1
Benvenuti in PPCG
Muhammad Salman,

È possibile salvare un byte nel gatto 1 rimuovendo l'ultimo punto e virgola?
Muhammad Salman,

1
Sfortunatamente, leggere il file corrente è una scappatoia standard. Ma bello provare comunque.
Beefster


0

JavaScript (Node.js) , 199 byte


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

Provalo online!

Gatto A, 57 byte


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

Provalo online!

Gatto B, 142 byte

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.