Tulis program yang mereplikasi diri.


11

Tulis program sederhana yang menyalin dirinya sendiri ketika dieksekusi.

Program Anda harus berupa file yang dapat dieksekusi pada Windows, Linux, dll., Harus menghasilkan file yang dapat dieksekusi baru, yang identik dengan file yang dapat dieksekusi asli Anda, dengan nama acak, dan berhenti.

Program Anda seharusnya tidak melibatkan segala jenis membaca file atau menyalin. Hanya penulisan file untuk menghasilkan file yang dapat dieksekusi baru yang diizinkan.

(PS. Saya cukup malu ketika di Wikipedia, Self-replicating programmengalihkan ke Computer virusartikel ...: / ...)

Ukuran file terkecil yang dapat dieksekusi akan menang. Jawaban Anda mungkin berupa kode pemrograman dengan OS & compiler, kode assembly, atau dump HEX yang tepat dari file yang dapat dieksekusi.


6
Ini tampaknya hanya berbeda sepele dari tantangan [quine] yang ada. Atau apakah saya salah paham?
dmckee --- ex-moderator kitten

1
@ dmckee Saya melihat Assembly Language Quine dan Hello Hello yang mereplikasi diri sendiri menerima program penyalinan, tapi saya tidak bisa menemukan program menulis sendiri , bukan kodenya .
JiminP

1
... tapi saya ingin melihat bagaimana cara kerjanya! .. Saya tidak tahu bagaimana ide dapat diperpanjang dengan kode biner .. meskipun saya membaca artikel Quine di Wikipedia. PS. tidak ada kompiler untuk direplikasi dan tidak ada bahasa skrip yang diizinkan ...: /
JiminP

4
Masalah apa pun dapat dibuat sedikit lebih sulit dan lebih buruk dengan menambahkan lebih banyak kendala untuk itu. Saya menemukan masalah ini perpanjangan sepele dari masalah quine.
Alexandru

1
Jika ukuran terkecil yang dapat dieksekusi menang, bukankah kita juga memperhitungkan kode juru bahasa sebagai bagian dari ukuran yang dapat dieksekusi agar ini adil bagi pengguna bahasa yang dikompilasi?
Thomas Dignan

Jawaban:


4

Bash, 236

Lebih lama dari yang seharusnya, tapi aku benci antrean panjang. Baris tambahan tidak bersifat opsional.

b=\\ q=\' r=\> d=\$
s='exec >$$; echo b=$b$b q=$b$q r=$b$r d=$b$d; echo s=$q$s$q'
t='echo t=$q$t$q; echo $s; echo $t; chmod 777 $$'
exec >$$; echo b=$b$b q=$b$q r=$b$r d=$b$d; echo s=$q$s$q
echo t=$q$t$q; echo $s; echo $t; chmod 777 $$

Sebenarnya, bukan itu yang saya inginkan, karena saya menulis pertanyaan yang "salah" dan jawaban Anda adalah jawaban yang bagus ...
JiminP

@ JiminP: Bagaimana bukan apa yang Anda inginkan? Saya baru saja membaca deskripsi masalah dua kali lagi, dan gagal memahami.
JB

Yah ... yang saya inginkan adalah kode biner yang dapat dieksekusi. Seperti yang saya akui di atas, karena pertanyaan saya tidak terlalu 'benar' ... maaf untuk itu.
JiminP

3
@ JiminP Yah, ya, kata "biner" tidak muncul sama sekali dalam pertanyaan. Saya baru saja menemukannya di komentar, tetapi untuk pembatasan seperti itu, itu tidak memotongnya. Anda dapat membuka pertanyaan baru dengan semua input yang terkonsolidasi dari komentar. Saya sarankan Anda menggunakan kotak pasir untuk memastikan pelanggan tetap membantu Anda menyelesaikan detail kecil. Namun berhati-hatilah, jawaban biner cenderung membosankan.
JB

10

Perakitan untuk x86 Linux, 106 byte

BITS 32
                org     0x2E620000
                db      0x7F, "ELF", 1, 1, 1, 0 ; e_ident
                dd      0, 0
                dw      2                       ; e_type
                dw      3                       ; e_machine
                dd      1                       ; e_version
                dd      _start                  ; e_entry
                dd      phdr - $$               ; e_phoff
                dd      0                       ; e_shoff
                dd      0                       ; e_flags
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
phdr:           dd      1                       ; e_phnum       ; p_type
                                                ; e_shentsize
                dd      0                       ; e_shnum       ; p_offset
                                                ; e_shstrndx
                dd      $$                                      ; p_vaddr
fname           equ     $ - 2
                db      'out', 0                                ; p_paddr
                dd      filesize                                ; p_filesz
                dd      filesize                                ; p_memsz
                dd      5                                       ; p_flags
                dd      0x1000                                  ; p_align
_start:         mov     al, 5                   ; 5 = open syscall
                mov     ebx, fname
                mov     cl, 65                  ; 65 = O_WRONLY | O_CREAT
                mov     dx, 666q
                int     0x80
                lea     edx, [byte ecx + filesize - 65]
                xchg    eax, ebx
                xchg    eax, ecx
                mov     cl, 0
                mov     al, 4                   ; 4 = write syscall
                int     0x80
                mov     al, 1                   ; 1 = exit syscall
                int     0x80
filesize        equ     $ - $$

Ini untuk assembler nasm. Bangun biner dengan baris perintah:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Berikut file yang sama dengan hex dump: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 4C 00 62 2E 2C 00 00 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 00 62 2E 6F 75 74 00 6A 00 00 00 6A 00 00 00 05 00 00 00 00 10 00 00 B0 05 BB 36 00 62 2E B1 41 66 BA B6 01 CD 80 8D 51 29 93 91 B1 00 B0 04 CD 80 B0 01 CD 80

Seperti yang diminta, program menyalin dirinya ke file terpisah. (Program bisa saja jauh lebih singkat jika diizinkan untuk hanya menulis ke stdout dan membiarkan pengguna mengarahkan ulang ke file.)

Saya menghindari menggunakan trik batas untuk mengurangi ukuran. Ini harus sepenuhnya biner ELF 32-bit.

Diedit untuk menambahkan : Dalam versi di atas file yang dibuat hanyalah file biasa, tetapi terpikir oleh saya bahwa untuk beberapa byte (dan sedikit tikungan aturan), Anda dapat membuat sesuatu yang sedikit lebih menarik. Versi ini hanya dua byte lebih panjang, pada 108 byte:

BITS 32
                org     0x00010000
                db      0x7F, "ELF", 1, 1, 1, 0 ; e_ident
                dd      0, 0
                dw      2                       ; e_type
                dw      3                       ; e_machine
                dd      1                       ; e_version
                dd      _start                  ; e_entry
                dd      phdr - $$               ; e_phoff
                dd      0                       ; e_shoff
                dd      0                       ; e_flags
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
phdr:           dd      1                       ; e_phnum       ; p_type
                                                ; e_shentsize
                dd      0                       ; e_shnum       ; p_offset
                                                ; e_shstrndx
                dd      $$                                      ; p_vaddr
fname:          db      'asr', 0                                ; p_paddr
                dd      filesize                                ; p_filesz
                dd      filesize                                ; p_memsz
                dd      7                                       ; p_flags
                dd      0x1000                                  ; p_align
_start:         mov     al, 5                   ; 5 = open syscall
                mov     ebx, fname
                inc     byte [ebx]
                mov     cl, 65                  ; 65 = O_WRONLY | O_CREAT
                mov     dx, 777q
                int     0x80
                lea     edx, [byte ecx + filesize - 65]
                xchg    eax, ebx
                xchg    eax, ecx
                mov     cl, 0
                mov     al, 4                   ; 4 = write syscall
                int     0x80
                mov     al, 1                   ; 1 = exit syscall
                int     0x80
filesize        equ     $ - $$

Beri nama versi ini asr, untuk "replikator diri":nasm -f bin -o asr asr.asm && chmod +x asr

Versi hex dump untuk orang yang mengalami gangguan nafas: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 4C 00 01 00 2C 00 00 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 00 01 00 61 73 72 00 6C 00 00 00 6C 00 00 00 07 00 00 00 00 10 00 00 B0 05 BB 38 00 01 00 FE 03 B1 41 66 BA FF 01 CD 80 8D 51 2B 93 91 B1 00 B0 04 CD 80 B0 01 CD 80

Ketika Anda menjalankannya, itu menciptakan file yang hampir identik bernama bsr, tetapi itu sendiri dapat dieksekusi. Menjalankannya akan membuat file biner lain bernama csr. Dan seterusnya.

(Perhatikan bahwa hal-hal menjengkelkan mulai terjadi setelah itu zsr. Saya mempertimbangkan untuk membuat versi yang akan mengubah nama perubahan atrdan sebagainya, tapi saya pikir kebanyakan orang akan bosan dengan baik sebelum itu, jadi mungkin tidak semua byte ekstra bernilai. )


+1 untuk jawaban perakitan! Pernahkah Anda melihat tantangan quine perakitan ?
MD XF

2

Berikut ini adalah bukti konsep (ungolfed) yang menunjukkan bagaimana layanan Kompilasi di .NET dapat digunakan untuk mengkompilasi kode sumber saat itu juga untuk menghasilkan output yang identik. Salinan pertama tidak identik dengan aslinya, tetapi salinan selanjutnya dari proses berikutnya persis sama dengan nama file acak:

using System;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace _2947
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello world!");

            var s = @"
using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace _2947
{{
    class Program
    {{
        static void Main(string[] args)
        {{
            Console.WriteLine({1}Hello world!{1});

            var s = @{1}{0}{1};
            s = string.Format(s, s, '{1}');

            string exeName = Environment.CurrentDirectory + @{1}\{1} + new Random().Next(1000, 9999) + {1}.exe{1};

            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = true;
            cp.OutputAssembly = exeName;
            cp.GenerateInMemory = false;
            cp.TreatWarningsAsErrors = false;
            cp.ReferencedAssemblies.Add({1}System.dll{1});

            var c = CSharpCodeProvider.CreateProvider({1}cs{1});
            var cr = c.CompileAssemblyFromSource(cp, s);
        }}
    }}
}}
";
            s = string.Format(s, s, '"');

            string exeName = Environment.CurrentDirectory + @"\" + new Random().Next(1000, 9999) + ".exe";

            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = true;
            cp.OutputAssembly = exeName;
            cp.GenerateInMemory = false;
            cp.TreatWarningsAsErrors = false;
            cp.ReferencedAssemblies.Add("System.dll");

            var c = CSharpCodeProvider.CreateProvider("cs");
            var cr = c.CompileAssemblyFromSource(cp, s);
        }
    }
}

Output demonstrasi pada baris perintah:

C:\projects\codegolf\2947\2947\bin\Debug>2947
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 8425.exe
               4 File(s)         39,760 bytes
               2 Dir(s)   6,486,368,256 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>8425
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 7538.exe
09/27/2011  02:17 PM             6,656 8425.exe
               5 File(s)         46,416 bytes
               2 Dir(s)   6,486,360,064 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>7538
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 4127.exe
09/27/2011  02:17 PM             6,656 7538.exe
09/27/2011  02:17 PM             6,656 8425.exe
               6 File(s)         53,072 bytes
               2 Dir(s)   6,486,351,872 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>

2

Batch

Versi 1 (30 byte)

type%0>%random%.bat&type%0>con

Saya menang! :)


referensi% 0 menyebabkan pembacaan dari file, yang melanggar aturan. Selain itu, versi biner saya bahkan lebih pendek. :-)
peter ferrie

1

File DOS COM - 50 byte

Menciptakan file X.COMmana Xdiganti dengan yang digit dari waktu saat ini. File COM hanya dimuat ke dalam memori pada offset 100hsegmen data (CS dan DS diatur agar sama) sehingga kita dapat menuliskan memori ini ke sebuah file.

0000000: b402 cd1a 80e6 0f80 ce30 8836 2c01 31c9  .........0.6,.1.
0000010: ba2c 01b4 3ccd 21c6 062c 0178 89c3 b440  .,..<.!..,.x...@
0000020: ba00 01b9 3200 cd21 b44c cd21 782e 636f  ....2..!.L.!x.co
0000030: 6d00                                     m.

sumber nasm

org 100h ; this is a COM file
mov ah,02h ; fn=get time
int 1ah ; rtc interrupt
; convert to ascii - dh gets ones digit of seconds
and dh,0fh
or dh,30h
mov [fname],dh ; move time into filename
xor cx,cx ; clear attributes
mov dx,fname ; load filename
mov ah,3ch ; fn=create file
int 21h ; dos interrupt
mov byte [fname],'x' ; reset filename
mov bx,ax ; set filehandle
mov ah,40h ; fn=write to file
mov dx,100h ; offset is the loaded binary
mov cx,len ; length of write
int 21h ; dos iterrupt
mov ah,4ch ; fn=exit
int 21h ; dos interrupt
fname: db 'x.com',0
len equ $-$$

1

File DOS .COM, 29 byte

'@' Diganti secara acak dengan huruf aneh di bagian pertama + bagian alfabet (A, C, E, G, dll). File output adalah 255 atau 256 byte. Register awal dalam DOS nyata (sebagai lawan debugger) adalah AX = 0000, CX = 00FF, SI = 0100.

40       INC  AX         ;"@"
2E       CS:             ;"."
43       INC  BX         ;"C"
4F       DEC  DI         ;"O"
4D       DEC  BP         ;"M"
00 20    ADD  [BX+SI],AH ;"\0" and dummy parm
E4 40    IN   AL,40
24 0F    AND  AL,0F
0C 41    OR   AL,41
88 04    MOV  [SI],AL
B4 3C    MOV  AH,3C
41       INC  CX
89 F2    MOV  DX,SI
CD 21    INT  21
93       XCHG BX,AX
B4 40    MOV  AH,40
49       DEC  CX
CD 21    INT  21
C3       RET

0

File DOS COM - 36 byte

56 BE 80 00 AD FE C8 A2 10 01 7E 17 89 F2 88 74
02 B4 3C 33 C9 CD 21 72 0A 8B D8 B4 40 5A B9 24
00 CD 21 C3 

Nama file output ditentukan pada baris perintah, terpotong ke format 8.3, spasi OK (spasi dalam nama file DOS legal). Diuji menggunakan prompt perintah WinXP.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.