방사선 경화 조사기 작성


17

과제는 방사선 경화형 조사기를 작성하는 것입니다. 정확히 무엇을 의미합니까?

irradiator는 입력으로 문자열을 제공 할 때 한 문자를 제거하고 가능한 모든 버전의 문자열을 출력하는 프로그램입니다. 예를 들어 input이 주어지면 Hello, world!프로그램은 다음을 출력해야합니다.

ello, world!
Hllo, world!
Helo, world!
Helo, world!
Hell, world!
Hello world!
Hello,world!
Hello, orld!
Hello, wrld!
Hello, wold!
Hello, word!
Hello, worl!
Hello, world

그러나 방사선 조사 장치는 방사선으로부터 보호되어야하므로, 작성한 방사선 조사 장치를 통과해도 살아남 아야합니다. 즉, 프로그램의 단일 바이트가 제거 될 때 프로그램은 여전히 ​​제대로 작동해야합니다.

테스트 사례

abc -> bc; ac; ab
foo bar -> oo bar:fo bar:fo bar:foobar:foo ar:foo br:foo ba
source -> ource;surce;sorce;souce;soure;sourc;

명세서

  • 표준 I / O 규칙에 따라 적절한 방법으로 입력 할 수 있습니다.
  • 출력은 문자열 목록 또는 문자 또는 문자 그룹으로 구분 된 인쇄 된 목록 일 수 있습니다. 후행 구분 기호를 사용할 수 있습니다
  • 가능한 모든 버전을 포함하는 한 출력 순서는 상관 없습니다.
  • 중복 된 항목 (예 : Helo, world!첫 번째 예에서 두 개의 항목 )은 필터링 될 수 있지만 반드시 필요한 것은 아닙니다.
  • 이것이 이므로 바이트 단위의 가장 작은 프로그램이 승리합니다.

... 또는 쉼표일까요?
Jonathan Allan

4
와 C 프로그램 때문에 하나는 정말, 골프 언어를 선호한다 vvoid제거가 컴파일되지 않습니다
르지 Szewczyk을

3
@Krzysztof tbh 나는 모든 실용적인 언어가 장황함과 구문 때문에 방사선 경화에서 살아남지 못할 것이라고 생각합니다. 이 도전뿐만 아니라 모든 RH에 도전합니다.
Shieru Asakoto '

답변:


13

05AB1E , 29 26 바이트

æIg<ùˆ\æIg<ùˆ\æIg<ùˆ¯¯{Å`s

온라인으로 사용해보십시오! 또는 조사 된 모든 버전을 사용해보십시오 .

내가 찾을 수있는 가장 짧은 조사기는 5 바이트입니다.

æ        # powerset of the input
 Ig      # length of the input
   <     # - 1
    ù    # elements of a with length b

아이디어는 3 번 반복 한 다음 과반수 투표를하는 것입니다.

æIg<ù         # irradiate
     ˆ        # add the result to the global array
      \       # pop (in case the above instruction gets irradiated)
æIg<ùˆ\       # idem
æIg<ùˆ        # no pop, it's okay to dirty the stack at this point
¯             # push global array
 ¯            # and again, so at least one goes through
  {           # sort
   Å          # conveniently ignored by the parser
    `         # dump
     s        # swap
              # and implicitly output

Å2 바이트 명령에 대한 접두사입니다,하지만이 없습니다 Å`가 왜 명령을 Å무시 도착은. 그래도 나중에 필요합니다.

정렬하면 다 수표가 배열의 중간에 있어야합니다. 덤프 후 스와핑은 해당 값을 스택의 맨 위에 가져옵니다.

초기 부분의 모든 조사는 전역 배열에서 오류를 발생 시키며 대다수 투표로 해결됩니다. 마지막 {Å`s비트의 조사는 다음과 같이 추론하기가 훨씬 까다 롭습니다.

  • Å 어쨌든 무시되므로 조사해도 괜찮습니다.

  • 백틱이 조사 Å`s되면 Ås"배열의 중간에 가져 오기"확장 명령이됩니다.

  • 경우 {또는 s조사, 다른 수단 아무것도 없다고 때문에 글로벌 어레이는 동일한 값을 세 번이다. 이 경우 정렬 / 스와핑이 필요하지 않으며 모든 값이 작동합니다.


3
매우 인상적! RH 챌린지에 대한 05AB1E 답변을 볼 수 있다고 생각하지 않았습니다. 나는이 답변에 보상을주는 현상금을 추가 할 것입니다 (그리고 도전에 약간 더 많은 노출을 줄 것입니다). 당신은 내 많은 답변을 골프를 쳤으므로, 당신은 그들에게도 많은 신용을받을 가치가 있습니다! :)
Kevin Cruijssen

3
실제로, 나는 전에 RH 도전에 대한 05AB1E 답변을 보았습니다 . 아직도, 매우 인상적입니다!
Kevin Cruijssen

5

8086 머신 코드 (MS-DOS .COM), 83 바이트

DOSBox 또는 선호하는 증기 구동 컴퓨팅 엔진에서 실행할 수 있습니다. 조사 할 문자열은 명령 행 인수로 제공됩니다.

이진 :

00000000 : EB 28 28 8A 0E 80 00 49 BD 83 00 B4 02 51 8A 0E : .((....I.....Q..
00000010 : 80 00 BE 82 00 AC 39 EE 74 04 88 C2 CD 21 E2 F5 : ......9.t....!..
00000020 : 59 45 B2 0A CD 21 E2 E5 C3 90 EB D7 D7 8A 0E 80 : YE...!..........
00000030 : 00 49 BD 83 00 B4 02 51 8A 0E 80 00 BE 82 00 AC : .I.....Q........
00000040 : 39 EE 74 04 88 C2 CD 21 E2 F5 59 45 B2 0A CD 21 : 9.t....!..YE...!
00000050 : E2 E5 C3                                        : ...

읽을 수있는 :

cpu 8086
org 0x100
    jmp part2
    db 0x28

part1:
    mov cl, [0x80]
    dec cx
    mov bp, 0x83
    mov ah, 0x02

.l:
    push cx
    mov cl, [0x80]
    mov si, 0x82
.k:
    lodsb
    cmp si, bp
    je .skip
    mov dl, al
    int 0x21
.skip:
    loop .k
    pop cx
    inc bp
    mov dl, 10
    int 0x21
    loop .l
    ret

    nop
part2:
    jmp part1
    db 0xd7
    mov cl, [0x80]
    dec cx
    mov bp, 0x83
    mov ah, 0x02

.l:
    push cx
    mov cl, [0x80]
    mov si, 0x82
.k:
    lodsb
    cmp si, bp
    je .skip
    mov dl, al
    int 0x21
.skip:
    loop .k
    pop cx
    inc bp
    mov dl, 10
    int 0x21
    loop .l
    ret

개요

활성 부분은 항상 복사에 의해 손길이 닿지 않도록 복제됩니다. 우리는 점프를 통해 건강한 버전을 선택합니다. 각 점프는 짧은 점프이며, 단지 2 바이트 길이이며, 두 번째 바이트는 변위입니다 (즉, 부호 결정 방향으로 점프 할 거리).

코드를 조사 할 수있는 네 부분으로 나눌 수 있습니다 : 점프 1, 코드 1, 점프 2 및 코드 2. 깨끗한 코드 파트가 항상 사용되도록하는 것이 좋습니다. 코드 부분 중 하나에 조사하면 다른 코드 부분을 선택해야하지만 점프 중 하나에 조사하면 두 코드 부분이 모두 깨끗해 지므로 어느 코드 부분을 선택해도 문제가되지 않습니다.

두 개의 점프 부품이있는 이유는 첫 번째 부품의 점프를 건너 뛰어 감지하는 것입니다. 첫 번째 코드 부분이 조사되면 마크에서 1 바이트 도착한다는 의미입니다. 우리가 그러한 벙치 착륙이 코드 2를 선택하고 적절한 착륙이 코드 1을 선택하면 우리는 황금색입니다.

두 점프 모두에 대해, 변위 바이트를 복제하여 각 점프 부분을 3 바이트 길이로 만듭니다. 이렇게하면 마지막 두 바이트 중 하나에 조사하면 여전히 점프가 유효 해집니다. 첫 번째 바이트의 조사는 점프가 발생하는 것을 막을 것입니다. 마지막 두 바이트는 완전히 다른 명령을 형성하기 때문입니다.

첫 점프를하세요 :

EB 28 28        jmp +0x28 / db 0x28

0x28바이트 중 하나 가 제거되면 여전히 동일한 위치로 이동합니다. 경우 0xEB바이트가 제거되고, 우리는 대신에 종료됩니다

28 28           sub [bx + si], ch

이것은 MS-DOS에 대한 양 성적 인 지침이며 (다른 맛은 동의하지 않을 수 있음) 코드 1로 넘어갑니다. 손상이 점프 1에 있었기 때문에 깨끗해야합니다.

점프를하면 두 번째 점프에 착륙합니다.

EB D7 D7        jmp -0x29 / db 0xd7

이 바이트 시퀀스가 ​​손상되지 않고 마크에 바로 도달하면 코드 1이 깨끗하고이 명령이 해당 부분으로 이동한다는 것을 의미합니다. 변경된 변위 바이트가 손상된 변위 바이트 중 하나라도이를 보장합니다. 손상된 코드 1 또는 점프 1로 인해 1 바이트가 떨어지거나 0xEB나머지 바이트가 손상된 경우 나머지 2 바이트도 양성입니다.

D7 D7           xlatb / xlatb

어떤 경우이든, 우리가이 두 명령을 실행하게되면 점프 1, 코드 1 또는 점프 2가 조사되어 코드 2로 넘어갑니다.

테스팅

다음 프로그램은 모든 버전의 .COM 파일을 자동으로 만드는 데 사용되었습니다. 또한 대상 환경에서 실행할 수있는 BAT 파일을 생성합니다.이 파일은 조사 된 각 바이너리를 실행하고 출력을 별도의 텍스트 파일로 파이프합니다. 출력 파일을 비교하여 검증하는 것은 쉽지만 DOSBox에는이 없기 fc때문에 BAT 파일에 추가되지 않았습니다.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    FILE *fin, *fout, *fbat;
    int fsize;
    char *data;

    if (!(fin = fopen(argv[1], "rb")))
    {
        fprintf(stderr, "Could not open input file \"%s\".\n", argv[1]);
        exit(1);
    }

    if (!(fbat = fopen("tester.bat", "w")))
    {
        fprintf(stderr, "Could not create BAT test file.\n");
        exit(2);
    }

    fseek(fin, 0L, SEEK_END);
    fsize = ftell(fin);
    fseek(fin, 0L, SEEK_SET);

    if (!(data = malloc(fsize)))
    {
        fprintf(stderr, "Could not allocate memory.\n");
        exit(3);
    }

    fread(data, 1, fsize, fin);

    fprintf(fbat, "@echo off\n");

    for (int i = 0; i < fsize; i++)
    {
        char fname[512];

        sprintf(fname, "%03d.com", i);
        fprintf(fbat, "%s Hello, world! > %03d.txt\n", fname, i);

        fout = fopen(fname, "wb");

        fwrite(data, 1, i, fout);
        fwrite(data + i + 1, 1, fsize - i - 1, fout);

        fclose(fout);
    }

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