Kendi kendini kopyalayan bir program yazın.


11

Yürütüldüğünde kendini kopyalayan basit bir program yazın.

Programınız Windows, Linux, vb. Üzerinde bir tür yürütülebilir dosya olmalıdır, orijinal yürütülebilir dosyanızla aynı olan, yeni bir yürütülebilir dosya oluşturmalı ve rasgele bir ad ile çıkmalıdır.

Programınız herhangi bir dosya okuma veya kopyalama içermemelidir . Yalnızca yeni yürütülebilir dosya oluşturmak için dosya yazmaya izin verilir.

(PS. Vikipedi'de oldukça utandım, makaleye Self-replicating programyönlendiriyor Computer virus...: / ...)

En küçük yürütülebilir dosya boyutu kazanır. Yanıtınız, yürütülebilir bir dosyanın uygun işletim sistemi ve derleyicisi, montaj kodu veya HEX dökümü olan bir programlama kodu olabilir.


6
Bu sadece varolan [quine] zorluklardan çok farklı görünmektedir. Yoksa yanlış mı anladım?
dmckee --- eski moderatör kedi yavrusu

1
@ dmckee Meclis Dili Quine ve Kendini çoğaltan Hello World programının kopyalamayı kabul ettiğini gördüm , ancak programın kodunu değil kendini yazdığını bulamadım .
JiminP

1
... ama aslında nasıl çalıştığını görmek istiyorum! .. Vikipedi'de Quine makalesini okuduğum halde fikrin ikili kodlarla nasıl genişletilebileceğini bilmiyorum. PS. çoğaltma için derleyici yok ve komut diline izin verilmiyor ...: /
JiminP

4
Herhangi bir sorun, daha fazla kısıtlama ekleyerek biraz daha zor ve çirkin hale getirilebilir. Bu sorunu quine sorununun önemsiz bir uzantısı olarak görüyorum.
Alexandru

1
En küçük yürütülebilir boyut kazanırsa, derlenmiş dillerdeki kullanıcılar için adil olması için yorumlayıcı kodunu yürütülebilir boyutun bir parçası olarak da hesaba katmamalıyız?
Thomas Dignan

Yanıtlar:


4

Baş, 236

Kesinlikle gerekli olandan daha uzun, ama uzun çizgilerden nefret ediyorum. Sondaki yeni satır isteğe bağlı değildir.

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

Aslında, "yanlış" bir soru yazdığım ve cevabınız harika bir soru olduğu için istediğim gibi değil ...
JiminP

@JiminP: İstediğiniz bu nasıl değil? Sorun açıklamasını tekrar iki kez okudum ve anlayamıyorum.
JB

Şey ... istediğim yürütülebilir bir ikili kod oldu. Yukarıda da itiraf ettiğim gibi, sorum tam olarak 'doğru' olmadığı için ... bunun için üzgünüm.
JiminP

3
@JiminP Evet, soruda "ikili" kelimesi hiç görünmüyor. Sadece yorumlarda buldum, ama böyle bir kısıtlama için, sadece kesmiyor. Yorumlar'daki tüm konsolide girdilerle yeni bir soru açabilirsiniz. Düzenleyicilerin küçük ayrıntıları ütülemenize yardımcı olması için korumalı alanı kullanmanızı öneririm . Ama dikkat, ikili cevaplar gerçek sıkıcı olma eğilimindedir.
JB

10

X86 Linux, 106 bayt için derleme

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

Bu nasm toplayıcı içindir. Komut satırı ile ikili dosyayı oluşturun:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

İşte onaltılık dökümü ile aynı dosya: 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

Talep edildiği gibi, program kendisini ayrı bir dosyaya kopyalar. (Programın yalnızca stdout'a yazmasına ve kullanıcının bir dosyaya yönlendirmesine izin vermiş olsaydı, önemli ölçüde daha kısa olabilirdi.)

Boyutu azaltmak için sınırda hileler kullanmaktan kaçındım. Bu tamamen uyumlu bir 32 bit ELF ikili dosyası olmalıdır.

Eklemek için düzenlenmiştir : Yukarıdaki sürümde oluşturulan dosya sadece düz bir dosyadır, ancak bana birkaç bayt (ve kuralların küçük bir bükümü) için biraz daha ilginç bir şey oluşturabileceğiniz ortaya çıkıyor. Bu sürüm 108 baytta yalnızca iki bayt daha uzun:

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

asr"Kendini çoğaltan" için bu sürümü adlandırın :nasm -f bin -o asr asr.asm && chmod +x asr

Nazm engelliler için onaltılık döküm versiyonu: 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

Çalıştırdığınızda, hemen hemen aynı bsr, ancak yürütülebilir bir dosya oluşturur. Çalıştırılması adlı başka bir ikili dosya oluşturur csr. Ve bunun gibi.

(Sinir bozucu şeyler sonra olmaya başlar unutmayın zsr. Ben ad değişikliği atrvb basamaklı bir sürüm yapmayı düşündüm , ama çoğu insan o zamandan önce çok sıkılmış olacağını düşünüyorum, bu yüzden muhtemelen tüm ekstra bayt değmez. )


Montaj yanıtı için +1! Meclis quine meydan okuma gördün mü ?
MD XF

2

Burada, .NET'teki Derleme hizmetlerinin, özdeş bir çıktı oluşturmak üzere kaynak kodunu anında derlemek için nasıl kullanılabileceğini gösteren bir kavram kanıtı (ungolfed). İlk kopya orijinal ile aynı değildir, ancak sonraki çalışmalardan sonraki kopyalar rastgele dosya adlarıyla tamamen aynıdır:

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);
        }
    }
}

Komut satırında gösterim çıktısı:

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

yığın

Sürüm 1 (30 bayt)

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

Ben kazandım! :)


% 0 başvurusu, kuralları ihlal eden dosyadan bir okumaya neden olur. Ayrıca, ikili versiyonum daha da kısadır. :-)
peter ferrie

1

DOS COM dosyası - 50 bayt

Bir dosya oluşturur şimdiki zamanın olanlar rakam ile değiştirilir. COM dosyaları , veri segmentinin ofisinde (CS ve DS aynı olacak şekilde) belleğe yüklenir, böylece bu belleği bir dosyaya yazabiliriz.X.COMX100h

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.

nasm kaynağı

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

DOS .COM dosyası, 29 bayt

'@' Rastgele olarak ilk yarısında + alfabenin bir bölümünde (A, C, E, G, vb.) Tek bir harfle değiştirilir. Çıktı dosyaları 255 veya 256 bayttır. Gerçek DOS'taki ilk kayıtlar (hata ayıklayıcının aksine) AX = 0000, CX = 00FF, SI = 0100'dür.

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

DOS COM Dosyası - 36 bayt

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 

Çıktı dosya adı komut satırında belirtilir, 8.3 biçiminde kesilir, boşluklar OK (DOS dosya adlarındaki boşluklar yasaldır). WinXP komut istemi kullanılarak test edildi.

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.