Un programme qui imprime des programmes

13

Défi

Votre objectif est d'écrire un programme qui imprime un autre programme. Ce programme imprimé doit imprimer un autre programme et le nouveau programme doit imprimer un autre programme jusqu'à la fin.

Règles

  1. Chaque programme doit contenir moins de 256 octets. (Si cela doit être changé, laissez un commentaire)
  2. Le dernier programme doit être un programme vide.
  3. Il doit y avoir un nombre fini de programmes, donc le programme ne peut pas être une quine.
  4. Les programmes doivent tous s'exécuter dans la même langue.
  5. Aucune entrée n'est autorisée.
  6. Le programme gagnant est le programme qui imprime autant de programmes que possible, en se comptant.

Bonne chance!

La tortue
la source
Le score maximum est 2^2048, ou 3.2317e616.
orlp
Pour faciliter la comparaison des grands scores, veuillez inclure une approximation de votre score dans le formulaire a*10^b1<=a<10et best un nombre naturel.
flawr
2
En fait, mon calcul précédent était faux. En supposant que le programme doit être en octets, le score maximum possible est <nombre trop long pour le commentaire> ou 1.2673e614.
orlp

Réponses:

20

CJam, 4,56 × 10 526 programmes

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`}?\"_~"}_~

Score exact: 254 219 + 254 192 + 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 3

Tous les programmes doivent être enregistrés à l'aide de l'encodage ISO-8859-1 pour respecter la taille limite des fichiers.

Merci à @ChrisDrost qui a signalé un bug et suggéré l'approche d'imbrication.

Essayez-le en ligne dans l' interpréteur CJam .

254 219 + 2 ≈ 4,56 × 10 526 programmes

La part de ligne du score peut être obtenue par le programme suivant, beaucoup plus simple 1 .

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

L'exécution de ce programme produit le programme

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

et après 254 219 - 1 itérations supplémentaires, le programme

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

Ce dernier programme non vide se termine avec une erreur 2 et n'imprime rien (le programme vide).

Comment ça fonctionne

Supposons que la chaîne se trouve déjà sur la pile.

{      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 autres programmes

C'est là que les choses deviennent un peu folles.

Le premier programme est hautement compressible. En écrivant un programme similaire qui, au lieu du programme vide, produit éventuellement le premier programme de la section ci-dessus, nous pouvons améliorer le score de 254 192 programmes 3 .

Le programme

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

est similaire au premier programme de la section précédente, et l'exécution du premier et de sa sortie pour 254 192 itérations produit le second.

Supposons que la chaîne se trouve déjà sur la pile:

{                           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.

Programmes Moar

Le premier programme de la section précédente est encore très compressible, nous pouvons donc appliquer une méthode similaire et écrire un programme qui, après 254 166 itérations, produit le programme susmentionné.

En répétant cette technique encore et encore jusqu'à ce que nous atteignions la limite de 255 octets, nous pouvons ajouter un total de 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 1 ≈ 1,59 × 10 399 programmes à celles des sections précédentes.


1 Nouvelle ligne ajoutée pour plus de clarté.
2 Par consensus sur Meta , cela est autorisé par défaut.
3 ou 0.0000000000000000000000000000000000000000000000000000000000000012%

Dennis
la source
Continuons cette discussion dans le chat .
Dennis
5

JavaScript, 1000 programmes

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)
      : ``
)

Sa validité dépend précisément de la manière de comprendre la troisième règle.

Ypnypn
la source
Il ne s'agit pas techniquement d' une quine, car il imprime une version modifiée de son propre code source plutôt qu'une copie identique. Il utilise évidemment des techniques de type quine. Je pense que nous aurons besoin de précisions de @TheTurtle.
JohnE
5
@JohnE et Ypnypn C'est quelque chose comme j'envisageais. Cela marche.
The Turtle
6
Vous êtes toujours bien en dessous de la limite de longueur de code. Pourquoi ne changez-vous pas 999 en quelque chose de plus grand?
DankMemes
4

Ruby, 1,628 × 10 ^ 237 programmes

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

Même approche que ma réponse Perl, mais parce que Ruby gère déjà les gros volumes, il est plus facile de stocker en hexadécimal.


Ruby, 9.277 × 10 ^ 90 programmes

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

Donc, cette tentative est une variation légèrement différente de la précédente quine-like, mais à cause de toutes les fonctions supplémentaires, je n'obtiens pas un nombre aussi élevé que l'autre ... C'était intéressant d'essayer une autre approche!

Dom Hastings
la source
4

Python 2, programmes 9.7 * 10 ^ 229

O=0
if len(hex(O))<191:print"O=0x%x"%(O+1)+open(__file__).read()[-68:]
Bleu
la source
Sympa, je n'ai pas pensé à la répétition des cordes!
Dom Hastings du
2

Programmes C, 2.2 * 10 ^ 177

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

Ce n'est pas parfait, mais plutôt bon. Je veux dire qu'il fait exactement des 255octets de long et génère des programmes de la même longueur. Vous pourriez probablement jouer un peu plus pour gagner d'autres programmes, mais je vais le laisser tel quel pour l'instant.

Le programme est basé sur une simple quine C. De plus, il existe un algorithme de comptage assez simple qui compte toutes les valeurs possibles du tableau char n. Nous avons autant de programmes que de permutations de la chaîne n.

La plage des ombles est limitée à une plage de #(= 35) à [= (91). C'est parce que je n'en veux pas "ou \dans la chaîne, car ils doivent être échappés.

La génération du programme se termine lorsque toutes les valeurs du tableau char nsont [. Ensuite, il génère un programme factice simple main(){}, qui lui-même ne produit rien.

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

Pour démontrer que cela devrait fonctionner, je viens de changer les limites, donc seuls les caractères entre le code ASCII 35et 36sont utilisés et seulement 4 éléments de tableau.

Les programmes résultants sont

% 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(){})

Cela génère 2^4 + 1 = 17différents programmes.

Ainsi, le programme ci-dessus génère ((91-35)+1)^101 + 1 = 57^101 + 1 ~= 2.2 * 10^177différents programmes. Je ne suis pas entièrement sûr si cela compte, ou si mon calcul est même correct

MarcDefiant
la source
1
Pourriez-vous s'il vous plaît inclure qu'il s'agit de 2.2 * 10^177(pour ceux qui veulent comparer)?
flawr
Je ne savais pas comment calculer celui-ci, mais je l'ai inclus ;-)
MarcDefiant
wolframalpha.com =)
flawr
1

Perl, 1 × 10 ^ 163

Sinon, c'est un quine assez basique, réduit à aussi peu de caractères que possible, qui ne fonctionne que pendant que le compteur ne l'est pas 0.

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

Common Lisp, 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#)))))
  • Il y a 113 neuf.
  • Le prochain programme compte 112 neuf suivis d'un 8
  • Le programme suivant a 112 neuf suivis d'un 7
  • ...

Le nombre de neuf est limité par la taille maximale du code, 256, en tenant compte des espaces introduits par l'imprimante.

coredump
la source
1

Perl, 1,4 * 10 ^ 225

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

Approche similaire à python; même résultat!

alexander-brett
la source
0

> <> , 65534 (?) Programmes

J'ai ajouté un point d'interrogation à côté de 65533 car je n'ai pas encore vérifié qu'il peut imprimer 65533 (même si j'ai des raisons de croire qu'il devrait). Une fois qu'il me reste un peu de temps, je vais trouver un moyen de le tester.

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

Vous pouvez l'essayer en ligne ici .

L'essentiel de ce programme est qu'il modifie la sortie du caractère à la toute fin, puis décrémente sa valeur numérique avant l'impression. J'ai reçu 65534 programmes car la valeur ascii du caractère à la fin du code est 65533, donc en comptant le premier programme, nous avons 65534 (si vous comptez le programme vide 65535, je suppose). Le dernier programme "retourné" n'est rien; il se termine simplement lorsque la valeur du caractère est 0.

Je suis sûr qu'il pourra imprimer un caractère pour toutes les itérations: je n'ai pas pu trouver de source définitive pour combien de caractères> <> peut imprimer, mais il y a des caractères directement en dessous de 65533, numériquement.

Faites-moi savoir s'il y a des problèmes avec cette mise en œuvre; Je ne suis pas certain de la validité de mon entrée.


Explication

J'ai volé sans vergogne l'idée d'utiliser un guillemet simple pour créer une pseudo-quine à partir du wiki> <> et un commentaire que j'ai vu ici une fois.

":?!;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 

Ce qu'il fait, c'est tout analyser après le guillemet en tant que caractères, puis décrémenter le dernier. De là, il inverse simplement la pile (afin d'imprimer dans le bon ordre), pousse un guillemet sur la pile, puis imprime jusqu'à ce que la pile soit vide.

cole
la source
0

Python, 1 × 10 ^ 194 programmes

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

Cela doit être exécuté à partir d'un fichier, pas d' une réplique interactive. Ce n'est pas une quine.

Merci à @The Turtle de m'avoir aidé à économiser 3 octets, ce qui est plus de place pour neuf!
Merci à @poke de m'avoir aidé à économiser 2 octets, ce qui est plus de place pour neuf!

Amateur de fromage
la source
@ Cheese Lover Le if n!=0est redondant. Vous pouvez simplement écrire if n.
The Turtle
Vous pouvez également vous débarrasser de deux espaces; après le if n:et entre les replacearguments.
poke
0

Bash, 52 programmes

Absolument sans inspiration et (espérons-le) solidement à la dernière place.

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
la source