2 gatos en una quine


30

Reto

Haga dos programas, A y B, que son programas cat en el mismo idioma. Cuando se concatena, AB (también en el mismo idioma) debe ser una quine.

Por ejemplo, supongamos que helloy worldson ambos programas de gatos en XYZ idioma. Si helloworldes una quine en dicho idioma, entonces su solución es válida.

Para aquellos de ustedes que no están familiarizados con gatos y quines, un programa de gato es uno que imprime exactamente lo que se le dio a través de stdin y un quine es un programa que imprime su propio código fuente.

Puntaje y Reglas

  • El recuento total de bytes del programa AB concatenado es su puntaje. Como se trata de código de golf, gana el puntaje más bajo.
  • Las lagunas estándar están prohibidas
  • La entrada debe tomarse de stdin y la salida debe ir a stdout.
  • Los programas cat no necesitan tomar argumentos; solo necesitan copiar stdin en stdout.
  • La quine debería funcionar cuando el programa no recibe ninguna entrada, pero no tiene que funcionar correctamente (pero puede) para otras entradas.
  • La quine no necesita terminar, siempre que imprima exactamente su código fuente una vez, nada más.
  • La quine debe tener al menos un byte de largo.
  • A y B pueden ser el mismo programa.
  • BA no necesita ser una quine o incluso un programa válido.

No creo que debas tener la A y B puede ser la misma regla del programa
Muhammad Salman

2
@MuhammadSalman Mi idea original era duplicar un programa de gatos para convertirlo en una quine. Solo quería abrir la puerta a soluciones más fáciles porque no estaba completamente seguro de que fuera posible. Parece que me equivoqué en ambos aspectos, pero estoy de acuerdo con eso.
Beefster

3
Probablemente debería agregar que no ABdebe estar vacío, ya que muchos idiomas tienen un gato de 0 bytes que permite una quine de 0 bytes.
DJMcMayhem

99
@DJMcMayhem, sin embargo, una quine de 0 bytes no sería una quine válida.
Nissa

44
¿Qué es un programa de gatos?
Pedro A

Respuestas:


32

V , 2 + 2 == 4 bytes

2i2i

Prueba la quine!

¡Prueba el gato!

A es2i

B es también2i

¿Como funciona?

En primer lugar, algunas explicaciones de cómo funciona V. Una cosa notable que hace posible esta respuesta es que en V, el programa vacío es un programa cat. Este no es un caso especial, es inherente a cómo opera V. En el inicio, todas las entradas se cargan en un "búfer", cada comando modifica el búfer de alguna manera, y luego, cuando el programa termina, el búfer se imprime implícitamente. Esto significa que cualquier cadena de NOP también es un programa cat.

El icomando significa ingresar al modo de inserción , lo que significa que cada carácter que sigue a un ise agregará al búfer. Con un número que lo precede, ese texto se duplicará n veces.

Esto significa que para el programa cat, no se agregará nada al búfer, y se imprimirá tal como se leyó. En otras palabras:

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

Pero para la quine, hay texto después de i:

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

Descarado sin respuesta

V , 0 bytes

Pruébalo en línea!

A es el programa vacío.

B es también el programa vacío.

:PAGS


21
Todos los demás idiomas: ¡ Oy, hemos llegado a un callejón sin salida! . V: * publica quine estándar * .
Erik the Outgolfer

13

Ruby, 71 bytes

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

Se puede dividir en gatos de la siguiente manera:

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

y

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

Los dos gatos son idénticos, excepto por los 2 principales, que no funcionan en los tres programas. El <<2es una herejía, lo que significa que todo lo que comienza en la línea siguiente hasta que termina en 2 en su propia línea es una cadena, que concatenamos a sí mismo ( *2) y agregamos un 2 al final. En los gatos, la herejía está bien formada pero vacía. así que la expresión regular no coincidirá y pasaremos a la $<.readexpresión y la salida STDOUT. Sin embargo, una vez que capturamos a los gatos, la cadena no terminará hasta la tercera línea, por lo que la expresión regular coincide y hacemos un cortocircuito y sacamos la quine.


11

Pyth, 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

Eso fue divertido.
Prueba el quine aquí
Prueba el primer gato aquí
Prueba el segundo gato aquí

Explicaciones

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 de Visual C #) , 551 bytes

A: 95 bytes

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

Pruébalo en línea!

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

Pruébalo en línea!

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

Pruébalo en línea!

A y B toman la entrada como un argumento de línea de comando. A + B ignora cualquier entrada. Se agregan 18 bytes en B y A + B para el/p:StartupObject=B opción enviada a MSBuild. Es estrictamente necesario en A + B, pero parecía una trampa no tenerlo también en B. De esta manera, los indicadores del compilador para A + B son los indicadores del compilador para A (ninguno) más los indicadores del compilador para B.

Explicación

El programa A es sencillo. La clase A contiene una variable estática (no utilizada) iinicializada 2e imprime su primer argumento cuando se ejecuta. Al //final es importante para el código A + B, pero no hace nada en A en sí.

El programa B es extraño de forma aislada, pero esencialmente igual. Crea una clase A que contiene una variable estática iinicializada 0y luego ejecuta el método Main de la clase B, que hace lo mismo que el programa A porqueA.i es menor que 1, y regresa antes que cualquiera de las cosas extrañas. Las nuevas líneas no son necesarias aquí, pero son importantes para A + B.

Cuando se combina, el //Programa A comenta la declaración de Clase A del Programa B, pero debido a la nueva línea, la Clase B está bien, lo A.ique permite referirse al 2valor del Programa A en su lugar. El indicador del compilador hace que el programa ejecute B.Main () ya que A.Main () también existe. El resultado es que el Programa A + B no genera su argumento, sino que pasa al siguiente segmento de B.Main (), que es básicamente la quine estándar de C # .


1
"los programas cat ... necesitan copiar stdin en stdout"
Jakob

9

Haskell , 116 + 20 = 187 175 174 136 bytes

Un montón de bytes guardados desde que Ørjan Johansen me mostró interact

Gato 1

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

Pruébalo en línea!

Gato 2

main|1>0=interact id

Pruébalo en línea!

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

Pruébalo en línea!


El principio básico en el trabajo aquí es que cuando añadimos el segundo gato a la primera cambiamos el nombre de la función estamos interactuando con los de aa idmain. Como interact ides un gato, queremos idmainuna función que devuelva una quine. La solución obvia sería usar const, sin embargo, ya que podemos suponer que la entrada está vacía también (++)funciona. Desde aquí encontramos el código fuente a través de medios bastante estándar, tenemos una variable gque codifica la fuente y utilizamos un contenedor especial para imprimirlo en forma de cadena y en forma de código. Hay una ligera excepción de que necesitamos poner nuestro codificador en la parte delantera porque ya tenemos que terminar coninteract id . Esto significa un extrag=no está codificado y debe manejarse manualmente. Nuestro próximo gato es bastante estándar, excepto que necesitamos que sea un código válido cuando se pega al final del otro gato, por lo que necesitamos que ambos gatos sean instancias de guardias de patrones.

Estrategia alternativa, 43 + 105 = 186 148

Gato 1

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

Pruébalo en línea!

Gato 2

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

Pruébalo en línea!

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

Pruébalo en línea!


1
Puede acortar eso un poco reemplazando getContents+ putStrcon interact id. Pruébalo en línea! (El quine ya no funciona con entradas no vacías, lo que permite usar una (++ ...)sección para idmain.)
Ørjan Johansen

@ ØrjanJohansen ¡Gracias! No lo sabía interact, supongo que es porque rara vez hago cosas de E / S con Haskell. He editado la publicación.
Wheat Wizard

8

Python 3, 286 bytes

¡Mi primer Python golf y mi primer quine! No muy elegante, pero 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()));

(sin línea nueva)

Programa B (48 bytes)

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

(sin línea nueva)

Pruébalo en línea

Expresiones de gratitud

  • -24 bytes gracias a Jo King
  • -82 bytes gracias a Jo King

Puede hacer end=open...y usar en %rlugar de %sno tener que hacer la nueva línea y las citas
Jo King

Genial, cambié a %r. Sin embargo, no estoy seguro de lo que quieres decir con la nueva línea.
Jakob

1
En lugar de %sformatear una nueva línea, simplemente puede hacer el literal \n. También puede usar ;para dividir sentencias en lugar de \n(excepto que ifdebe estar en su propia línea). %se puede escapar en la cadena haciendo %%. El único argumento necesario para formatear la cadena es la cadena en sí, todo lo demás se puede dividir
Jo King

1
El programa B (y el texto) puede usar locals()para guardar 2 bytes.
Jonathan Allan

6

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

Programa A (termina en una nueva línea):

#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 (no termina en nueva línea):

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

No es terriblemente astuto, y como de costumbre, C ++ no es tan bueno para quining. No me sorprendería si hay formas de eliminar bytes aquí y allá de la misma idea. El único inconveniente es cambiar el comportamiento de algo después de que se haya definido, y un inicializador de variable dinámico con efecto secundario hace el truco. (¿Se puede hacer esto incluso en C sin extensiones del compilador?)

Pruébelo en línea: A , B , AB

(La única preocupación de portabilidad que conozco es que el programa supone <cstdio>poner nombres tanto en el espacio de nombres global como en 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())#

Pruébalo en línea!

Programa B:

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

Pruébalo en línea!

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

Pruébalo en línea!

Solo funciona cuando la entrada está vacía; de lo contrario, antepone la entrada a la salida.


Las comillas dobles deben ser simples.
Jonathan Allan

Se permite estrellarse?
Jakob

@Jakob La pregunta no dice que no se permita el bloqueo , y generalmente se ignora la salida a STDERR
Jo King

OK bastante justo. ¡Atajos inteligentes!
Jakob

4

Agregado , 15 + 126 = 141 bytes

UNA:

AllInput[]|Echo

Pruébalo en línea!

SI:

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

Pruébalo en línea!

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

Pruébalo en línea!

Explicación

Cada uno de los programas cat codifica AllInput[]|Echo, que es un programa cat simple. B es la fase quine principal; solo, es una función vectorizada (a través de unario @) llamada sin entradas (llamada como |Call). Por lo tanto, el primer condicional se If[_,A,B]ejecuta B, que es simplemente AllInput[]|Echo.

Cuando se ejecuta A + B , el unario se @convierte en binario @debido a la Echofusión con la lambda:

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

Ahora, esto significa que la lambda se ejecuta antes que Echoes. Volviendo al condicional, esta función ahora tiene todo STDIN como argumento. Entonces, se If[_,A,B]ejecuta A, que es el marco de trabajo estándar.


3

Stax , 16 + 12 = 28 bytes

Gato 1:

"yi|d|ca34b4lr"y

Ejecutar y depurarlo

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

Gato 2:

i|d|ca34b4lr

Ejecutar y depurarlo

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

Ejecutar y depurarlo

"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

Gato 1:

Lua , 41 bytes

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

Pruébalo en línea!


Gato 2:

Lua , 70 bytes

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

Pruébalo en línea!


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

Pruébalo en línea!

io.input(arg[0]) en Cat 2 establece el archivo actual como entrada estándar, y como resultado, el gato imprime el código fuente


1
Bienvenido a PPCG
Muhammad Salman

¿Puede guardar un byte en el gato 1 eliminando el último punto y coma?
Muhammad Salman

1
Desafortunadamente, leer el archivo actual es una laguna estándar. Pero buen intento de todos modos.
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()

Pruébalo en línea!

Cat A, 57 bytes


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

Pruébalo en línea!

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

Pruébalo en línea!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.