자기 복제 프로그램을 작성하십시오.


11

실행될 때 자체를 복사하는 간단한 프로그램을 작성하십시오.

귀하의 프로그램은 Windows, Linux 등에서 일종의 실행 파일이어야하며, 임의의 이름을 가진 원래 실행 파일과 동일한 새 실행 파일을 생성하고 종료해야합니다.

당신의 프로그램 어떤 종류의 파일 읽기 나 복사를 포함 해서는 안됩니다 . 새 실행 파일을 생성하기위한 파일 쓰기 만 허용됩니다.

(PS. Wikipedia에서 기사로 Self-replicating program리디렉션 할 때 매우 당황했습니다 Computer virus... : / ...)

실행 파일 크기가 가장 작습니다. 귀하의 답변은 적절한 OS 및 컴파일러가 포함 된 프로그래밍 코드, 어셈블리 코드 또는 실행 파일의 HEX 덤프 일 수 있습니다.


6
이것은 기존의 [퀸] 도전과는 사소한 차이가있는 것으로 보인다. 아니면 내가 잘못 이해 했습니까?
dmckee --- 전 운영자 고양이

1
@dmckee 어셈블리 언어 Quine자체 복제 Hello World 프로그램에서 복사를 허용하는 것을 보았지만 코드가 아닌 프로그램이 자체적으로 작성되는 것을 찾을 수 없었습니다 .
JiminP

1
...하지만 실제로 어떻게 작동하는지 알고 싶습니다! .. 이진 코드로 아이디어를 확장 할 수있는 방법을 모르겠습니다. Wikipedia에서 Quine 기사를 읽더라도 말입니다. 추신. 복제를위한 컴파일러와 스크립트 언어는 허용되지 않습니다 ... : /
JiminP

4
제약 조건을 추가하면 문제를 조금 더 어렵고 추악하게 만들 수 있습니다. 이 문제가 quine 문제의 사소한 확장이라는 것을 알았습니다.
Alexandru

1
실행 파일 크기가 가장 작 으면, 인터프리터 코드를 실행 가능한 크기의 일부로 고려하여 컴파일 된 언어 사용자에게 적합하지 않아야합니까?
Thomas Dignan

답변:


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 어셈블러를위한 것입니다. 명령 행을 사용하여 바이너리를 빌드하십시오.nasm -f bin -o a.out selfrep.asm && chmod +x a.out

다음은 16 진 덤프와 동일한 파일입니다. 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

요청에 따라 프로그램은 자체 파일을 별도의 파일로 복사합니다. (stdout에 쓰고 사용자가 파일로 리디렉션하도록 허용하면 프로그램이 상당히 짧아 질 수 있습니다.)

크기를 줄이기 위해 경계선 트릭을 사용하지 않았습니다. 이것은 완전한 32 비트 ELF 바이너리 여야합니다.

추가 편집 : 위의 버전에서 생성 된 파일은 단순한 파일이지만 몇 바이트 (그리고 규칙의 작은 굴곡)에 대해 조금 더 흥미로운 것을 만들 수 있습니다. 이 버전은 108 바이트에서 2 바이트 만 더 깁니다.

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

nasm 장애가있는 16 진 덤프 버전 : 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! 어셈블리 퀴네 챌린지를 보셨습니까 ?
MD XF

2

다음은 .NET의 Compilation 서비스를 사용하여 소스 코드를 즉시 컴파일하여 동일한 출력을 생성하는 방법을 보여주는 개념 증명 (교체되지 않음)입니다. 첫 번째 사본은 원본과 동일하지 않지만 후속 실행의 후속 사본은 무작위 파일 이름과 정확히 동일합니다.

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 참조는 파일에서 읽기를 유발하여 규칙을 위반합니다. 게다가, 이진 버전은 더 짧습니다. :-)
peter ferrie

1

DOS COM 파일-50 바이트

파일 생성 현재 시간의 것들의 숫자로 대체됩니다. COM 파일은 데이터 세그먼트의 오프셋에서 단순히 메모리에로드되므로 (CS와 DS는 동일하게 설정 됨)이 메모리를 파일에 간단히 쓸 수 있습니다.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 소스

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

DOS COM 파일-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 명령 프롬프트를 사용하여 테스트했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.