2 chats dans une quine


30

Défi

Créez deux programmes, A et B, qui sont tous deux des programmes de chat dans la même langue. Une fois concaténé, AB (également dans la même langue) devrait être un quine.

Par exemple, supposez helloet worldsont les deux programmes de chat en langage XYZ. Si helloworldc'est une quine dans ladite langue, alors votre solution est valide.

Pour ceux d'entre vous qui ne connaissent pas les chats et les quines, un programme cat est celui qui imprime exactement ce qui lui a été donné via stdin et un quine est un programme qui imprime son propre code source.

Scoring et règles

  • Le nombre total d'octets du programme AB concaténé est votre score. Comme c'est du golf de code, le score le plus bas l'emporte.
  • Les failles standard sont interdites
  • L'entrée doit provenir de stdin et la sortie doit aller à stdout.
  • Les programmes cat n'ont pas besoin de prendre d'arguments; il suffit de copier stdin sur stdout.
  • Le quine devrait fonctionner lorsque le programme ne reçoit aucune entrée, mais ne doit pas fonctionner correctement (mais peut) pour d'autres entrées.
  • Le quine n'a pas besoin de se terminer, à condition d'imprimer exactement son code source une fois, rien de plus.
  • Le quine doit être d'au moins un octet de long.
  • A et B peuvent être le même programme.
  • BA n'a pas besoin d'être une quine ou même un programme valide.

Je ne pense pas que vous devriez avoir les mêmes règles de programme A et B
Muhammad Salman

2
@ MuhammadSalman Mon idée originale était d'avoir un programme de chat doublé pour devenir une quine. Je voulais juste ouvrir la porte à des solutions plus faciles parce que je n'étais pas tout à fait sûr que c'était possible. On dirait que j'avais tort sur les deux points, mais ça me va.
Beefster

3
Vous devriez probablement ajouter que cela ne ABdoit pas être vide, car de nombreuses langues ont un chat de 0 octet permettant un quine de 0 octet.
DJMcMayhem

9
@DJMcMayhem un quine de 0 octet ne serait cependant pas un quine valide.
Nissa

4
Qu'est-ce qu'un programme chat?
Pedro A

Réponses:


32

V , 2 + 2 == 4 octets

2i2i

Essayez la quine!

Essayez le chat!

A est2i

B est aussi2i

Comment ça marche?

Tout d'abord, quelques explications sur le fonctionnement de V. Une chose notable qui rend cette réponse possible est que dans V, le programme vide est un programme cat. Ce n'est pas un cas particulier, c'est inhérent au fonctionnement de V. Au démarrage, toutes les entrées sont chargées dans un "tampon", chaque commande modifie le tampon d'une manière ou d'une autre, puis lorsque le programme est terminé, le tampon est implicitement imprimé. Cela signifie que toute chaîne de NOP est également un programme cat.

La icommande signifie entrer en mode d'insertion , ce qui signifie que chaque caractère suivant un isera ajouté dans le tampon. Avec un nombre le précédant, ce texte sera dupliqué n fois.

Cela signifie que pour le programme cat, rien ne sera ajouté au tampon et il sera imprimé tel qu'il a été lu. En d'autres termes:

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

Mais pour la quine, il y a du texte après i:

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

Non-réponse effrontée

V , 0 octet

Essayez-le en ligne!

A est le programme vide.

B est également le programme vide.

: P


21
Toutes les autres langues: Oy, nous sommes dans une impasse! . V: * affiche le quine standard * .
Erik the Outgolfer

13

Rubis, 71 octets

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

Peut être divisé en chats comme suit:

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

et

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

Les deux chats sont identiques à l'exception du 2 principal, qui est un no-op dans les trois programmes. Le <<2est une chaîne héréditaire, ce qui signifie que tout ce qui commence sur la ligne suivante jusqu'à ce qu'un 2 se terminant sur sa propre ligne soit une chaîne, que nous concaténons à lui-même ( *2) et ajoutons une traînée 2. Chez les chats, la chaîne héréditaire est bien formée mais vide, de sorte que l'expression régulière ne correspondra pas et nous passerons à l' $<.readexpression et à la sortie STDOUT. Une fois que nous avons concaténé les chats, cependant, la chaîne ne se terminera pas avant la troisième ligne, donc l'expression régulière correspond et nous court-circuitons et sortons le quine.


11

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

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

C'était amusant.
Essayez la quine ici
Essayez le premier chat ici
Essayez le deuxième chat ici

Des explications

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 # (compilateur Visual C #) , 551 octets

A: 95 octets

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

Essayez-le en ligne!

B: 438 + 18 octets

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

Essayez-le en ligne!

A + B: 533 + 18 octets

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

Essayez-le en ligne!

A et B prennent l'entrée comme argument de ligne de commande. A + B ignore toute entrée. 18 octets sur B et A + B sont ajoutés pour le/p:StartupObject=B option envoyée à MSBuild. C'est seulement strictement nécessaire sur A + B, mais il semblait être de la triche de ne pas l'avoir aussi en B. De cette façon, les drapeaux de compilation pour A + B sont les drapeaux de compilation pour A (aucun) plus les drapeaux de compilation pour B.

Explication

Le programme A est simple. La classe A contient une variable statique (inutilisée) iinitialisée à 2et affiche son premier argument lors de son exécution. le// à la fin est important pour le code A + B, mais ne fait rien dans A lui-même.

Le programme B est bizarre dans l'isolement, mais essentiellement le même. Il crée une classe A contenant une variable statique iinitialisée à 0, puis exécute la méthode Main de classe B, qui fait la même chose que le programme A carA.i est inférieure à 1, et renvoie avant tout ce qui est bizarre. Les nouvelles lignes ne sont pas nécessaires ici, mais sont importantes pour A + B.

Lorsqu'il est combiné, le //programme A commente la déclaration de classe A du programme B, mais à cause de la nouvelle ligne, la classe B est correcte, ce A.iqui permet de se référer à la 2valeur du programme A à la place. L'indicateur du compilateur fait exécuter le programme B.Main () car A.Main () existe également. Le résultat est que le programme A + B ne produit pas son argument, mais passe à la place au segment suivant de B.Main (), qui est fondamentalement juste le quine C # standard .


1
"les programmes de chat ... doivent copier stdin vers stdout"
Jakob

9

Haskell , 116 + 20 = 187 175 174 136 octets

Un tas d'octets économisés depuis que Ørjan Johansen m'a montré interact

Cat 1

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

Essayez-le en ligne!

Cat 2

main|1>0=interact id

Essayez-le en ligne!

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

Essayez-le en ligne!


Le principe de base à l'œuvre ici est que lorsque nous ajoutons le deuxième chat au premier, nous changeons le nom de la fonction avec laquelle nous interagissons de aà idmain. Puisque interact idc'est un chat nous voulons idmainune fonction qui retourne une quine. La solution évidente serait d'utiliser const, cependant, car nous pouvons supposer que l'entrée est également vide (++). De là, nous trouvons le code source via des moyens assez standard, nous avons une variable gqui code la source et nous utilisons un wrapper spécial pour l'imprimer sous forme de chaîne et sous forme de code. Il y a une légère exception que nous devons mettre notre encodeur à l'avant parce que nous devons déjà terminer avec interact id. Cela signifie un supplémentg=n'est pas codé et doit être géré manuellement. Notre prochain chat est assez standard, sauf que nous devons en faire un code valide lorsqu'il est collé à la fin de l'autre chat, nous avons donc besoin que les deux chats soient des instances de gardes de modèle.

Stratégie alternative, 43 + 105 = 186 148

Cat 1

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

Essayez-le en ligne!

Cat 2

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

Essayez-le en ligne!

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

Essayez-le en ligne!


1
Vous pouvez raccourcir un peu cela en remplaçant getContents+ putStrpar interact id. Essayez-le en ligne! (Le quine ne fonctionne plus avec une entrée non vide, ce qui permet d'utiliser une (++ ...)section pour le idmain.)
Ørjan Johansen

@ ØrjanJohansen Merci! Je ne savais pas interact, je suppose que c'est parce que je fais rarement des trucs IO avec Haskell. J'ai édité le post.
Wheat Wizard

8

Python 3, 286 octets

Mon premier golf Python et ma première quine! Pas très élégant, mais ça marche.

Programme A (238 octets)

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

(pas de nouvelle ligne de fin)

Programme B (48 octets)

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

(pas de nouvelle ligne de fin)

Essayez-le en ligne

Remerciements

  • -24 octets grâce à Jo King
  • -82 octets grâce à Jo King

Vous pouvez faire end=open...et utiliser %rau lieu de %sne pas avoir à faire la nouvelle ligne et les citations
Jo King

Cool, je suis passé à %r. Je ne sais pas ce que vous voulez dire sur la nouvelle ligne.
Jakob

1
Au lieu de %sformater une nouvelle ligne, vous pouvez simplement faire le littéral \n. Vous pouvez également utiliser ;pour fractionner les instructions au lieu de \n(sauf qu'il ifdoit être sur sa propre ligne). %peut être échappé dans la chaîne en faisant %%. Le seul argument nécessaire pour formater la chaîne est la chaîne elle-même, tout le reste peut être rayé
Jo King

1
Le programme B (et le texte correspondant) peut utiliser locals()pour économiser 2 octets.
Jonathan Allan

6

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

Programme A (se termine par une nouvelle ligne):

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

Programme B (ne se termine pas par une nouvelle ligne):

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

Pas terriblement sournois, et comme d'habitude, le C ++ n'est pas génial pour quining. Je ne serai pas surpris s'il existe des moyens de raser les octets ici et là avec la même idée. Le seul petit hic est de changer le comportement de quelque chose après qu'il a été défini, et un initialiseur de variable dynamique avec effet secondaire fait l'affaire. (Cela peut-il même être fait en C sans extensions de compilateur?)

Essayez-le en ligne: A , B , AB

(Le seul problème de portabilité que je connaisse est que le programme suppose de <cstdio>placer les noms à la fois dans l'espace de noms global et dans std.)


5

Befunge-98 (FBBI) , 8 + 15 = 23 octets

A + B: (ne fonctionne que pour aucune entrée)

+9*5~,#@#@~,9j>:#,_:@#"

Essayez-le en ligne!

UNE:

+9*5~,#@

Essayez-le en ligne!

B:

#@~,9j>:#,_:@#"

Essayez-le en ligne!


Je me demandais si quelqu'un réussirait à répondre avec insouciance. Dommage que celui-ci ne soit pas 2D: - /
Beefster

@Beefster ouais. Le problème est qu'il est assez difficile de faire une Quine 2D. Peut-être que je vais travailler sur quelque chose
MildlyMilquetoast

5

Python 3 , 100 + 37 = 137 octets

Programme A:

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

Essayez-le en ligne!

Programme B:

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

Essayez-le en ligne!

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)

Essayez-le en ligne!

Fonctionne uniquement lorsque l'entrée est vide, sinon elle ajoute l'entrée à la sortie.


Les guillemets doubles doivent être simples.
Jonathan Allan

Le crash est autorisé?
Jakob

@Jakob La question ne dit pas que le plantage n'est pas autorisé, et généralement la sortie vers STDERR est ignorée
Jo King

OK très bien. Des raccourcis intelligents!
Jakob

4

Attaché , 15 + 126 = 141 octets

UNE:

AllInput[]|Echo

Essayez-le en ligne!

B:

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

Essayez-le en ligne!

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

Essayez-le en ligne!

Explication

Chacun des programmes cat encode AllInput[]|Echo, qui est un simple programme cat. B est la phase quine principale; seule, c'est une fonction vectorisée (via unaire @) appelée sans entrée (appelée comme |Call). Ainsi, le premier conditionnel If[_,A,B]s'exécute B, ce qui est tout simplement AllInput[]|Echo.

Lorsque A + B est exécuté, unaire @devient binaire en @raison de la Echofusion avec le lambda:

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

Maintenant, cela signifie que le lambda est exécuté avant l' Echoest. Revenons au conditionnel, cette fonction a maintenant tout STDIN comme argument. Donc, If[_,A,B]exécute A, qui est le cadre standard de quine.


3

Stax , 16 + 12 = 28 octets

Cat 1:

"yi|d|ca34b4lr"y

Exécuter et déboguer

"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

Exécuter et déboguer

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

Exécuter et déboguer

"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 octets

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

Essayez-le en ligne!


Cat 2:

Lua , 70 octets

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

Essayez-le en ligne!


Quine:

Lua , 111 octets

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

Essayez-le en ligne!

io.input(arg[0]) dans Cat 2 définit le fichier actuel comme entrée standard, et par conséquent, le chat imprime le code source


1
Bienvenue chez PPCG
Muhammad Salman

Vous pouvez enregistrer un octet dans la catégorie 1 en supprimant le dernier point-virgule?
Muhammad Salman

1
Malheureusement, la lecture du fichier actuel est une faille standard. Mais bon essai quand même.
Beefster


0

JavaScript (Node.js) , 199 octets


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

Essayez-le en ligne!

Cat A, 57 octets


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

Essayez-le en ligne!

Cat B, 142 octets

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

Essayez-le en ligne!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.