โปรแกรมทำลายตนเอง


16

เป้าหมายของคุณคือการสร้างโปรแกรมที่สมบูรณ์ซึ่งปรับเปลี่ยนซอร์สโค้ดของตัวเองจนกระทั่งตัวละครทุกตัวของซอร์สโค้ดนั้นแตกต่างจากที่มันเริ่ม

โปรดระบุแหล่งที่มาเริ่มต้นและแหล่งที่สิ้นสุดในโพสต์ของคุณรวมถึงคำอธิบาย เช่นอธิบายว่าโปรแกรมของคุณทำอะไร (ภาษาอื่น) ภาษาที่คุณใช้กลยุทธ์ของคุณเป็นต้น

กฎระเบียบ

  • โปรแกรมของคุณต้องหยุดบางครั้งหลังจากการปรับเปลี่ยนเสร็จสมบูรณ์
  • จริง ๆ แล้วจะต้องแก้ไขของตัวเองกำลังเรียกใช้ซอร์สโค้ด (ไม่จำเป็นต้องเป็นไฟล์ที่คุณส่งไปยังล่ามก็แก้ไขคำแนะนำ) ไม่พิมพ์โปรแกรมใหม่หรือเขียนไฟล์ใหม่
  • ช่องโหว่มาตรฐานไม่ได้รับอนุญาต
  • โปรแกรมที่สั้นที่สุดชนะ

  • หากภาษาของคุณสามารถแก้ไขไฟล์ของตัวเองและดำเนินการกระบวนการคอมไพเลอร์ใหม่ แต่ไม่สามารถแก้ไขซอร์สโค้ดของตัวเอง (ที่กำลังทำงานอยู่) คุณสามารถเขียนโปรแกรมดังกล่าวแทนได้ที่การลงโทษ + 20% ไบต์ปัดเศษขึ้น ภาษาที่แก้ไขตัวเองได้จริงควรพิจารณาเป็นพิเศษ

แก้ไข : หากโปรแกรมของคุณหยุดทำงานกับข้อผิดพลาดโปรดระบุว่าเป็นเช่นนั้น (และอาจพูดว่าข้อผิดพลาดคืออะไร)


7
ฉันเข้าใจอย่างถูกต้องหรือไม่ว่าโปรแกรมควรปรับเปลี่ยนแหล่งที่มาของตัวเองในขณะที่กำลังทำงานในลักษณะที่อาจมีผลต่อพฤติกรรมของโปรแกรมหรือไม่ สิ่งนี้จะแยกแยะภาษาที่ไม่ใช่ความลับส่วนใหญ่ หรืออนุญาตให้แก้ไขแหล่งที่มาและเปิดตัวกระบวนการล่าม / ผู้แปลใหม่ได้หรือไม่
Zgarb

@Zgarb จริง ๆ แล้วมันจะต้องแก้ไขของตัวเองในขณะนี้กำลังเรียกใช้รหัสที่มา ใช่ว่าจะออกกฎส่วนใหญ่ภาษา
mbomb007

8
@ mbomb007 แย่จัง
mınxomaτ

1
@ mbomb007 มันบอกว่าไม่มีที่ใดในคุณที่ท้าทายว่าจะต้องเรียกใช้ซอร์สโค้ดที่แก้ไขแล้ว
mınxomaτ

1
นอกจากนี้มันไม่ได้ทำให้ความท้าทายนี้เล็กน้อยมันจะยังคงขอบเขตที่ดี คุณใช้ภาษานี้มากเกินไป
mınxomaτ

คำตอบ:


19

/// , 1 ไบต์

/

โปรแกรมค้นหากลุ่ม/(จุดเริ่มต้นของกลุ่มการแทนที่รูปแบบ) และลบกลุ่มเพื่อเตรียมการแทนที่ จากนั้นก็ถึง EOF ดังนั้นจึงเลิกและหยุด


คำตอบที่เร็วที่สุดคือ 1 ไบต์ดังนั้นมันจึงเป็นผู้ชนะ
mbomb007

22

เขาวงกต 2 ไบต์

>@

>หมุนแหล่งที่มาเพื่อที่ว่ามันจะกลายเป็น

@>

ตัวชี้คำสั่งอยู่ในขั้นตอนสุดท้ายและจะหมุนไปรอบ ๆ เพื่อให้@โปรแกรมหยุดทำงาน

แน่นอนว่า<@ยังใช้งานได้


12

Python 2, 225 ไบต์

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)

ซอร์สโค้ดสิ้นสุดคือสตริง"0"ที่มีความยาวเท่ากับจำนวนไบต์ในออบเจ็กต์รหัสต้นฉบับที่รวบรวม

รหัสค้นหาวัตถุรหัสกำลังทำงานsys._getframe().f_code.co_codeและสร้างโครงสร้างที่แสดงถึงวัตถุสตริงของหลาม "0"*len(c)จากนั้นจะได้รับหน่วยความจำที่รหัสจริงใช้เวลาและแทนที่มันด้วย

เมื่อรันแล้วโปรแกรมจะออกจากการติดตามย้อนกลับต่อไปนี้:

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

สิ่งนี้แสดงให้เห็นว่าการเขียนทับสำเร็จและโปรแกรมนั้นตายเพราะ0ไม่มีรหัสที่ถูกต้อง

ฉันประหลาดใจว่านี่เป็นไปได้ในงูหลามวัตถุเฟรมเป็นแบบอ่านอย่างเดียวฉันไม่สามารถสร้างสิ่งใหม่ได้ สิ่งที่ซับซ้อนเพียงอย่างเดียวก็คือการเปลี่ยนวัตถุที่ไม่เปลี่ยนรูป (สตริง)


ไม่แน่ใจว่าสิ่งนี้ค่อนข้างตรงตามข้อกำหนดหรือไม่ว่าอักขระทุกตัวต้องแตกต่างกัน "1" ในซอร์สโค้ดต้นฉบับจะยังคงเป็น "1" ในโค้ดที่ยุ่งเหยิง ...
Darrel Hoffman

ในความเป็นจริง"1"สตริงในโค้ดไม่ได้เป็นส่วนหนึ่งของ 'code' แต่เป็นค่าคงที่ที่ถูกอ้างถึงในไบต์ สิ่งที่ฉันกำลังเปลี่ยนแปลงจริง ๆ ก็คือเครื่องเสมือนของไพ ธ อนที่รวบรวมไว้ไม่ใช่ค่าคงที่หรือตัวแปร ดังนั้นสิ่งที่ฉันเปลี่ยนไม่ใช่ซอร์สโค้ดต่อคำพูดเพียงแค่รวบรวมรหัส ฉันสามารถเปลี่ยนซอร์สโค้ดเป็นที่จัดเก็บได้ แต่นั่นจะไม่ส่งผลกระทบต่อรหัสเมื่อใช้งานจริงเพราะมันจะถูกคอมไพล์แล้ว หากคุณต้องการฉันสามารถโพสต์สิ่งนี้ใน 'คอมไพล์ Python 2.7 ที่คอมไพล์ด้วยค่าคงที่' แต่นั่นอาจเป็น IMO ที่ไร้สาระ
Blue

และฉันก็ไม่สามารถดูโค้ดที่คอมไพล์ได้เพราะการเปลี่ยนให้ดูภายในฉันกำลังเปลี่ยนโค้ดจริง ๆ แล้วหมายความว่าฉันไม่เห็นโค้ดจริงๆ ดังนั้นฉันไม่รู้เลยว่ารหัสจะมาแทนที่ตัวละครทุกตัวจริงๆหรือเปล่าเพราะมันเปลี่ยนไปมากที่สุด (?) ของพวกเขา
Blue

จะได้รับการแก้ไขปัญหาของ 1 ไม่ได้มีการเปลี่ยนแปลงในรหัสเรียบเรียงคุณสามารถเปลี่ยน"1"ไป<backtick>1+1<backtick>ไบต์เท่านั้นอีก 2
ชำเลืองไปที่

ไม่ใช่ที่ฉันเห็น (คอมไพล์ด้วย 2.7.10) น่าเสียดายที่1+1จากคำแนะนำของฉันกลายเป็น2เวอร์ชั่นคอมไพล์แล้ว ... คอมไพเลอร์ฉลาดเกินไปสำหรับตัวของมันเอง!
Mego

11

ชั่ว 1 ไบต์

q

ความชั่วร้ายมีร้านค้าหน่วยความจำหลายแห่ง - หนึ่งคือซอร์สโค้ดตัวเองและหนึ่งคือล้อซึ่งเป็นคิววงกลมซึ่งเริ่มต้นที่ศูนย์เดียว qสลับซอร์สโค้ดและวงล้อดังนั้นจึงแทนที่ซอร์สด้วย null-byte อย่างไรก็ตามตัวอักษรตัวพิมพ์เล็กเท่านั้นเป็นตัวดำเนินการจริงในความชั่วร้ายดังนั้นอักขระนั้นจึงเป็นแบบไม่ใช้งานและโปรแกรมจะหยุดทำงาน


6

MSM , 8 ไบต์

'.qp.;.;

แปลงซอร์สโค้ดเป็น pqpqpqpq

MSM ทำงานในรายการสตริง คำสั่งถูกนำมาจากด้านซ้ายและพวกเขาปฏิบัติต่อด้านขวาเป็นกองซ้อน ชายรักชายมักจะทำงานในแหล่งของตัวเอง

การดำเนินการติดตาม:

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

6

Malbolge, 1 หรือ 2 ไบต์

D

ภาษา Malbolge "เข้ารหัส" แต่ละคำสั่งหลังจากเรียกใช้งานดังนั้นจดหมายฉบับนี้ (Malbolge NOP) จะกลายเป็น!(ซึ่งเป็น nop ด้วย) แล้วจึงยุติ ด้วยเหตุผลบางอย่าง Malbolge interpreter ที่ฉันใช้ต้องใช้สองไบต์ในการเรียกใช้โดยให้DC(ทั้งสองอย่างเป็น nops) กลายเป็น!U(ทั้งสองอย่างนั้นยังเป็น nops ด้วย)

แก้ไข: สถานะเริ่มต้นของหน่วยความจำ Malbolge ขึ้นอยู่กับอักขระสองตัวสุดท้ายในรหัสดังนั้นจึงไม่ได้กำหนดไว้อย่างดีสำหรับโปรแกรมอักขระหนึ่งตัว (แม้ว่ารหัสนี้จะไม่สนใจสถานะเริ่มต้นของหน่วยความจำ)


5

x86 asm - 6 ไบต์

ไม่แน่ใจว่า "จนกว่าตัวละครของแหล่งที่มาทุกตัวจะแตกต่างจากที่เริ่ม" อ้างอิงถึงแต่ละไบต์, แต่ละ nemonic หรือการปรับเปลี่ยนทั่วไป ถ้าฉันไม่ถูกต้องฉันสามารถเปลี่ยน xor เป็น rep xor ดังนั้นแต่ละบิตจะเปลี่ยนค่า แต่หวังว่าจะไม่ทำเช่นนั้นเพื่อประหยัดอีก 6 ไบต์เพื่อให้อยู่อย่างน้อยนิดหน่อยเทียบได้กับภาษากอล์ฟพิเศษเหล่านี้

ทั้งหมดนี้จะเปลี่ยน c2 เป็น c3 retn โดยรับที่อยู่สดของ eip และ xoring 5 ไบต์ด้านหน้า

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

5

SMBFขนาด 92 ไบต์

สามารถเล่นกอล์ฟได้และฉันจะทำงานให้มากขึ้นในภายหลัง

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

คำอธิบาย

โปรแกรมสร้างคำสั่งต่อไปนี้ที่ส่วนท้ายของเทปเพื่อลบตัวเองดังนั้นจึงต้องสร้างค่าต่อไปนี้บนเทป:

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

ทำพวงกับ91s, nulls (แสดงเป็น_) ระหว่างเพื่อใช้สำหรับค่าอุณหภูมิ

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

code__91_91_91_91_91_91_
   ^

ปรับค่าตามความแตกต่าง

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

[_[_-_]_<_]การดำเนินเทปต่อไปนี้จะเป็นศูนย์ทั้งหมดมีข้อยกเว้นของรหัสที่สร้างขึ้น

บันทึก:

โปรแกรมนี้ทำให้ฉันรู้ว่า Python interpreter สำหรับ SMBF ของฉันมีข้อผิดพลาดหรือสองและฉันยังไม่ได้หาวิธีแก้ไข ตอนนี้ได้รับการแก้ไขแล้ว


4

Emacs Lisp 22 ไบต์

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

เรียกใช้จาก 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)

ฟังก์ชันประเมินค่าเป็น nilฟังก์ชั่นในขณะนี้ประเมิน

อีกวิธีหนึ่ง (ยกเลิกการผูกมัด) 30 ไบต์

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

void-functionการประเมินและข้อผิดพลาดเป็น มีฟังก์ชันอยู่ก่อนที่จะถูกเรียกใช้


4

Redcode , 7 ไบต์, 1 คำสั่ง (เป็นเพียงตัวอย่างเท่านั้นไม่ใช่การแข่งขัน)

นี่เป็นตัวอย่างเล็กน้อย

ย้ายตำแหน่งหน่วยความจำถัดไปไปยังตัวเองแล้วหยุด (เนื่องจากหน่วยความจำทั้งหมดถูกเตรียมใช้งานเพื่อDAT 0 0หยุดโปรแกรมเมื่อดำเนินการ)

MOV 1 0

2
ทำไมคุณนับสิ่งนี้เป็นคำแนะนำแทนที่จะเป็นไบต์?
Martin Ender

เพราะฉันไม่รู้ว่ามันมีกี่ไบท์ ฉันคิดว่ามันขึ้นอยู่กับขนาดของหน่วยความจำหรือการติดตั้งใช้งานหรือไม่ ...
mbomb007

4
ฉันจะนับตามตัวอักษร ASCII ถ้าคุณไม่รู้ว่ามันใช้งานอย่างไร
lirtosiast

1
จากหน้า Wikipedia: คำสั่ง Redcode แต่ละคำสั่งมีช่องเสียบหน่วยความจำหนึ่งช่องและใช้เวลาหนึ่งรอบในการดำเนินการ ... หน่วยความจำได้รับการแก้ไขในหน่วยของคำสั่งเดียว
mbomb007

3
ทั้งหมดรหัสกอล์ฟโพสต์คะแนนในไบต์ เนื่องจากไม่มีรหัสเครื่อง Redcode เราต้องใช้อักขระใน "แหล่งที่มาของการประกอบ" ไม่ใช่สิ่งที่มันประกอบ
lirtosiast

3

Powershell 65 ไบต์

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

กำหนดฟังก์ชั่นที่เขียนตัวเองเป็นโมฆะ

ประเมินมันหนึ่งครั้งและกำจัดมันเอง

อีกทางหนึ่ง (ลบตัวเองออกจากหน่วยความจำ) 36 ไบต์

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

การเรียกมันก่อนจะลบออกจากนั้นพยายามประเมินแบบเรียกซ้ำ การผิดพลาดเป็นคำสั่งที่ไม่รู้จัก


3

MIXAL, 6 ไบต์ (นับ 2 แท็บ)

    STZ    0

โปรแกรมเริ่มต้นที่ตำแหน่งหน่วยความจำ 0 จากนั้นเขียน 0 ไปยังตำแหน่งหน่วยความจำ 0 จึงทำการลบตัวเอง เครื่องหยุดโดยอัตโนมัติ

นี่เป็นภาษาแอสเซมบลีสำหรับคอมพิวเตอร์ MIX ของสมมุติฐานของ Donald Knuth ซึ่งอาจประกอบและเรียกใช้โดยใช้ชุดพัฒนา GNU MIX ( https://www.gnu.org/software/mdk/ )


3

> <> , 40 34 30 ไบต์

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

ลองที่นี่!

คำอธิบาย:

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

โดยพื้นฐานแล้วสิ่งนี้จะวางบล็อกจำนวน 3 บล็อกไว้ในสแต็กดังนี้: (ypos, xpos, ASCII อักขระ) ซึ่งได้รับการย้อนกลับในตอนท้ายดังนั้นคำสั่ง 'p' สุดท้ายจะอ่าน (ตัวอักษร, xpos, ypos) และกำหนดตำแหน่งนั้นใน รหัสกับตัวละครนั้น อักขระตัวแรกถูกตั้งค่าด้วยตนเองเป็น '<' เพื่อให้รหัสจบลงด้วยการเป็น '> p <' ในตอนท้ายเพื่อวนคำสั่ง จากนั้นอักขระอื่น ๆ ทั้งหมดจะถูกเขียนทับเป็น '' รวมถึงอักขระ p '' เป็นจริง "ASCII CHAR 0" ซึ่งไม่ใช่ NOP และจะให้ข้อผิดพลาดเมื่ออ่าน

นอกจากนี้จะต้องมีจำนวนอักขระแปลก (?) ก่อนคำสั่ง 'p' มิฉะนั้นจะไม่ถูกวนซ้ำในครั้งสุดท้ายและเขียนทับ


2

แบตช์ 11 ไบต์

@echo>%0&&*

แก้ไขซอร์สโค้ดเป็น 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.

ที่@นั่นมีคำสั่งไม่ได้สะท้อน แต่ส่วนใหญ่ดังนั้นทั้งสองechoไม่เข้าแถว


@สามารถลบออกได้เพราะECHO(ตัวพิมพ์ใหญ่) =! echo(ตัวพิมพ์เล็ก)
pppery

@ppperry ทั้งสองechoไม่สามารถเข้าแถวได้
ericw31415

แต่พวกมันต่างกัน
pppery


0

(ระบบไฟล์) Befunge 98, 46 bytes

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

aโปรดทราบว่าโปรแกรมนี้จะสร้างและปรุงแต่งไฟล์ชื่อ มันทำงานอย่างไร:

  1. รหัสจะสร้างไฟล์ชื่อaที่มีรหัสทั้งหมด (ไม่เกิน 256 อักขระในแต่ละมิติ) เลื่อนหนึ่งช่องว่างขึ้นและอีกสองช่องทางซ้าย
  2. จากนั้นโปรแกรมนี้อ่านไฟล์ที่ชื่อaเป็นหนึ่งบรรทัดแทนที่ทั้งบรรทัดแรกด้วยเนื้อหาของaไฟล์
  3. บรรทัดที่สองซึ่งถูกคัดลอกด้านหน้า IP จะถูกดำเนินการ
  4. ซึ่งการอ่านaไฟล์ลงในบรรทัดที่สองได้เลื่อนตำแหน่งไปทางขวาสองตำแหน่ง

ในฐานะที่เป็นผลข้างเคียงซอร์สโค้ดสิ้นสุดยังไม่ถูกต้องแม้แต่ Befunge! (เนื่องจากมีบรรทัดใหม่เป็นข้อมูลในบรรทัดเดียว)


0

Python 2, 238 ไบต์ + 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"):])

โดยพื้นฐานแล้วสิ่งนี้จะสลับการเข้ารหัสไฟล์ปัจจุบันของแหล่งไพ ธ อนระหว่างasciiและutf-8ดังนั้นการเปลี่ยนแปลงตัวละครทุกตัวของแหล่งที่มา!


มีช่องว่างเพิ่มเติมบางส่วนที่สามารถลบออกได้ ) as-> )as, ->) else , , )else"utf-8"if'w',encoding
mbomb007
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.