Un programa que imprime programas

13

Desafío

Su objetivo es escribir un programa que imprima otro programa. Ese programa impreso debería imprimir otro programa, y ​​el nuevo programa debería imprimir otro programa, hasta el final.

Reglas

  1. Cada programa debe tener menos de 256 bytes. (Si esto necesita ser cambiado, deje un comentario)
  2. El último programa debe ser un programa vacío.
  3. Debe haber un número finito de programas, por lo que el programa no puede ser una quine.
  4. Todos los programas deben ejecutarse en el mismo idioma.
  5. No se permite ninguna entrada.
  6. El programa ganador es el programa que imprime tantos programas como sea posible, contándose a sí mismo.

¡Buena suerte!

La tortuga
fuente
La puntuación máxima es 2^2048, o 3.2317e616.
orlp
Para facilitar la comparación de puntajes grandes, incluya una aproximación a su puntaje en la forma a*10^bdonde 1<=a<10y bes un número natural.
flawr
2
En realidad, mi cálculo anterior estaba equivocado. Suponiendo que el programa debe estar en bytes, la puntuación máxima posible es <número demasiado largo para comentario> o 1.2673e614.
orlp

Respuestas:

20

CJam, 4.56 × 10 526 programas

2D#2b{"\256b_(256b:c'\s`_:(er`":T~{;38'ÿ*`{:T~{;63'ÿ*`{:T~{;88'ÿ*`{:T~{;114'ÿ*`{:T~{;140'ÿ*`{:T~{;166'ÿ*`{:T~{;192'ÿ*`{:T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}_~

Puntaje exacto: 254 219 + 254 192 + 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 3

Todos los programas deben guardarse utilizando la codificación ISO-8859-1 para cumplir con el límite de tamaño de archivo.

Gracias a @ChrisDrost que señaló un error y sugirió el enfoque de anidación.

Pruébelo en línea en el intérprete de CJam .

254 219 + 2 ≈ 4.56 × 10 526 programas

La línea compartida de la puntuación se puede lograr con el siguiente programa, mucho más simple 1 .

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

Ejecutar este programa produce el programa

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

y después 254 219 - 1 iteraciones más, el programa

{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

Este último programa no vacío sale con un error 2 y no imprime nada (el programa vacío).

Cómo funciona

Suponga que la cadena ya está en la pila.

{      e# Push a code block.
  \    e# Swap the string on top of the code block.
       e# This will cause a runtime error if there is no string on the stack.
  256b e# Convert the string (treated as a base-256 number) to integer (I).
  _(   e# Copy the integer and decrement the copy.
  256b e# Convert the integer into the array of its base-256 digits.
  :c   e# Cast each base-256 digit to character. Converts from array to string.
  '\s  e# Push a string that contains a single backslash.
  `    e# Push its string representation, i.e., the array ['" '\ '\ '"].
  _:(  e# Push a copy and decrement each character. Pushes ['! '[ '[ '!].
  er   e# Perform transliteration to replace "s with !s and \s with [s.
       e# This skips characters that require escaping.
  `    e# Push its string representation, i.e., surround it with double quotes.
  Q    e# Push an empty string.
  ?    e# Select the first string if I is non-zero, the empty string otherwise.
  \    e# Swap the selected string with the code block.
  "_~" e# Push that string on the stack.
}      e#
_~     e# Push a copy of the code block and execute it.
       e# The stack now contains the modified string, the original code block
       e# and the string "_~", producing an almost exact copy of the source.

254 192 ≈ 5.35 × 10 461 más programas

Aquí es donde las cosas se ponen un poco locas.

El primer programa es altamente compresible. Al escribir un programa similar que, en lugar del programa vacío, finalmente produzca el primer programa de la sección anterior, podemos mejorar la puntuación en 254 192 programas 3 .

El programa

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{"\256b_(256b:c'\s`_:(er`":T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}_~

es similar al primer programa de la sección anterior, y ejecuta el primero y su salida para 254 192 iteraciones produce el último.

Suponga que la cadena ya está en la pila:

{                           e# Push a code block.
  "\256b_(256b:c'\s`_:(er`" e# Push that string on the stack.
                            e# The characters inside it behave exactly as
                            e# they did in the previous section.
  :T~                       e# Save the string in T and evaluate it.
  {                         e# If the integer I is non-zero, keep the generated
                            e# string; else:
    ;                       e#   Pop the code block from the stack.
    219'ÿ*`                 e#   Push a string of 219 ÿ's (with double quotes).
    {Q?\"_~"}               e#   Push that block on the stack.
    s                       e#   Push its string representation.
    (\                      e#   Shift out the { and swap it with the tail.
    T                       e#   Push T.
  }?                        e#
  \                         e# Swap the selected string with the code block
                            e# or T with the tail of the code block.
  "_~"                      e# Push that string on the stack.
}                           e#
_~                          e# Push a copy of the code block and execute it.

Programas de moar

El primer programa de la sección anterior sigue siendo altamente compresible, por lo que podemos aplicar un método similar y escribir un programa que, después de 254 166 iteraciones, produzca el programa mencionado anteriormente.

La repetición de esta técnica una y otra vez hasta que golpeó el límite de 255 bytes, podemos añadir un total de 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 1 ≈ 1,59 × 10 399 programas para los de las secciones anteriores.


1 Nueva línea agregada para mayor claridad.
2 Por consenso sobre Meta , esto está permitido por defecto.
3 o 0.0000000000000000000000000000000000000000000000000000000000000012%

Dennis
fuente
Continuemos esta discusión en el chat .
Dennis
5

JavaScript, 1000 programas

x=999;
q=";alert(x=999?`q=${JSON.stringify(q)+q}`.split(x).join(x-1):``)";
alert(
    x ? `x=999;q=${JSON.stringify(q)+q}`.split(x).join(x-1) // basically .replaceAll(x, x-1)
      : ``
)

Si esto es válido depende precisamente de cómo entender la tercera regla.

Ypnypn
fuente
Técnicamente no es una quine, ya que imprime una versión modificada de su propio código fuente en lugar de una copia idéntica. Utiliza técnicas similares a las de quine, obviamente. Creo que necesitaremos una aclaración de @TheTurtle.
JohnE
55
@JohnE e Ypnypn Esto es algo como lo imaginé. Esto funciona.
The Turtle
66
Aún estás muy por debajo del límite de longitud del código. ¿Por qué no cambias el 999 a algo más grande?
DankMemes
4

Ruby, 1.628 × 10 ^ 237 programas

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;_="a=%#x-1;_=%p;puts _%%[a,_]if a";puts _%[a,_]if a

El mismo enfoque que mi respuesta de Perl, pero como Ruby ya maneja grandes ints, es más fácil de almacenar como hexadecimal.


Ruby, 9.277 × 10 ^ 90 programas

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;b=0xf;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-("%x"%a).length));_="a=%#x;b=%#x;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-('%%x'%%a).length));_=%p;puts _%%[a,b-1,_]if a";puts _%[a,b-1,_]if a

Por lo tanto, este intento es una variación ligeramente diferente del anterior, pero debido a todas las funciones adicionales, no obtengo el número tan alto como el otro ... ¡Sin embargo, fue interesante probar otro enfoque!

Dom Hastings
fuente
4

Python 2, 9.7 * 10 ^ 229 programas

O=0
if len(hex(O))<191:print"O=0x%x"%(O+1)+open(__file__).read()[-68:]
Azul
fuente
Bien, no pensé en la repetición de cuerdas!
Dom Hastings
2

C, 2.2 * 10 ^ 177 programas

#define S(s)char*q=#s,n[]="#####################################################################################################";i;s
S(main(){while(n[i]==91)n[i++]=35;i==101?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})

No es perfecto, pero es bastante bueno. Quiero decir que tiene exactamente 255bytes de longitud y genera programas de la misma longitud. Probablemente podría tocar un poco más para obtener más programas, pero lo dejaré como está por ahora.

El programa se basa en una simple C quine. Además, hay un algoritmo de conteo bastante simple que cuenta a través de todos los valores posibles de la matriz de caracteres n. Tenemos tantos programas como permutaciones de la cadena n.

El rango de caracteres está limitado a un rango de #(= 35) a [= (91). Eso es porque no quiero ninguno "o\ en la cadena, porque necesitan escapar.

La generación del programa finaliza cuando todos los valores en la matriz de caracteres nson [. Luego genera un programa ficticio simple main(){}, que en sí mismo no genera nada.

#define  S(s) char *q = #s; /* have the source as a string */ \
char n[] = "#####################################################################################################"; \ 
int i; \
s /* the source itself */
S(main() {
    while(n[i]=='[') /* clear out highest value, so next array element be incremented */
        n[i++]='#'; 
    i==101 /* end of array reached? output dummy program */
        ? q = "main(){}"
        : n[i]++; /* count one up in the whole array */
    printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)", n, q);
})

Como demostración de que debería funcionar, acabo de cambiar los límites, por lo que solo los caracteres entre el código ASCII 35y36 que se utilizan y sólo 4 elementos de la matriz.

Los programas resultantes son

% echo > delim; find -iname 'program_*.c' | xargs -n1 cat delim

#define S(s)char*q=#s,n[]="####";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$###";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="###$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$##$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="####";i;s
S(main(){})

Esto salidas 2^4 + 1 = 17 diferentes programas.

Entonces, el programa anterior genera ((91-35)+1)^101 + 1 = 57^101 + 1 ~= 2.2 * 10^177diferentes programas. No estoy completamente seguro de si esto cuenta, o si mi cálculo es correcto

MarcDefiant
fuente
1
¿Podría incluir que se trata de esto 2.2 * 10^177(para aquellos que quieren comparar)?
flawr
No sabía cómo calcular este, pero lo
incluí
wolframalpha.com =)
flawr
1

Perl, 1 × 10 ^ 163

De lo contrario, esta es una quine bastante básica, reducida a la menor cantidad de caracteres posible, que solo se ejecuta mientras el contador no lo es 0.

use bigint;$i=9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999||die;$_=<<'e';eval
print"use bigint;\$i=$i-1||die;\$_=<<'e';eval
${_}e
"
e
Dom Hastings
fuente
1

Lisp común, 10 113 -1

(LET ((X
       99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999))
  (WHEN #1=(PLUSP X)
    #2=(SETF *PRINT-CIRCLE* T)
    #3=(PRINT (LIST 'LET `((X ,(1- X))) (LIST 'WHEN '#1# '#2# '#3#)))))
  • Hay 113 nueves.
  • El siguiente programa tiene 112 nueves seguido de un 8
  • El siguiente programa tiene 112 nueves seguido de un 7
  • ...

El número de nueves está limitado por el tamaño máximo de código, 256, teniendo en cuenta los espacios introducidos por la impresora.

volcado de memoria
fuente
1

Perl, 1.4 * 10 ^ 225

use bignum;open$F,__FILE__;$_=<$F>;s/0x\w+/($&-1)->as_hex/e;0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&&print

Enfoque similar a python; mismo resultado!

alexander-brett
fuente
0

> <> , 65534 (?) Programas

Agregué un signo de interrogación al lado de 65533 ya que aún no he verificado que pueda imprimir 65533 (aunque tengo razones para creer que debería). Una vez que tenga un poco más de tiempo, voy a encontrar una manera de probarlo.

":?!;1-r00gol?!;a0.�

Puedes probarlo en línea aquí .

La esencia de este programa es que cambia la salida del personaje al final y luego disminuye su valor numérico antes de imprimir. Obtuve 65534 programas porque el valor ASCII del carácter al final del código es 65533, por lo que contando el primer programa tenemos 65534 (supongo que si cuenta el programa vacío 65535). El último programa "devuelto" no es nada; simplemente termina cuando el valor del carácter es 0.

Estoy bastante seguro de que podrá imprimir un carácter para todas las iteraciones: no pude encontrar una fuente definitiva para cuántos caracteres> <> pueden imprimir, pero hay caracteres directamente debajo de 65533, numéricamente.

Avíseme si hay algún problema con esta implementación; Estoy un poco inseguro sobre la validez de mi entrada.


Explicación

He robado descaradamente la idea de utilizar una comilla simple para crear una pseudoquina de la wiki> <> y un comentario que vi aquí una vez.

":?!;1-r00gol?!;a0.�
"                     begins string parsing
 :?!;                 terminates program if final character is 0, numerically
     1-               decrements final character by 1
       r              reverses stack
        00g           grabs quotation mark (fancy way of putting " ")
           ol?!;      prints and terminates if stack is empty
                a0.   jumps back to o to loop 

Lo que hace es analizar todo después de las comillas como caracteres y luego disminuir el último. A partir de ahí, simplemente invierte la pila (para imprimir en el orden correcto), coloca una comilla en la pila y luego imprime hasta que la pila esté vacía.

col
fuente
0

Python, 1 × 10 ^ 194 programas

n=99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
if n:print open(__file__).read().replace(str(n),str(n-1))

Esto debe ejecutarse desde un archivo, no desde una respuesta interactiva. No es una quine.

¡Gracias a @The Turtle por ayudarme a ahorrar 3 bytes, que es más espacio para nueves!
¡Gracias a @poke por ayudarme a ahorrar 2 bytes, que es más espacio para nueves!

Amante del queso
fuente
@ Cheese Lover The if n!=0es redundante. Solo puedes escribir if n.
The Turtle
También puedes deshacerte de dos espacios; después de if n:y entre los replaceargumentos.
meter
0

Bash, 52 programas

Completamente sin inspiración y (con suerte) sólidamente en el último lugar.

echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo
Chris
fuente