Program Mutilasi Diri

16

Sederhananya, tujuan Anda adalah membuat program lengkap yang mengubah kode sumbernya sendiri hingga setiap karakter sumber berbeda dari apa yang dimulai.

Harap sertakan sumber awal serta sumber akhir dalam posting Anda, serta deskripsi. Misalnya, Jelaskan apa yang program Anda lakukan, bahasa yang Anda gunakan, strategi Anda, dll.

Aturan

  • Program Anda harus berhenti beberapa saat setelah modifikasi selesai.
  • Ini harus benar-benar memodifikasi sendiri, sedang menjalankan kode sumber (tidak harus file yang Anda berikan kepada penerjemah, itu memodifikasi instruksinya), tidak mencetak program baru atau menulis file baru.
  • Celah standar tidak diijinkan.
  • Kemenangan program terpendek.

  • Jika bahasa Anda dapat memodifikasi file sendiri dan menjalankan proses kompiler baru, tetapi tidak dapat memodifikasi kode sumbernya sendiri (saat ini sedang berjalan), Anda dapat menulis program seperti itu dengan penalti + 20% byte, dibulatkan. Bahasa pengubah otomatis yang sesungguhnya harus memiliki keunggulan.

Sunting : Jika program Anda terhenti karena kesalahan, harap sebutkan itu (dan mungkin katakan apa kesalahannya.)

mbomb007
sumber
7
Apakah saya mengerti benar bahwa program harus memodifikasi sumbernya sendiri ketika sedang berjalan, dengan cara yang berpotensi mempengaruhi perilakunya? Ini akan mengesampingkan sebagian besar bahasa non-esoterik. Atau diizinkan untuk memodifikasi sumber dan meluncurkan proses juru bahasa / kompiler baru di atasnya?
Zgarb
@Zgarb Ini harus benar-benar memodifikasi kode sumbernya sendiri, yang sedang berjalan. Ya, itu mengesampingkan sebagian besar bahasa.
mbomb007
8
@ mbomb007 Itu buruk.
mınxomaτ
1
@ mbomb007 Dikatakan tidak ada di dalam diri Anda yang menantang bahwa ia harus menjalankan kode sumber yang dimodifikasi.
mınxomaτ
1
Juga, tidak itu tidak membuat tantangan ini sepele, itu akan tetap baik cakupannya. Anda mengesampingkan terlalu banyak bahasa dengan ini.
mınxomaτ

Jawaban:

19

/// , 1 byte

/

Program ini menemukan /(awal dari grup pengganti-pola), dan menghapusnya sebagai persiapan untuk melakukan penggantian. Kemudian mencapai EOF, jadi menyerah dan berhenti.

lirtosiast
sumber
Ini adalah jawaban paling awal dengan 1 byte, jadi itu adalah pemenangnya.
mbomb007
22

Labirin , 2 byte

>@

The >berputar sumber sehingga menjadi

@>

Pointer instruksi sekarang berada di jalan buntu dan berbalik untuk mencapai @yang mengakhiri program.

Tentu saja <@akan berhasil juga.

Martin Ender
sumber
12

Python 2, 225 byte

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)

Kode sumber akhir adalah string "0"s yang panjangnya sama dengan jumlah byte dalam objek kode terkompilasi asli.

Kode menemukan objek kode yang sedang berjalan sys._getframe().f_code.co_code,, dan membuat struktur yang mewakili objek string python. Ini kemudian mendapatkan memori yang benar-benar diambil dan diganti dengan kode "0"*len(c).

Saat dijalankan, program keluar dengan traceback berikut:

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

Ini menunjukkan bahwa penimpaan berhasil dan program mati karena 0bukan opcode yang valid.

Saya terkejut bahwa ini bahkan mungkin dalam python, objek bingkai hanya-baca, saya tidak dapat membuat yang baru. Satu-satunya hal yang rumit yang dilakukan adalah mengubah objek yang tidak dapat diubah (string).

Biru
sumber
Tidak yakin apakah ini cukup memenuhi persyaratan bahwa SETIAP karakter harus berbeda. "1" dalam kode sumber asli masih akan menjadi "1" dalam kode yang rusak ...
Darrel Hoffman
Yah sebenarnya, "1"string dalam kode itu sebenarnya bukan bagian dari 'kode', itu hanya sebuah konstanta yang disebut dalam bytecode. Apa yang sebenarnya saya ubah adalah python opcode mesin virtual yang dikompilasi, bukan konstanta atau variabel. Jadi yang saya ubah bukanlah kode sumber per kata, hanya kode yang dikompilasi. Saya dapat mengubah kode sumber sebagai disimpan tetapi itu tidak akan benar-benar mempengaruhi kode saat runtime karena sudah dikompilasi. Jika Anda mau, saya dapat memposting ini dalam 'compcodes Python 2.7 yang dikompilasi dengan konstanta', tetapi itu akan menjadi IMO konyol.
Biru
Dan juga, saya tidak dapat melihat kode yang dikompilasi karena dengan mengubahnya untuk melihat ke dalam, saya benar-benar mengubah kode, yang berarti saya tidak benar-benar melihat kode. Jadi sungguh, saya tidak tahu apakah kode itu benar-benar menggantikan setiap karakter, hanya saja itu mengubah sebagian besar (?) Dari mereka
Biru
Untuk menyiasati masalah 1 yang tidak diubah dalam kode yang dikompilasi, Anda dapat mengubah "1"ke <backtick>1+1<backtick>hanya 2 byte lagi
Mego
Bukan yang saya lihat (dikompilasi dengan 2.7.10). Sayangnya, 1+1dari saran saya berubah menjadi 2dalam versi yang dikompilasi ... Kompiler terlalu pintar untuk kebaikannya sendiri!
Mego
11

jahat , 1 byte

q

jahat memiliki beberapa penyimpanan memori - satu adalah kode sumber itu sendiri dan satu adalah roda yang merupakan antrian melingkar yang diinisialisasi ke nol tunggal. qswap kode sumber dan roda, sehingga menggantikan sumber dengan null-byte. Namun, hanya huruf kecil yang merupakan operator dalam kejahatan, sehingga karakter hanyalah sebuah larangan dan program berakhir.

Martin Ender
sumber
6

MSM , 8 byte

'.qp.;.;

Mengubah kode sumber menjadi pqpqpqpq

MSM beroperasi pada daftar string. Perintah diambil dari kiri dan mereka memperlakukan sisi kanan sebagai tumpukan. MSM selalu bekerja pada sumbernya sendiri.

Jejak eksekusi:

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

Malbolge, 1 atau 2 byte.

D

Bahasa Malbolge "mengenkripsi" setiap instruksi setelah mengeksekusinya, jadi surat ini (Malbolge NOP) akan menjadi !(yang juga merupakan nop), dan kemudian berakhir. Untuk beberapa alasan, interpreter Malbolge yang saya gunakan membutuhkan dua byte untuk dijalankan, memberi DC(keduanya adalah nops) menjadi!U (keduanya juga nops)

Sunting: Keadaan awal memori Malbolge tergantung pada dua karakter terakhir dalam kode, sehingga tidak didefinisikan dengan baik untuk satu program karakter. (Meskipun kode ini tidak peduli dengan keadaan awal memori)

pppery
sumber
5

x86 asm - 6 byte

tidak yakin apakah "sampai setiap karakter sumber berbeda dari apa yang dimulai sebagai" mengacu pada setiap byte, setiap nemonik, atau modifikasi umum. jika saya tidak valid saya dapat mengubah xor menjadi repor xor sehingga setiap bit mengubah nilai tetapi berharap tidak melakukan itu untuk menghemat 6 byte lebih agar tetap setidaknya sedikit sebanding dengan bahasa-bahasa golf khusus ini.

Semua ini dilakukan adalah mengubah c2 ke c3 retn dengan mendapatkan alamat langsung eip dan xoring 5 byte di depan.

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

SMBF , 92 byte

Dapat bermain golf, dan saya mungkin akan mengerjakannya lebih lanjut nanti.

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

Penjelasan

Program menghasilkan perintah-perintah berikut di akhir rekamannya untuk menghapus dirinya sendiri, sehingga ia harus menghasilkan nilai-nilai berikut pada rekaman itu:

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

Buat sekelompok 91s, dengan nulls (ditampilkan sebagai _) antara untuk digunakan untuk nilai temp.

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

code__91_91_91_91_91_91_
   ^

Sesuaikan nilainya dengan perbedaan

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

Eksekusi rekaman berikut akan semua nol, dengan pengecualian kode yang dihasilkan [_[_-_]_<_].

catatan:

Program ini membuat saya menyadari bahwa juru bahasa Python saya untuk SMBF memiliki satu atau dua bug, dan saya belum menemukan cara untuk memperbaikinya. Sudah diperbaiki sekarang.

mbomb007
sumber
4

Emacs Lisp 22 byte

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

Jalankan dari 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)

Fungsi sekarang dievaluasi menjadi nil.

Bergantian (lepaskan ikatannya sendiri) 30 byte

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

Evaluasi dan galat sebagai void-function. Fungsi sudah ada sebelum dijalankan.

Jonathan Leech-Pepin
sumber
4

Redcode , 7 byte, 1 instruksi (Hanya sebuah contoh. Tidak bersaing)

Ini adalah contoh sepele.

Memindahkan lokasi memori berikutnya ke dalam dirinya sendiri, lalu berhenti (karena seluruh memori diinisialisasi ke DAT 0 0, yang menghentikan program ketika dieksekusi.)

MOV 1 0
mbomb007
sumber
2
Mengapa Anda menghitung ini sebagai instruksi, bukan byte?
Martin Ender
Karena saya tidak tahu berapa byte. Saya pikir itu tergantung pada ukuran memori, atau implementasi? ...
mbomb007
4
Saya akan menghitung dengan karakter ASCII jika Anda tidak tahu bagaimana penerapannya.
lirtosiast
1
Dari halaman Wikipedia: Setiap instruksi Redcode menempati tepat satu slot memori dan membutuhkan tepat satu siklus untuk dijalankan. ... Memori ditangani dalam satuan satu instruksi.
mbomb007
3
Semua posting kode-golf dinilai dalam byte. Karena tidak ada kode mesin Redcode, kita harus menggunakan karakter dalam "sumber perakitan", bukan untuk apa dirakitnya.
lirtosiast
3

Powershell 65 byte

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

Tentukan fungsi yang menulis ulang dirinya sendiri menjadi nol.

Evaluasilah sekali dan hilangkan dengan sendirinya.

Bergantian (menghapus sendiri dari memori) 36 byte

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

Menyebutnya terlebih dahulu menghapusnya kemudian mencoba untuk mengevaluasi secara rekursif. Kesalahan sebagai perintah yang tidak dikenal.

Jonathan Leech-Pepin
sumber
3

MIXAL, 6 byte (menghitung 2 tab)

    STZ    0

Program dimulai pada lokasi memori 0 dan kemudian menulis 0 ke lokasi memori 0, sehingga terhapus dengan sendirinya. Mesin berhenti secara otomatis.

Ini adalah bahasa assembly untuk komputer MIX hipotetis Donald Knuth, yang dapat dirakit dan dijalankan menggunakan kit pengembangan MIX GNU ( https://www.gnu.org/software/mdk/ ).

musarithmia
sumber
3

> <> , 40 34 30 byte

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

Coba di sini!

Penjelasan:

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

Pada dasarnya ini menempatkan sekelompok 3 blok karakter dalam tumpukan seperti: (ypos, xpos, karakter ASCII) yang akan dibalik di bagian akhir sehingga perintah 'p' terakhir dibaca (karakter, xpos, ypos) dan menetapkan posisi itu di kode untuk karakter itu. Karakter pertama secara manual ditetapkan sebagai '<', sehingga kode berakhir menjadi '> p <' di akhir untuk mengulangi perintah. Kemudian setiap karakter lain ditimpa sebagai '' termasuk karakter p. The '' sebenarnya "ASCII CHAR 0" yang BUKAN NOP dan akan memberikan kesalahan saat dibaca.

Juga harus ada jumlah karakter ganjil (?) Sebelum perintah 'p' atau tidak akan diulang kembali menjadi yang terakhir dan ditimpa.

torcado
sumber
2

Batch, 11 byte

@echo>%0&&*

Memodifikasi kode sumber menjadi 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.

Ada di @sana sehingga perintah tidak digaungkan, tetapi sebagian besar agar keduanya echotidak berbaris.

ericw31415
sumber
yang @dapat dihapus, karena ECHO(huruf besar) =! echo(huruf kecil)
pppery
@pperry Keduanya echotidak bisa berbaris.
ericw31415
Tapi mereka kasus yang berbeda.
pppery
2

Jolf, 4 byte, tidak bersaing

₯S₯C

Ini memberi ₯Snilai pada ₯Celemen ode ke input, undefinedkarena tidak ada yang diberikan. Coba di sini!

Conor O'Brien
sumber
0

(Filesystem) Befunge 98, 46 byte

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

Perhatikan bahwa program ini membuat dan memanipulasi file bernama a. Bagaimana itu bekerja:

  1. Kode membuat file bernama aberisi seluruh kode (keluar ke 256 karakter di setiap dimensi) bergeser satu ruang ke atas dan dua di sebelah kiri.
  2. Program ini kemudian membaca file bernama asatu baris, menggantikan seluruh baris pertama dengan isi afile.
  3. Baris kedua, yang telah disalin di depan IP, dieksekusi
  4. Yang berbunyi a file ke baris kedua menggeser dua tempat ke kanan.

Sebagai efek samping, kode sumber akhir bahkan tidak valid Befunge! (karena berisi baris baru sebagai data dalam satu baris)

pppery
sumber
0

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

Pada dasarnya, ini mengubah encoding file sumber python saat ini di antara asciidan utf-8, sehingga pada dasarnya mengubah setiap karakter sumber!

Prahlad Yeri
sumber
Ada beberapa ruang ekstra yang bisa dihilangkan. ) as-> )as, ) else-> )else, "utf-8"if, 'w',encoding.
mbomb007