Kendini Sakatlama Programı


16

Basitçe söylemek gerekirse, amacınız, kaynağın her karakteri başladığından farklı olana kadar kendi kaynak kodunu değiştiren eksiksiz bir program oluşturmaktır .

Lütfen yayının yanı sıra bitiş kaynağının yanı sıra bir açıklama da ekleyin. Örn. Programınızın (başka) ne yaptığını, kullandığınız dili, stratejinizi vb. Açıklayın.

kurallar

  • Değişiklik tamamlandıktan sonra programınızın bir süre durması gerekir.
  • Şu anda çalışan kendi kaynak kodunu (yorumlayıcıya ilettiğiniz dosya değil, talimatlarını değiştirir) değiştirmeli, yeni bir program yazdırmamalı veya yeni bir dosya yazmamalıdır.
  • Standart boşluklara izin verilmez.
  • En kısa program kazanır.

  • Diliniz kendi dosyasını değiştirebilir ve yeni bir derleyici işlemi yürütebilir, ancak kendi (şu anda çalışan) kaynak kodunu değiştiremezse, bunun yerine, yuvarlanmış olarak +% 20 baytlık bir ceza ile yazabilirsiniz. Gerçek kendini değiştiren diller bir avantaja sahip olmalıdır.

Düzenleme : Programınız hatalarla durursa, lütfen programı belirtin (ve belki de hataların ne olduğunu söyleyin).


7
Programın, davranışını potansiyel olarak etkileyecek şekilde, çalışırken kendi kaynağını değiştirmesi gerektiğini doğru anladım mı? Bu, ezoterik olmayan dillerin çoğunu dışlar. Veya kaynağı değiştirmesine ve üzerinde yeni bir tercüman / derleyici işlemi başlatmasına izin veriliyor mu?
Zgarb

@Zgarb Aslında, şu anda çalışan kendi kaynak kodunu değiştirmelidir. Evet, bu çoğu dili geçersiz kılar.
mbomb007

8
@ mbomb007 Bu kötü.
mınxomaτ

1
@ mbomb007 Zorunlu hiçbir yerde, değiştirilmiş kaynak kodunu çalıştırması gerektiği söylenmiyor.
7x15

1
Ayrıca, hayır bu meydan okumayı önemsiz yapmaz, yine de iyi bir kapsamda olacaktır. Bununla çok fazla dil çıkardınız.
7x15

Yanıtlar:


19

/// , 1 bayt

/

Program bir /(model değiştirme grubunun başlangıcı) bulur ve değiştirme işlemini hazırlarken onu kaldırır. Sonra EOF'a ulaşır, pes eder ve durur.


1 bayt ile ilk cevap, bu yüzden kazanan.
mbomb007

22

Labirent , 2 bayt

>@

>Kaynak böylece olur döndüğü

@>

Talimat işaretçisi şimdi çıkmazda ve @programı sona erdirmek için dönüyor .

Tabii ki <@de işe yarar.


12

Python 2, 225 bayt

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)

Bitiş kaynak kodu, "0"uzunluğu orijinal derlenmiş kod nesnesindeki bayt sayısına eşit olan bir s dizesidir .

Kod, çalışan kod nesnesini bulur ve sys._getframe().f_code.co_codepython dize nesnelerini temsil eden bir yapı oluşturur. Daha sonra kodun aldığı belleği alır ve onunla değiştirir "0"*len(c).

Çalıştırıldığında, program aşağıdaki izlemeyle çıkar:

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

Bu, üzerine yazma işleminin başarılı olduğunu ve 0geçerli bir opcode olmadığından programın öldüğünü gösterir .

Bunun python'da bile mümkün olduğuna şaşırdım, çerçeve nesneleri salt okunur, yenilerini oluşturamıyorum. Bunun yaptığı tek karmaşık şey değişmez bir nesneyi (dize) değiştirmek.


Bunun HER karakterin farklı olması gereken gereksinimleri karşılayıp karşılamadığından emin değilim. Orijinal kaynak kodundaki "1" yine de karışık koddaki "1" olur ...
Darrel Hoffman

Aslında, "1"koddaki dize aslında 'kodun bir parçası değildir, sadece bayt kodunda atıfta bulunulan bir sabittir. Aslında değiştirdiğim sabit veya değişken değil derlenmiş python sanal makine opcodes olduğunu. Yani değiştirdiğim kaynak kodu değil, sadece derlenmiş kod. Depolandığı gibi kaynak kodunu değiştirebilirdim ama zaten derlenmiş olurdu çünkü aslında çalışma zamanında kodu etkilemez. İsterseniz, bunu 'sabitlenmiş bir Python 2.7 opcodesinde' gönderebilirim, ama bu aptalca IMO olurdu.
Mavi

Ve ayrıca, içinde görmek için değiştirerek, aslında kodu değiştiriyorum, yani aslında kodu görmüyorum çünkü derlenmiş koda bakamıyorum. Gerçekten, kod gerçekten her karakterin yerini alır, hiçbir fikrim yok, sadece en (?) Onları değiştirir
Mavi

Derlenmiş kodda değiştirilmesini değil 1 soruna almak için, değişebilir "1"için <backtick>1+1<backtick>sadece 2 daha byte için
Mego

Gördüğümden değil (2.7.10 ile derlendi). Ne yazık ki, 1+1benim öneriden 2derlenmiş sürümünde bir dönüşür ... Derleyici kendi iyiliği için çok akıllı!
Mego

11

kötü , 1 bayt

q

Kötülüğün birkaç bellek deposu vardır - biri kaynak kodun kendisi ve diğeri tek bir sıfıra başlatılan dairesel bir kuyruk olan tekerlektir . qkaynak kodunu ve tekerleği değiştirir, böylece kaynağı boş bir baytla değiştirir. Ancak, sadece küçük harfler kötülükte gerçek işleçlerdir, böylece karakter basit bir işlem değildir ve program sona erer.


6

MSM , 8 bayt

'.qp.;.;

Kaynak kodunu pqpqpqpq

MSM bir dize listesi üzerinde çalışır. Komutlar soldan alınır ve sağ tarafa yığın olarak davranırlar. MSM her zaman kendi kaynağı üzerinde çalışır.

Yürütme izlemesi:

'.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 veya 2 bayt.

D

Malbolge dili, her talimatı yürüttükten sonra "şifreler", bu nedenle bu harf (Malbolge NOP) bir !(ayrıca bir nop) haline gelir ve sonra sona erer. Bazı nedenlerden dolayı, kullandığım Malbolge yorumlayıcısının çalışması için iki bayt gerekir DC(her ikisi de nop'tur) !U(her ikisi de noptur)

Düzenleme: Malbolge belleğinin başlangıç ​​durumu, koddaki son iki karaktere bağlıdır, bu nedenle bir karakter programı için iyi tanımlanmamıştır. (Bu kod belleğin başlangıç ​​durumunu umursamasa da)


5

x86 asm - 6 bayt

"kaynağın her karakteri başladığı şeyden farklı olana kadar" her bayt, her nemonik veya genel modifikasyonu ifade edip etmediğinden emin değilim. geçersiz olduğumda, her bitin değerlerini değiştirmesi için xor'u değiştirebilirim, ancak bu özel golf dilleriyle en azından biraz karşılaştırılabilir kalmak için 6 bayt kaydetmek için bunu yapmamayı umuyordum.

Bütün bunlar, eip'in canlı adresini alarak ve önünde 5 bayt xoring yaparak bir c2'yi c3 retnine dönüştürmektir.

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 bayt

Golf yapılabilir ve muhtemelen daha sonra üzerinde daha fazla çalışacağım.

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

açıklama

Program, kendisini silmek için bantın sonunda aşağıdaki komutları üretir, bu nedenle bantta aşağıdaki değerleri oluşturmak zorundadır:

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

Geçici değerler için kullanmak üzere 91null değeri (olarak gösterilir _) olacak şekilde bir demet s yapın .

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

code__91_91_91_91_91_91_
   ^

Değerleri farklılıklara göre ayarlayın

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

Yürütülmeyi izleyen bant, oluşturulan kod hariç tümü sıfır olacaktır [_[_-_]_<_].

Not:

Bu program, SMBF için Python yorumcumun bir veya iki hata olduğunu fark etmemi sağladı ve henüz bir çözüm bulamadım . Şimdi düzeltildi.


4

Emacs Lisp 22 bayt

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

REPL'den çalıştır:

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)

Fonksiyon şimdi olarak değerlendirilir nil.

Alternatif olarak (kendi kendine) 30 bayt

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

Değerlendirin ve hataları olarak void-function. İşlev çalıştırılmadan önce vardı.


4

Redcode , 7 bayt, 1 talimat (Sadece bir örnek. Rekabet etmiyor )

Bu önemsiz bir örnek.

Bir sonraki bellek konumunu kendi üzerine taşır, ardından durur (çünkü belleğin tamamı başlatıldığından DAT 0 0, yürütüldüğünde programı durdurur.)

MOV 1 0

2
Bunu neden bayt yerine talimat olarak sayıyorsunuz?
Martin Ender

Çünkü kaç bayt olduğunu bilmiyorum. Sanırım bu bellek boyutuna veya uygulamaya bağlı mı? ...
mbomb007

4
Nasıl uygulandığını bilmiyorsanız ASCII karakterlerine göre sayılırdım.
lirtosiast

1
Wikipedia sayfasından: Her Redcode talimatı tam olarak bir bellek yuvası kaplar ve yürütülmesi tam olarak bir döngü sürer. ... Bellek bir komutun birimlerinde adreslenir.
mbomb007

3
Tüm kod-golf direkleri bayt olarak puanlanır. Redcode makine kodu olmadığından, "birleştirme kaynağı" ndaki karakterleri kullanmalıyız, birleştirdikleri şeyi kullanmamalıyız.
lirtosiast

3

Powershell 65 bayt

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

Kendini null değerine yeniden yazan bir işlev tanımlayın.

Bir kez değerlendirin ve kendini yok eder.

Alternatif olarak (kendini bellekten siler) 36 bayt

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

Önce onu çağırır, ardından yinelemeli olarak değerlendirmeye çalışır. Bilinmeyen bir komut olarak hata veriyor.


3

MIXAL, 6 bayt (2 sekme sayma)

    STZ    0

Program, bellek yeri 0'dan başlar ve sonra bellek yeri 0'a 0 yazar, böylece kendini siler. Makine otomatik olarak durur.

Bu, Donald Knuth'un varsayımsal MIX bilgisayarının montaj dilidir ve GNU MIX geliştirme kiti ( https://www.gnu.org/software/mdk/ ) kullanılarak monte edilebilir ve çalıştırılabilir .


3

> <> , 40 34 30 bayt

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

Burada deneyin!

Açıklama:

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

Temel olarak bu, yığına şu şekilde 3 karakter bloğunu koyar: (ypos, xpos, ASCII karakteri) sonunda tersine döner, böylece son 'p' komutu okunur (karakter, xpos, ypos) ve bu karakteri kodlayın. İlk karakter manuel olarak '<' olarak ayarlanır, böylece kod, komutu döngüye sokmak için sonunda '> p <' olur. Sonra diğer tüm karakterlerin üzerine p karakteri dahil bir '' olarak yazılır. '' Aslında "ASCII CHAR 0" dır ve bu bir NOP DEĞİLDİR ve okunduğunda bir hata verecektir.

Ayrıca, 'p' komutundan önce tek (?) Sayıda karakter olması gerekir, aksi takdirde son kez geri döndürülmez ve üzerine yazılmaz.


2

Toplu, 11 bayt

@echo>%0&&*

Kaynak kodunu olarak değiştirir 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.

@Orada çok komutu yankılandı değil mi, ama çoğunlukla bu yüzden iki echos sıraya yoktur.


@çünkü, çıkarılabilir ECHO! (büyük harf) = echo(küçük)
pppery

@ppperry İkisi sıraya giremez echo.
ericw31415

Ama bunlar farklı vakalar.
pppery


0

(Dosya Sistemi) Befunge 98, 46 bayt

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

Bu programın adında bir dosya oluşturduğunu ve değiştirdiğini unutmayın a . Nasıl çalışır:

  1. Kod a, tüm kodu içeren bir dosya oluşturur (her boyutta 256 karaktere kadar) bir boşluk yukarı ve iki sola kaydırılmıştır.
  2. Bu program daha sonra adlı dosyayı okur a bir satır olarak ilk satırın tamamını adosyanın içeriğiyle değiştirir .
  3. IP'nin önüne kopyalanan ikinci satır yürütülür
  4. Hangi adosyayı ikinci satıra okurken iki yer sağa kaydırdı.

Bir yan etki olarak, bitiş kaynak kodu bile geçerli değil Befunge! (çünkü tek satırda veri olarak yeni satırlar içerir)


0

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

Temel olarak, bu, python kaynağının geçerli dosya kodlamasını ve arasında değiştirir asciive utf-8böylece kaynağın her karakterini değiştirir!


Kaldırılabilecek fazladan boşluklar var. ) as-> )as, ) else-> )else, "utf-8"if, 'w',encoding.
mbomb007
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.