Programme d'auto-mutilation

16

Autrement dit, votre objectif est de créer un programme complet qui modifie son propre code source jusqu'à ce que chaque caractère de la source soit différent de ce qu'il était au départ.

Veuillez inclure la source de début ainsi que la source de fin dans votre message, ainsi qu'une description. Par exemple, décrivez ce que fait (autrement) votre programme, le langage que vous avez utilisé, votre stratégie, etc.

Règles

  • Votre programme doit s'arrêter quelque temps après la fin de la modification.
  • Il doit en fait modifier son propre code source en cours d'exécution (pas nécessairement le fichier que vous avez passé à l'interpréteur, il modifie ses instructions), ne pas imprimer un nouveau programme ou écrire un nouveau fichier.
  • Les failles standard ne sont pas autorisées.
  • Le programme le plus court gagne.

  • Si votre langue peut modifier son propre fichier et exécuter un nouveau processus de compilation, mais ne peut pas modifier son propre code source (en cours d'exécution), vous pouvez écrire un tel programme à la place avec une pénalité de + 20% octets, arrondie. Les vrais langages auto-modifiants devraient avoir un avantage.

Edit : Si votre programme s'arrête avec des erreurs, veuillez le spécifier comme tel (et peut-être dire quelles sont les erreurs.)

mbomb007
la source
7
Dois-je comprendre correctement que le programme doit modifier sa propre source pendant son exécution, d'une manière qui affecte potentiellement son comportement? Cela exclurait la plupart des langues non ésotériques. Ou est-il autorisé à modifier la source et à lancer un nouveau processus interpréteur / compilateur dessus?
Zgarb
@Zgarb Il doit en fait modifier son propre code source en cours d'exécution. Oui, cela exclut la plupart des langues.
mbomb007
8
@ mbomb007 C'est mauvais.
mınxomaτ
1
@ mbomb007 Il n'est dit nulle part dans votre contestation qu'il doit exécuter le code source modifié.
mınxomaτ
1
De plus, non, cela ne rend pas ce défi trivial, il sera toujours bien défini. Vous avez exclu trop de langues avec cela.
mınxomaτ

Réponses:

19

/// , 1 octet

/

Le programme trouve un /(le début d'un groupe de remplacement de modèle) et le supprime en préparation pour effectuer le remplacement. Ensuite, il atteint EOF, donc il abandonne et s'arrête.

lirtosiast
la source
C'est la première réponse avec 1 octet, c'est donc le gagnant.
mbomb007
22

Labyrinthe , 2 octets

>@

Le >fait pivoter la source pour qu'elle devienne

@>

Le pointeur d'instruction est maintenant dans une impasse et se retourne pour frapper le @qui termine le programme.

Bien sûr, <@cela fonctionnerait aussi.

Martin Ender
la source
12

Python 2, 225 octets

import sys
from ctypes import*
c=sys._getframe().f_code.co_code
i=c_int
p=POINTER
class S(Structure):_fields_=zip("r"*9+"v",(i,c_void_p,i,c_char_p,i,p(i),i,c_long,i,c_char*len(c)))
cast(id(c),p(S)).contents.v=`len([])`*len(c)

Le code source de fin est une chaîne de "0"s dont la longueur est égale au nombre d'octets dans l'objet de code compilé d'origine.

Le code trouve l'objet de code en cours d'exécution sys._getframe().f_code.co_codeet crée une structure qui représente les objets chaîne de python. Il obtient ensuite la mémoire que le code prend réellement et la remplace "0"*len(c).

Lorsqu'il est exécuté, le programme se termine avec le retraçage suivant:

XXX lineno: 7, opcode: 49
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    cast(id(c),p(S)).contents.v=`1+1`*len(c)
SystemError: unknown opcode

Cela montre que l'écrasement a réussi et que le programme meurt parce qu'il 0n'est pas un opcode valide.

Je suis surpris que cela soit même possible en python, les objets frame sont en lecture seule, je ne peux pas en créer de nouveaux. La seule chose compliquée que cela fait est de changer un objet immuable (une chaîne).

Bleu
la source
Je ne sais pas si cela répond tout à fait aux exigences que CHAQUE caractère doit être différent. Le "1" dans le code source d'origine serait toujours un "1" dans le code mutilé ...
Darrel Hoffman
Eh bien en fait, la "1"chaîne dans le code ne fait pas partie du «code», c'est juste une constante à laquelle se réfère le bytecode. Ce que je change en fait, ce sont les opcodes de machine virtuelle python compilés, pas les constantes ou les variables. Donc ce que je change n'est pas le code source proprement dit, juste le code compilé. Je pouvais changer le code source tel qu'il était stocké, mais cela n'affecterait pas réellement le code au moment de l'exécution car il aurait déjà été compilé. Si vous le vouliez, je pourrais poster ceci dans un «opcodes Python 2.7 compilés avec des constantes», mais ce serait idiot IMO.
Blue
Et aussi, je ne peux pas regarder le code compilé car en le modifiant pour voir à l'intérieur, je change en fait le code, ce qui signifie que je ne vois pas réellement le code. Donc vraiment, je n'ai aucune idée si le code remplace vraiment chaque caractère, juste qu'il en change la plupart (?)
Blue
Pour contourner la question du 1 pas changé dans le code compilé, vous pouvez changer le "1"à <backtick>1+1<backtick>seulement 2 octets
Mego
Pas que je vois (compilé avec 2.7.10). Malheureusement, le résultat 1+1de ma suggestion est transformé en un 2dans la version compilée ... Le compilateur est trop intelligent pour son propre bien!
Mego
11

mal , 1 octet

q

evil a plusieurs magasins de mémoire - l'un est le code source lui-même et l'autre est la roue qui est une file d'attente circulaire qui est initialisée à un seul zéro. qéchange le code source et la roue, de sorte qu'il remplace la source par un octet nul. Cependant, seules les lettres minuscules sont de véritables opérateurs dans le mal, de sorte que le caractère est simplement un no-op et le programme se termine.

Martin Ender
la source
6

MSM , 8 octets

'.qp.;.;

Transforme le code source en pqpqpqpq

MSM fonctionne sur une liste de chaînes. Les commandes sont prises depuis la gauche et elles traitent le côté droit comme une pile. MSM fonctionne toujours sur sa propre source.

Trace d'exécution:

'.qp.;.;                       upon start the source is implicitly split into a
                               list of single char strings

' . q p . ; . ;                ' takes the next element and pushes it on the stack
    q p . ; . ; .              q is not a command so it's pushed
      p . ; . ; . q            same for p
        . ; . ; . q p          . concats the top and next to top element
          ; . ; . pq           ; duplicates the top element
            . ; . pq pq        concat
              ; . pqpq         dup
                . pqpq pqpq    concat
                  pqpqpqpq     MSM stops when there's only one element left      
nimi
la source
6

Malbolge, 1 ou 2 octets.

D

Le langage Malbolge "crypte" chaque instruction après l'avoir exécutée, donc cette lettre (Malbolge NOP) deviendra un !(qui est aussi un nop), puis se terminera. Pour une raison quelconque, l'interpréteur Malbolge que j'utilise nécessite deux octets pour s'exécuter, ce qui donne DC(les deux étant nops) devenant !U(les deux étant également nops)

Modifier: l'état initial de la mémoire Malbolge dépend des deux derniers caractères du code, il n'est donc pas bien défini pour les programmes à un caractère. (Bien que ce code ne se soucie pas de l'état initial de la mémoire)

pppery
la source
5

x86 asm - 6 octets

Je ne sais pas si "jusqu'à ce que chaque caractère de la source soit différent de ce qu'il a commencé comme" fait référence à chaque octet, à chaque modification némonique ou générale. si je ne suis pas valide, je peux changer le xor en un xor de répétition pour que chaque bit change les valeurs mais espérait ne pas le faire pour économiser 6 octets de plus pour rester au moins un peu comparable à ces langages de golf spécialisés.

Tout cela ne fait que changer un c2 en un c3 retn en obtenant l'adresse live de eip et xoring 5 octets en face.

58          | pop eax                        ; store addr of eip in eax
83 70 05 01 | xor dword ptr ds:[eax + 5], 1  ; c2 ^ 1 = c3 = RETN
c2          | retn                           ; leave
Pulga
la source
5

SMBF , 92 octets

Peut être joué au golf, et je vais probablement y travailler plus tard.

>>+>>+>>+>>+>>+>>+[<-[>+<---]>+++++<<]>>>>>--[>-<++++++]>--->>++>+++++[>------<-]>->>++[<<]<

Explication

Le programme génère les commandes suivantes à la fin de sa bande pour s’effacer, il doit donc générer les valeurs suivantes sur la bande:

[[-]<]          ASCII: 91 91 45 93 60 93

Faites un tas de 91s, avec des _valeurs nulles (affichées comme ) entre à utiliser pour les valeurs temporaires.

>>+>>+>>+>>+>>+>>+[<-[>+<---]>+++++<<]

code__91_91_91_91_91_91_
   ^

Ajustez les valeurs par les différences

>>>>>--[>-<++++++]>---  Sub 46
>>++                    Add 2
>+++++[>------<-]>-     Sub 31
>>++                    Add 2
[<<]<                   Shift left to the code
code__[_[_-_]_<_]_      Zero out the code
   ^

La bande après l'exécution sera entièrement composée de zéros, à l'exception du code généré [_[_-_]_<_].

Remarque:

Ce programme m'a fait réaliser que mon interprète Python pour SMBF a un bogue ou deux, et je n'ai pas encore trouvé de correctif. C'est réparé maintenant.

mbomb007
la source
4

Emacs Lisp 22 octets

(defun a()(defun a()))

Exécutez à partir de REPL:

ELISP> (defun a()(defun a()))
a
ELISP> (symbol-function 'a)
(lambda nil
  (defun a nil))

ELISP> (a)
a
ELISP> (symbol-function 'a)
(lambda nil nil)

La fonction est désormais évaluée à nil.

Alternativement (se délier) 30 octets

(defun a()(fmakunbound 'a)(a))

Évaluer et erreurs comme void-function. La fonction existait avant d'être exécutée.

Jonathan Leech-Pepin
la source
4

Redcode , 7 octets, 1 instruction (Juste un exemple. Pas en compétition)

Ceci est un exemple trivial.

Déplace l'emplacement de mémoire suivant sur lui-même, puis s'arrête (car toute la mémoire est initialisée à DAT 0 0, ce qui arrête le programme lorsqu'il est exécuté.)

MOV 1 0
mbomb007
la source
2
Pourquoi comptez-vous cela comme des instructions au lieu d'octets?
Martin Ender
Parce que je ne sais pas combien d'octets c'est. Je pense que cela dépend de la taille de la mémoire ou de l'implémentation? ...
mbomb007
4
Je compterais par caractères ASCII si vous ne savez pas comment cela est implémenté.
lirtosiast
1
Depuis la page Wikipedia: Chaque instruction Redcode occupe exactement un emplacement de mémoire et prend exactement un cycle pour s'exécuter. ... La mémoire est adressée en unités d'une instruction.
mbomb007
3
Tous les messages de code-golf sont notés en octets. Puisqu'il n'y a pas de code machine Redcode, nous devons utiliser les caractères dans la "source d'assemblage", pas ce à quoi il s'assemble.
lirtosiast
3

Powershell 65 octets

function a{si -pat:function:a -va:([scriptblock]::create($null))}

Définissez une fonction qui se réécrit en null.

Évaluez-le une fois et il s’élimine.

Alternativement (se supprime de la mémoire) 36 octets

function a{remove-item function:a;a}

L'appeler d'abord le supprime puis tente d'évaluer de manière récursive. Erreur en tant que commande inconnue.

Jonathan Leech-Pepin
la source
3

MIXAL, 6 octets (comptant 2 onglets)

    STZ    0

Le programme démarre à l'emplacement de mémoire 0, puis écrit 0 à l'emplacement de mémoire 0, s'effaçant ainsi lui-même. La machine s'arrête automatiquement.

Il s'agit du langage d'assemblage de l'ordinateur hypothétique MIX de Donald Knuth, qui peut être assemblé et exécuté à l'aide du kit de développement GNU MIX ( https://www.gnu.org/software/mdk/ ).

musarithmie
la source
3

> <> , 40 34 30 octets

0&00a6*0&1+:&060"c"l=?!.~~r >p

Essayez-le ici!

Explication:

0&          Adds 0 to the registry
00a6*       Adds "0,0,<" to the stack; coords followed by a character
------------loop start (for clarity)
0           0 added to stack
&1+:&       Registry retrieved, increased by 1, duplicated, one put back in registry
0           ASCII character 0 added to stack (just a 0 but will be converted to that character when inserted in the code)
60          6 and 0 added to stack
"c"         The number 99 added to stack (length of code + 1 * 3)
l=?         Code length added to stack, checks if it is equal to 111

!.          If false, pointer jumps back to character (9,0) (loop start position)
~~r >p      If true, removes the 0 and 9, reverses stack, then loops the p command setting
all the characters to a "<" character and the 2nd character to a " "

Fondamentalement, cela met un tas de 3 blocs de caractères dans la pile comme suit: (ypos, xpos, caractère ASCII) qui est inversé à la fin de sorte que la commande finale 'p' se lit (caractère, xpos, ypos) et définit cette position dans le code à ce caractère. Le premier caractère est défini manuellement comme «<», de sorte que le code finit par être «> p <» à la fin pour boucler la commande. Ensuite, chaque autre caractère est remplacé par un '', y compris le caractère p. Le '' est en fait "ASCII CHAR 0" qui n'est PAS un NOP et donnera une erreur lors de la lecture.

Il doit également y avoir un nombre impair (?) De caractères avant la commande 'p', sinon il ne sera pas rebouclé une dernière fois et écrasé.

torcado
la source
2

Lot, 11 octets

@echo>%0&&*

Modifie le code source en ECHO is on.

@           - don't echo the command.
 echo       - print ECHO is on.
     >%0    - write to own file.
        &&* - execute * command after the above is done, * doesn't exist so program halts.

Le @est là pour que la commande ne soit pas répercutée, mais surtout pour que les deux echone s'alignent pas.

ericw31415
la source
le @peut être supprimé, car ECHO(majuscule)! = echo(minuscule)
pppery
@ppperry Les deux echos ne peuvent pas s'aligner.
ericw31415
Mais ce sont des cas différents.
pppery
2

Jolf, 4 octets, sans concurrence

₯S₯C

Ceci ₯Sets la ₯Cvaleur de l'élément ode à l'entrée, undefinedcar aucun n'est donné. Essayez-le ici!

Conor O'Brien
la source
0

(Système de fichiers) Befunge 98, 46 octets

ff*:1100'aof0'ai
               21f0'ai@

Notez que ce programme crée et manipule un fichier nommé a. Comment ça fonctionne:

  1. Le code crée un fichier nommé acontenant le code entier (jusqu'à 256 caractères dans chaque dimension) décalé d'un espace vers le haut et deux vers la gauche.
  2. Ce programme lit ensuite le fichier nommé acomme une seule ligne, remplaçant la première ligne entière par le contenu du afichier.
  3. La deuxième ligne, qui a été copiée devant l'IP, est exécutée
  4. Qui lit le afichier dans la deuxième ligne a décalé de deux places vers la droite.

Comme effet secondaire, le code source final n'est même pas valide Befunge! (car il contient des sauts de ligne sous forme de données sur une seule ligne)

pppery
la source
0

Python 2, 238 octets + 20% = 285,6

# coding: utf-8
import codecs
with codecs.open(__file__,'r') as f:
    t = f.read()
n="utf-8" if t.startswith("# coding: ascii") else "ascii"
with codecs.open(__file__,'w', encoding=n) as f:
    f.write(t[0]+" coding: "+n+t[t.find("\n"):])

Fondamentalement, cela bascule l'encodage du fichier actuel de la source python entre asciiet utf-8, changeant ainsi essentiellement chaque caractère de la source!

Prahlad Yeri
la source
Certains espaces supplémentaires peuvent être supprimés. ) as-> )as, ) else-> )else, "utf-8"if, 'w',encoding.
mbomb007