Entropic Quine!

12

Votre tâche consiste à écrire un programme ou une fonction qui:

  • Lorsqu'il est exécuté pour la première fois, génère son code source.
  • Lors des exécutions ultérieures, il devrait sortir ce qu'il a sorti précédemment, mais avec un changement de caractère aléatoire (défini ci-dessous). Il n'est pas nécessaire que ce soit un changement uniformément aléatoire, mais chaque changement possible devrait avoir une chance non nulle de se produire.

    Après la première exécution, votre programme ne sera plus nécessairement une quine; la sortie aura changé (et le programme est libre de se modifier également).

Par exemple, si votre quine l'était ABCD, son exécution répétée pourrait imprimer:

ABCD
A!CD
j!CD
j!CjD

Caractéristiques

  • Un changement de caractère est soit:

    • L'insertion d'un caractère aléatoire,
    • La suppression d'un caractère aléatoire, ou
    • Un remplacement d'un personnage par un nouveau personnage aléatoire. Notez que le nouveau caractère peut être identique à celui qu'il remplace, auquel cas aucune modification ne sera effectuée.

    Bien sûr, la suppression ou le remplacement d'un caractère d'une chaîne vide n'est pas une modification valide.

  • Bien que cela soit étiqueté , les règles contre la lecture de votre code source ne s'appliquent pas.

Vous pouvez utiliser n'importe quel jeu de caractères tant qu'il comprend les caractères utilisés dans votre code source.

Esolanging Fruit
la source
1
À quels caractères chaque personnage fait-il référence?
Dennis
2
À quelle fréquence cela doit-il fonctionner? De toute évidence, il ne peut pas être arbitrairement souvent ou autrement tous les programmes possibles aussi longs ou plus longs que celui d'origine doit être une solution au défi.
Martin Ender
1
Le personnage peut-il être ajouté n'importe où ou juste à la fin?
Conor O'Brien
1
@ ConorO'Brien Anywhere.
Esolanging Fruit
1
Combien d'itérations doit-il fonctionner?
dylnan

Réponses:

7

Python 3 , 288 270 224 212 195 196 194 180 178 168 168 octets

f=__file__
m=open(f).read()
x=m	
print(end=x)
h=hash
k=h(f)
n=k%2
a=h(m)%-~len(x)
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]
open(f,'w').write(m.replace("\t",";x=%r\t"%x))

Essayez-le en ligne!

Après avoir imprimé le code source du fichier lors de la première itération, nous ajoutons une ligne supplémentaire pour définir x au nouveau code source, plutôt que m.

Explication:

f=__file__    #Open and read the source code
m=open(f).read()

x=m       #Set x to the source code for the first iteration
x="..."
...
x="..."   #Set x to the latest iteration
          #On the last iteration there's a tab character to mark progress
print(end=x)    #Print the previous iteration's text

#Modify the text
h=hash
k=h(f)            #Generate a random number to use
n=k%2             #Whether the character will be inserted or changed/deleted
a=h(m)%-~len(x) #The index of the change
                         #Add 1 to the range to append new characters, and to avoid mod by 0 in the case of an empty string
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]    #Make the change

open(f,'w').write(m.replace("\t",";x=%r\t"%x))   #Modify the source code, adding the new iteration of the source code

En supposant que hashrenvoie un nombre uniformément aléatoire, il y a environ 1/6 chance d'insérer un nouveau personnage, 1/6 chance de changer un personnage existant et 2/6 chance de supprimer un personnage. Quelle est la chance sur 2/6 que vous demandez? Mais ça ne fait rien du tout 2/6 du temps!

(Voici un programme de validation adapté des réponses de mbomb007 . Essayez-le en ligne! )

Jo King
la source
Je pense que f=__file__cela aiderait aussi dans la première étape.
Ørjan Johansen
4

Python 3 , 205 195 octets

s='print(end=x);h=hash;k=h(x);n=k%2;a=h(s)%-~len(x);x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:];open(__file__,"w").write("s=%r;x=%r;exec(s)"%(s,x))';x='s=%r;x=%r;x=x%%(s,x);exec(s)';x=x%(s,x);exec(s)

Essayez-le en ligne!

Je voulais essayer une version qui ne lit pas le code source. S'est avéré pas mal comme je le pensais, et il n'y a que 30 octets derrière la version qui le fait . L'explication de son fonctionnement est essentiellement la même que celle de l'autre réponse, mais elle initialise x différemment car elle ne peut pas simplement lire le code source.

Jo King
la source
4

Python 2 , 779 801 octets

Bien que le défi ait été modifié pour montrer que la lecture de votre source est autorisée, je créais déjà ma solution sans cela. Donc, pour montrer que c'est possible, je l'ai terminé. Pas de lecture du fichier source:

s='s=%r;print s%%s\nfrom random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint\nf.write("\\n".join((s%%s).split("\\n")[1:5:2]).replace("4",`map(ord,s%%s)`))\nif L>5:exec\'b=[];h=%%d\\nwhile~-h:b+=[h%%%%1000];h/=1000\\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\\nprint"".join(map(chr,L))\'%%1\n\nn=R(0,2);p=R(0,len(L if L>5else s%%s));r=R(0,255);f.write("%%03d"*3%%(n,p,r))';print s%s
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
if L>5:exec'b=[];h=%d\nwhile~-h:b+=[h%%1000];h/=1000\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\nprint"".join(map(chr,L))'%1

n=R(0,2);p=R(0,len(L if L>5else s%s));r=R(0,255);f.write("%03d"*3%(n,p,r))

Essayez-le en ligne! (Notez que cela ne modifiera pas la source. Vous devez l'exécuter localement pour que cela fonctionne)

Pour montrer que les transformations fonctionnent, voici un programme de test (actuellement mis en place pour prendre toujours 100pour r, et il imprime le résultat pour chaque combinaison de net ppour la liste initiale.)



Explication:

s='s=%r;print s%%s...';print s%s...

La première ligne est votre quine classique, mais beaucoup plus longue pour tenir compte de ce qui vient après.

from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint

Importer pour des entiers aléatoires. Ldeviendra une liste d'ordinaux du code source, mais au départ c'est un entier qui n'est utilisé nulle part ailleurs dans la source pour permettre un remplacement de chaîne. Ouvrez le fichier pour écrire la nouvelle source. Lors des exécutions ultérieures, il s'ouvrira pour s'ajouter à la place.

f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))

Supprimez les première et troisième lignes de code. Remplacez ce qui 4précède par la liste des ordinaux.

if L>5:exec'b=[];h=%d\nwhile~-h:b+=[h%%1000];h/=1000\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\nprint"".join(map(chr,L))'%1

n=R(0,2);p=R(0,len(L if L>5else s%s));r=R(0,255);f.write("%03d"*3%(n,p,r))

En morceaux:

  • if L>5:- Ignore cette ligne lors de la première exécution. Plus tard, Lsera une liste, et cela s'exécutera. Je vais expliquer le execdernier, car il n'est pas exécuté la première fois.

  • n- Un nombre aléatoire 0-2. Ceci détermine quelle modification se produit (0 = insérer, 1 = remplacer, 2 = supprimer).

  • p - Une position aléatoire dans la liste où la modification se produira.

  • r - Un nombre aléatoire à insérer ou à remplacer dans la liste

  • f.write("%03d"*3%(n,p,r))- Ajoutez les 3 aléas à la fin du fichier source. À chaque exécution, cela s'ajoutera à un entier qui code toutes les modifications apportées à la source initiale qui se sont produites.

  • exec'b=[];h=%d...'%1...- Obtenez les nombres aléatoires (trouvés après %1lors des exécutions ultérieures), appliquez les modifications à la liste et imprimez.

  • while~-h:b+=[h%%1000];h/=1000- Construisez une liste des aléas générés jusqu'à présent, en tenant compte de l'interlignage 1, ce qui évite les problèmes avec les zéros non significatifs.

  • while b:r,p,n=b[-3:];b=b[:-3] - Attribuez les aléas pour cette itération.

  • L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1] - (0 = insérer, 1 = remplacer, 2 = supprimer)

  • print"".join(map(chr,L)) - Imprimez la source modifiée.

mbomb007
la source
Cela supprime-t-il parfois un caractère inexistant à la fin de la chaîne? Puisque ppeut être la longueur de la chaîne. De plus, quel est le comportement avec une chaîne vide?
Jo King
@JoKing J'ai ajouté un programme de test. Chaque changement de personnage possible peut se produire. Il montre simplement que chaque position peut être sélectionnée pour une insertion, un remplacement ou une suppression, et qu'il gère une liste vide. tio.run/##LYoxDsMgDEVnOAUjCAZgRO0NuIHloUOaRIocy6JDT08dpdt/…
mbomb007
Je ne pense pas qu'aucun changement ne soit valide, même si j'ai demandé au PO. La question ne ditOf course, deleting or replacing a character from an empty string is not a valid change
Jo King
J'ai demandé à Esolanging Fruit, et ils disent qu'aucun changement n'est valide, mais pas pour une chaîne vide.
Jo King
1
@JoKing devrait être corrigé.
mbomb007
1

Java 10, 370 octets

String s;v->{if(s==null){s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%3<2?c:"")+s.substring(r+(c%3>0?1:0));}}

Essayez-le en ligne.

Explication:

String s;               // Class-level String variable to store the modifying source code
v->{                    // Method without parameter nor return-type
  if(s==null){          //  If this is the first execution of this function:
    s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";
                        //   Set `s` to the unformatted source-code
    s=s.format(s,34,s);}//   And then to the formatted source-code
else{                   //  For any following executions of this function:
  int r=s.length();r*=Math.random();
                        //   Random index in range [0, length_of_modified_source_code)
  char c=127;c*=Math.random();
                        //   Random ASCII character in unicode range [0, 127)
  s=                    //   Replace the current String `s` with:
    s.substring(0,r)    //    The first [0, `r`) characters of the modified source code `s`
    +(c%3<2?            //    If the random option is 0 or 1:
           c:"")        //     Append the random character
        +s.substring(r  //    Append the rest of the modified source code `s`, but:
          +(c%3>0?      //     If the random option is 1 or 2:
             1:0));}}   //      Skip the first character of this second part

Explication générale:

-part:

  • La chaîne scontient le code source non formaté.
  • %sest utilisé pour entrer cette chaîne en elle-même avec le s.format(...).
  • %c, %1$cEt 34sont utilisés pour formater les guillemets doubles.
  • ( %%est utilisé pour formater le module %).
  • s.format(s,34,s) met tout cela ensemble.

Voici un programme de base Java quine.

Partie défi:

  • String s; est le code source que nous modifierons au niveau de la classe.
  • int r=s.length();r*=Math.random();est utilisé pour sélectionner un index aléatoire du code source dans la plage [0, length_of_modified_source_code).
  • char c=127;c*=Math.random();est utilisé pour sélectionner un caractère ASCII aléatoire (y compris les non imprimables) dans la plage unicode [0, 126].
  • c%3est utilisé pour sélectionner une option aléatoire de 0, 1 ou 2. L'option 0 ajoutera le caractère aléatoire avant l'index r; l'option 1 remplacera le caractère à l'index rpar le caractère aléatoire; et l'option 2 supprimera le caractère à l'index r.
Kevin Cruijssen
la source