Écrivez un programme d'auto-réplication.


11

Écrivez un programme simple qui se copie lorsqu'il est exécuté.

Votre programme doit être une sorte de fichier exécutable sous Windows, Linux, etc., doit générer un nouveau fichier exécutable, identique à votre fichier exécutable d'origine, avec un nom aléatoire, et se ferme.

Votre programme ne doit impliquer aucun type de lecture ou de copie de fichiers. Seule l'écriture de fichier pour générer un nouveau fichier exécutable est autorisée.

(PS. J'étais assez gêné quand sur Wikipedia, Self-replicating programredirige vers l' Computer virusarticle ...: / ...)

La plus petite taille de fichier exécutable gagne. Votre réponse peut être un code de programmation avec un système d'exploitation et un compilateur appropriés, un code d'assemblage ou un vidage HEX d'un fichier exécutable.


6
Cela semble ne différer que de manière négligeable des défis [quine] existants. Ou ai-je mal compris?
dmckee --- chaton ex-modérateur

1
@dmckee J'ai vu le programme Assembly World Quine et Self replicating Hello World accepter la copie, mais je n'ai pas trouvé le programme lui - même , pas son code .
JiminP

1
... mais je veux voir comment cela fonctionne réellement! .. Je ne sais pas comment l'idée peut être étendue avec des codes binaires .. même si j'ai lu l'article de Quine sur Wikipedia. PS. aucun compilateur pour la réplication et aucun langage de script n'est autorisé ...: /
JiminP

4
Tout problème peut être rendu plus difficile et plus laid en y ajoutant plus de contraintes. Je trouve que ce problème est une extension triviale du problème quine.
Alexandru

1
Si la plus petite taille exécutable gagne, ne devrions-nous pas également prendre en compte le code interprète dans le cadre de la taille exécutable pour que cela soit équitable pour les utilisateurs des langages compilés?
Thomas Dignan

Réponses:


4

Bash, 236

Plus long que strictement nécessaire, mais je déteste les longues lignes. La nouvelle ligne de fin n'est pas facultative.

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

En fait, ce n'est pas ce que je voulais, cependant, car j'ai écrit une "mauvaise" question et votre réponse est une excellente quine ...
JiminP

@JiminP: Comment se fait-il que ce ne soit pas ce que vous vouliez? Je viens de relire la description du problème deux fois et je n'arrive pas à comprendre.
JB

Eh bien ... ce que je voulais, c'était un code binaire exécutable. Comme je l'ai admis ci-dessus, puisque ma question n'était pas tout à fait «juste» ... désolé pour cela.
JiminP

3
@JiminP Eh bien, oui, le mot "binaire" n'apparaît pas du tout dans la question. Je viens de le trouver dans les commentaires, mais pour une telle restriction, il ne suffit pas. Vous pouvez ouvrir une nouvelle question avec toutes les entrées consolidées des commentaires. Je vous suggère d'utiliser le bac à sable pour vous assurer que les habitués vous aident à régler les petits détails. Mais attention, les réponses binaires ont tendance à être vraiment ennuyeuses.
JB

10

Assemblage pour x86 Linux, 106 octets

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

C'est pour l'assembleur nasm. Construisez le binaire avec la ligne de commande:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Voici le même fichier qu'un vidage hexadécimal: 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

Comme demandé, le programme se copie dans un fichier séparé. (Le programme aurait pu être considérablement plus court s'il avait été autorisé à simplement écrire sur stdout et à laisser l'utilisateur rediriger vers un fichier.)

J'ai évité d'utiliser des astuces limites pour réduire la taille. Il doit s'agir d'un binaire ELF 32 bits entièrement conforme.

Modifié pour ajouter : dans la version ci-dessus, le fichier créé est juste un fichier ordinaire, mais il me semble que pour quelques octets (et un petit pli des règles), vous pouvez créer quelque chose d'un peu plus intéressant. Cette version ne fait que deux octets de plus, à 108 octets:

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

Nommez cette version asr, pour "un auto-réplicateur":nasm -f bin -o asr asr.asm && chmod +x asr

Version de vidage hexadécimal pour les nasm-altérés: 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

Lorsque vous l'exécutez, il crée un fichier presque identique nommé bsr, mais qui est lui-même exécutable. L'exécuter créera un autre fichier binaire nommé csr. Etc.

(Notez que des choses ennuyeuses commencent à se produire après zsr. J'ai envisagé de créer une version qui répercuterait le changement de nom sur atret ainsi de suite, mais je pense que la plupart des gens s'ennuieront bien avant cela, donc cela ne vaut probablement pas tous les octets supplémentaires. )


+1 pour la réponse d'assemblage! Avez-vous vu le défi d'assemblage quine ?
MD XF

2

Voici une preuve de concept (non golfée) qui montre comment les services de compilation dans .NET peuvent être utilisés pour compiler le code source à la volée pour générer une sortie identique. La première copie n'est pas identique à l'original, mais les copies suivantes des exécutions suivantes sont exactement identiques avec des noms de fichiers aléatoires:

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

Sortie de démonstration en ligne de commande:

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

Lot

Version 1 (30 octets)

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

Je gagne! :)


la référence% 0 provoque une lecture du fichier, ce qui viole les règles. D'ailleurs, ma version binaire est encore plus courte. :-)
peter ferrie

1

Fichier DOS COM - 50 octets

Crée un fichier X.COMXest remplacé par le chiffre des de l'heure actuelle. Les fichiers COM sont simplement chargés dans la mémoire à l'offset 100hdu segment de données (CS et DS sont définis pour être identiques) afin que nous puissions simplement écrire cette mémoire dans un fichier.

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.

source de 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

Fichier DOS .COM, 29 octets

Le '@' est remplacé aléatoirement par une lettre impaire dans la première moitié + partie de l'alphabet (A, C, E, G, etc.). Les fichiers de sortie font 255 ou 256 octets. Les registres initiaux sous DOS réel (par opposition à un débogueur) sont que 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

Fichier DOS COM - 36 octets

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 

Le nom du fichier de sortie est spécifié sur la ligne de commande, tronqué au format 8.3, les espaces sont OK (les espaces dans les noms de fichiers DOS sont légaux). Testé à l'aide de l'invite de commande WinXP.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.