Напишите самовоспроизводящуюся программу.


11

Напишите простую программу, которая копирует себя при выполнении.

Ваша программа должна быть своего рода исполняемым файлом в Windows, Linux и т. Д., Должна генерировать новый исполняемый файл, который идентичен исходному исполняемому файлу со случайным именем и завершается.

Ваша программа не должна включать чтение или копирование файлов. Разрешается только запись файла для создания нового исполняемого файла.

(PS. Я был довольно смущен, когда в Википедии, Self-replicating programперенаправляет на Computer virusстатью ...: / ...)

Наименьший размер исполняемого файла побеждает. Ваш ответ может быть программным кодом с соответствующей ОС и компилятором, ассемблерным кодом или HEX-дампом исполняемого файла.


6
Похоже, это лишь тривиально отличается от существующих проблем. Или я неправильно понял?
dmckee --- котенок экс-модератора

1
@dmckee Я видел ассемблер Quine и Self реплицирующую программу Hello World, принимающую копирование, но я не смог найти саму программу , а не ее код .
JiminP

1
... но я хочу посмотреть, как это на самом деле работает! .. Я не знаю, как эту идею можно расширить с помощью двоичных кодов ... хотя я читал статью Куайна в Википедии. PS. нет компиляторов для репликации и не разрешены языки сценариев ...: /
JiminP

4
Любая проблема может быть сделана немного сложнее и сложнее, добавив к ней больше ограничений. Я считаю эту проблему тривиальным расширением проблемы Квина.
Александру

1
Если выигрывает наименьший размер исполняемого файла, не должны ли мы также учитывать код интерпретатора как часть размера исполняемого файла, чтобы это было справедливо для пользователей скомпилированных языков?
Томас Диньян

Ответы:


4

Баш, 236

Дольше, чем строго необходимо, но я ненавижу длинные очереди. Завершающий перевод строки не является обязательным.

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

На самом деле, это не то, что я хотел, однако, так как я написал «неправильный» вопрос, а ваш ответ - отличная лозунг ...
JiminP

@JiminP: Как это не то, что вы хотели? Я просто дважды прочитал описание проблемы и не смог понять.
JB

Ну ... я хотел исполняемый двоичный код. Как я признался выше, поскольку мой вопрос не был «правильным» ... извините за это.
JiminP

3
@ JiminP Ну, да, слово «двоичный» вообще не фигурирует в вопросе. Я только нашел это в комментариях, но для такого ограничения, это просто не сокращает это. Вы можете открыть новый вопрос со всеми сводными данными из комментариев. Я предлагаю вам использовать песочницу, чтобы завсегдатаи помогли вам сгладить мелкие детали. Но будьте осторожны, бинарные ответы обычно бывают скучными.
JB

10

Сборка для x86 Linux, 106 байт

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

Это для сборщика носа. Создайте двоичный файл с помощью командной строки:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Вот тот же файл, что и шестнадцатеричный дамп: 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

По запросу программа копирует себя в отдельный файл. (Программа могла бы быть значительно короче, если бы ей было позволено просто писать в стандартный вывод и позволить пользователю перенаправлять в файл.)

Я избегал использования граничных трюков, чтобы уменьшить размер. Это должен быть полностью совместимый 32-битный двоичный файл ELF.

Отредактировано, чтобы добавить : В вышеупомянутой версии созданный файл - просто обычный файл, но мне приходит в голову, что за пару байтов (и небольшой изгиб правил) вы можете создать что-то более интересное. Эта версия только на два байта длиннее, в 108 байтов:

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для "саморепликатора":nasm -f bin -o asr asr.asm && chmod +x asr

Шестнадцатеричная версия дампа для людей с нарушениями носа: 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

Когда вы запускаете его, он создает почти идентичный файл с именем bsr, но тот, который сам по себе является исполняемым. Запуск его создаст еще один двоичный файл с именем csr. И так далее.

(Обратите внимание, что раздражающие вещи начинают происходить после того, как zsr. Я подумал о создании версии, которая каскадно меняла бы название на atrи т. Д., Но я думаю, что большинству людей до этого будет скучно, поэтому, вероятно, это не стоит всех лишних байтов. )


+1 за сборку ответа! Вы видели сборку Quine ?
MD XF

2

Вот примерное доказательство (ungolfed), которое показывает, как сервисы компиляции в .NET могут быть использованы для компиляции исходного кода на лету для генерации идентичного вывода. Первая копия не идентична оригиналу, но последующие копии из последующих прогонов точно идентичны со случайными именами файлов:

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

Демонстрационный вывод в командной строке:

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

партия

Версия 1 (30 байт)

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

Я выигрываю! :)


ссылка% 0 вызывает чтение из файла, что нарушает правила. Кроме того, моя бинарная версия еще короче. :-)
Питер Ферри

1

COM-файл DOS - 50 байт

Создает файл, в X.COMкотором Xзаменяется цифрой единицы текущего времени. COM-файлы просто загружаются в память по смещению 100hсегмента данных (CS и DS установлены одинаковыми), поэтому мы можем просто записать эту память в файл.

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.

источник носа

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, 29 байт

Символ @ заменяется случайным образом на нечетную букву в первой половине + часть алфавита (A, C, E, G и т. Д.). Выходные файлы имеют размер 255 или 256 байт. Начальные регистры в реальном DOS (в отличие от отладчика) таковы, что 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

COM-файл DOS - 36 байт

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 

Имя выходного файла указывается в командной строке, усекается до формата 8.3, пробелы в порядке (пробелы в именах файлов DOS допустимы). Протестировано с использованием командной строки WinXP.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.