Selbstverstümmelungsprogramm

16

Kurz gesagt, Ihr Ziel ist es, ein vollständiges Programm zu erstellen, das seinen eigenen Quellcode ändert, bis jedes Zeichen der Quelle anders ist als das, als das es begonnen hat.

Bitte geben Sie in Ihrem Beitrag sowohl die Anfangsquelle als auch die Endquelle sowie eine Beschreibung an. ZB Beschreiben Sie, was (sonst) Ihr Programm macht, welche Sprache Sie verwendet haben, Ihre Strategie usw.

Regeln

  • Ihr Programm muss einige Zeit nach Abschluss der Änderung angehalten werden.
  • Es muss seinen eigenen, aktuell ausgeführten Quellcode ändern (nicht unbedingt die Datei, die Sie an den Interpreter übergeben haben, es muss seine Anweisungen ändern), kein neues Programm drucken oder eine neue Datei schreiben.
  • Standardlücken sind nicht zulässig.
  • Kürzeste Sendung gewinnt.

  • Wenn Ihre Sprache ihre eigene Datei ändern und einen neuen Compiler-Prozess ausführen kann, aber ihren eigenen (derzeit ausgeführten) Quellcode nicht ändern kann, können Sie ein solches Programm stattdessen mit einer aufgerundeten Strafe von + 20% schreiben. Echte selbstmodifizierende Sprachen sollten einen Vorteil haben.

Bearbeiten : Wenn Ihr Programm mit Fehlern anhält, geben Sie es bitte als solches an (und sagen Sie vielleicht, was die Fehler sind.)

mbomb007
quelle
7
Verstehe ich richtig, dass das Programm seine eigene Quelle ändern sollte, während es ausgeführt wird, in einer Weise, die möglicherweise sein Verhalten beeinflusst? Dies würde die meisten nicht-esoterischen Sprachen ausschließen. Oder darf die Quelle geändert und ein neuer Interpreter / Compiler-Prozess darauf gestartet werden?
Zgarb
@Zgarb Es muss tatsächlich seinen eigenen, aktuell ausgeführten Quellcode ändern. Ja, das schließt die meisten Sprachen aus.
mbomb007
8
@ mbomb007 Das ist schlimm.
Mittwoch,
1
@ mbomb007 Es steht nirgendwo in Ihrer Herausforderung, dass der geänderte Quellcode ausgeführt werden muss.
Mittwoch,
1
Nein, das macht diese Herausforderung nicht trivial. Sie haben damit zu viele Sprachen ausgeschlossen.
Mittwoch,

Antworten:

19

/// , 1 Byte

/

Das Programm findet eine /(den Beginn einer Musterersetzungsgruppe) und entfernt sie in Vorbereitung auf die Ersetzung. Dann erreicht es EOF, gibt also auf und hält an.

Lirtosiast
quelle
Das ist die früheste Antwort mit 1 Byte, es ist also der Gewinner.
mbomb007
22

Labyrinth , 2 Bytes

>@

Das >dreht die Quelle so, dass es wird

@>

Der Befehlszeiger befindet sich jetzt in einer Sackgasse und dreht sich um, um den zu treffen, der @das Programm beendet.

<@Würde natürlich auch funktionieren.

Martin Ender
quelle
12

Python 2, 225 Bytes

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)

Der endende Quellcode ist eine Zeichenfolge von "0"s, deren Länge der Anzahl der Bytes im ursprünglichen kompilierten Codeobjekt entspricht.

Der Code findet das ausgeführte Codeobjekt sys._getframe().f_code.co_codeund erstellt eine Struktur, die Python-String-Objekte darstellt. Es erhält dann den Speicher, den der Code tatsächlich benötigt, und ersetzt ihn durch "0"*len(c).

Wenn das Programm ausgeführt wird, wird es mit dem folgenden Traceback beendet:

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

Dies zeigt, dass das Überschreiben erfolgreich war und das Programm abstirbt, weil 0kein gültiger Opcode vorliegt.

Ich bin überrascht, dass dies sogar in Python möglich ist, Frame-Objekte sind schreibgeschützt, ich kann keine neuen erstellen. Das einzig Komplizierte dabei ist, ein unveränderliches Objekt (einen String) zu ändern.

Blau
quelle
Ich bin mir nicht sicher, ob dies den Anforderungen entspricht, dass JEDER Charakter anders sein muss. Die "1" im ursprünglichen Quellcode wäre immer noch eine "1" im entstellten Code ...
Darrel Hoffman
Tatsächlich ist die "1"Zeichenfolge im Code nicht Teil des "Codes", sondern nur eine Konstante, auf die im Bytecode verwiesen wird. Was ich gerade ändere, sind die kompilierten Opcodes der virtuellen Python-Maschine, nicht die Konstanten oder Variablen. Was ich ändere, ist also nicht der Quellcode, sondern nur der kompilierte Code. Ich könnte den Quellcode wie gespeichert ändern, aber das würde den Code zur Laufzeit nicht beeinflussen, da er bereits kompiliert worden wäre. Wenn Sie wollten, könnte ich dies in einem 'kompilierten Python 2.7-Opcode mit Konstanten' posten, aber das wäre albern, IMO.
Blue
Außerdem kann ich mir den kompilierten Code nicht ansehen, da ich durch Ändern des Codes den Code tatsächlich ändere, was bedeutet, dass ich den Code nicht wirklich sehe. Ich habe also keine Ahnung, ob der Code wirklich jedes Zeichen ersetzt, nur dass er die meisten (?) Von ihnen ändert
Blue
Um das zu umgehen das Problem der 1 nicht in dem kompilierten Code geändert wird, können Sie das ändern , "1"um <backtick>1+1<backtick>nur zwei weiteren Bytes
Mego
Nicht das ich sehe (kompiliert mit 2.7.10). Leider wird das 1+1von meinem Vorschlag 2in der kompilierten Version verwandelt ... Der Compiler ist zu schlau für sich selbst!
Mego
11

böse , 1 Byte

q

Das Böse hat mehrere Speicher - einer ist der Quellcode selbst und einer ist das Rad, das eine kreisförmige Warteschlange ist, die auf eine einzige Null initialisiert wird. qtauscht den Quellcode und das Rad aus, sodass die Quelle durch ein Null-Byte ersetzt wird. Allerdings sind nur Kleinbuchstaben echte Operatoren im Bösen, sodass dieses Zeichen einfach ein No-Op ist und das Programm beendet wird.

Martin Ender
quelle
6

MSM , 8 Bytes

'.qp.;.;

Transformiert den Quellcode in pqpqpqpq

MSM arbeitet mit einer Liste von Zeichenfolgen. Befehle werden von links genommen und die rechte Seite als Stapel behandelt. MSM arbeitet immer an seiner eigenen Quelle.

Ausführungsablaufverfolgung:

'.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
quelle
6

Malbolge, 1 oder 2 Bytes.

D

Die Malbolge-Sprache "verschlüsselt" jeden Befehl nach seiner Ausführung, sodass dieser Buchstabe (Malbolge NOP) zu einem !(was auch ein NOP ist) wird und dann endet. Aus irgendeinem Grund benötigt der Malbolge-Interpreter, den ich verwende, zwei Bytes, um ausgeführt zu werden DC. Beide sind Nops. !UBeide sind auch Nops.

Bearbeiten: Der Anfangszustand des Malbolge-Speichers hängt von den letzten beiden Zeichen im Code ab, daher ist er für Ein-Zeichen-Programme nicht genau definiert. (Obwohl dieser Code den Anfangszustand des Speichers nicht berücksichtigt)

Pfeffer
quelle
5

x86 asm - 6 Bytes

Ich bin mir nicht sicher, ob "bis jedes Zeichen der Quelle anders ist als das, als das es begonnen hat" sich auf jedes Byte, jede nemonische oder allgemeine Modifikation bezieht. Wenn ich ungültig bin, kann ich das xor in ein rep xor ändern, so dass jedes Bit seine Werte ändert, aber ich hatte gehofft, dass ich das nicht tun kann, um 6 weitere Bytes zu sparen, um zumindest ein bisschen vergleichbar mit diesen Spezialgolfsprachen zu bleiben.

Alles, was dies bewirkt, ist, ein c2 in ein c3 zu ändern, indem die Live-Adresse von eip abgerufen und 5 Bytes davor gespeichert werden.

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
quelle
5

SMBF , 92 Bytes

Kann golfen werden und ich werde wahrscheinlich später mehr daran arbeiten.

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

Erläuterung

Das Programm generiert die folgenden Befehle am Ende seines Bands, um sich selbst zu löschen. Daher muss es die folgenden Werte auf dem Band generieren:

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

Machen Sie eine Reihe von 91s, mit Nullen (angezeigt als _) dazwischen, um sie für temporäre Werte zu verwenden.

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

code__91_91_91_91_91_91_
   ^

Passen Sie die Werte an die Unterschiede an

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

Das Band nach der Ausführung besteht ausschließlich aus Nullen, mit Ausnahme des generierten Codes [_[_-_]_<_].

Hinweis:

Dieses Programm hat mir klar gemacht, dass mein Python-Interpreter für SMBF einen oder zwei Fehler aufweist, und ich habe noch keine Lösung gefunden. Es ist jetzt behoben.

mbomb007
quelle
4

Emacs Lisp 22 Bytes

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

Führen Sie von REPL aus:

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)

Funktion wertet jetzt auf aus nil.

Abwechselnd 30 Bytes

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

Bewerten und Fehler als void-function. Funktion existierte vor der Ausführung.

Jonathan Leech-Pepin
quelle
4

Redcode , 7 Bytes, 1 Anweisung (Nur ein Beispiel. Nicht konkurrierend)

Dies ist ein triviales Beispiel.

Verschiebt den nächsten Speicherort auf sich selbst und stoppt dann (da der gesamte Speicher auf initialisiert wird DAT 0 0, wodurch das Programm bei der Ausführung angehalten wird).

MOV 1 0
mbomb007
quelle
2
Warum zählen Sie dies als Anweisungen anstelle von Bytes?
Martin Ender
Weil ich nicht weiß, wie viele Bytes es sind. Ich denke, das ist abhängig von der Speichergröße oder der Implementierung? ...
mbomb007
4
Ich würde nach ASCII-Zeichen zählen, wenn Sie nicht wissen, wie es implementiert ist.
Lirtosiast
1
Auf der Wikipedia-Seite: Jeder Redcode-Befehl belegt genau einen Speicherplatz und benötigt genau einen Zyklus zur Ausführung. ... Der Speicher wird in Einheiten einer Anweisung adressiert.
mbomb007
3
Alle Code-Golf- Posts werden in Bytes gewertet. Da es keinen Redcode-Maschinencode gibt, müssen wir die Zeichen in der "Assembly-Quelle" verwenden, nicht die, zu denen sie zusammengesetzt sind.
Lirtosiast
3

Powershell 65 Bytes

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

Definieren Sie eine Funktion, die sich selbst auf null zurücksetzt.

Bewerten Sie es einmal und es beseitigt sich.

Alternativ (löscht sich aus dem Speicher) 36 Bytes

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

Wenn Sie es zuerst aufrufen, wird es entfernt und dann versucht, es rekursiv auszuwerten. Fehler als unbekannter Befehl.

Jonathan Leech-Pepin
quelle
3

MIXAL, 6 Bytes (zählen 2 Tabs)

    STZ    0

Das Programm startet an Speicherplatz 0 und schreibt dann 0 in Speicherplatz 0, wodurch es sich selbst löscht. Die Maschine stoppt automatisch.

Dies ist die Assemblersprache für Donald Knuths hypothetischen MIX-Computer, der mit dem GNU MIX Development Kit ( https://www.gnu.org/software/mdk/ ) zusammengestellt und ausgeführt werden kann .

Musarithmie
quelle
3

> <> , 40 34 30 Byte

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

Probieren Sie es hier aus!

Erläuterung:

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

Grundsätzlich werden 3 Zeichenblöcke wie folgt im Stapel abgelegt: (ypos, xpos, ASCII-Zeichen), die am Ende umgekehrt werden, sodass der endgültige Befehl 'p' (character, xpos, ypos) lautet und diese Position in der Zeile festlegt Code für dieses Zeichen. Das erste Zeichen wird manuell als '<' festgelegt, sodass der Code am Ende als '> p <' endet, um den Befehl zu wiederholen. Dann wird jedes andere Zeichen als '' einschließlich des Zeichens p überschrieben. Das '' ist eigentlich "ASCII CHAR 0", was KEINE NOP ist und beim Lesen einen Fehler ausgibt.

Außerdem muss vor dem Befehl 'p' eine ungerade (?) Anzahl von Zeichen stehen, sonst wird der Befehl nicht in eine letzte Schleife zurückgeschleift und überschrieben.

Torcado
quelle
2

Batch, 11 Bytes

@echo>%0&&*

Ändert den Quellcode in 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.

Das @ist da, damit der Befehl nicht wiederholt wird, aber meistens, damit die beiden echonicht in einer Reihe stehen.

ericw31415
quelle
Das @kann entfernt werden, weil ECHO(Großbuchstaben)! = echo(Kleinbuchstaben)
pppery
@ppperry Die beiden echokönnen sich nicht aneinanderreihen .
ericw31415
Aber es sind verschiedene Fälle.
Paprika
2

Jolf, 4 Bytes, nicht konkurrierend

₯S₯C

Dies ₯Ssetzt den ₯CWert des ode-Elements in den Eingang, undefinedda keiner angegeben ist. Probieren Sie es hier aus!

Conor O'Brien
quelle
0

(Dateisystem) Befunge 98, 46 Bytes

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

Beachten Sie, dass dieses Programm eine Datei mit dem Namen erstellt und bearbeitet a. Wie es funktioniert:

  1. Mit dem Code wird eine Datei amit dem Namen erstellt, die den gesamten Code enthält (maximal 256 Zeichen in jeder Dimension) und um eine Stelle nach oben und zwei Stellen nach links verschoben.
  2. Dieses Programm liest dann die aals eine Zeile bezeichnete Datei und ersetzt die gesamte erste Zeile durch den Inhalt dera Datei.
  3. Die zweite Zeile, die vor der IP kopiert wurde, wird ausgeführt
  4. Womit die aDatei in die zweite Zeile eingelesen wird, hat sich zwei Stellen nach rechts verschoben.

Als Nebeneffekt ist der endende Quellcode nicht einmal gültig Befunge! (weil es Zeilenumbrüche als Daten in einer einzelnen Zeile enthält)

Pfeffer
quelle
0

Python 2, 238 Bytes + 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"):])

Im Grunde wechselt dies die aktuelle Dateicodierung der Python-Quelle zwischen asciiund utf-8ändert somit im Wesentlichen jedes Zeichen der Quelle!

Prahlad Yeri
quelle
Es gibt einige zusätzliche Leerzeichen, die entfernt werden können. ) as-> )as, ) else-> )else, "utf-8"if, 'w',encoding.
mbomb007