Codegolf - Напишите Радиационно-Стойкий Облучатель

  • Автор темы Kamila
  • Обновлено
  • 19, Oct 2024
  • #1

Задача — написать радиационно-стойкий облучатель. Что именно я имею в виду?

Облучатель — это программа, которая, если на входе задана строка, выводит все возможные версии строки с удаленным одним символом. Например, учитывая ввод

 
 Helo, world! 
, the program should output:

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;

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

Тестовые случаи

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

Технические характеристики

  • Вы можете получить данные любым приемлемым способом с помощью нашего Стандартные правила ввода-вывода
  • Выходными данными может быть либо список строк, либо напечатанный список, разделенный символом или группой символов. Конечный разделитель допускается.
  • Вывод может быть в любом порядке, если он содержит все возможные версии.
  • Повторяющиеся записи (например, две Hello, world! s in the first example) may be filtered out, but this is not necessary
  • В этом случае побеждает наименьшая программа в байтах.

#код-гольф #код-гольф #радиационная закалка

Kamila


Рег
04 Feb, 2012

Тем
60

Постов
185

Баллов
525
  • 26, Oct 2024
  • #2

05AB1E, 29 26 байт

 
 
 
 
 
 
 
 
 
 #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, "d.com", i);

fprintf(fbat, "%s Hello, world! > d.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);
}
 

Попробуйте онлайн!, или попробуйте все облученные версии.

Самый короткий облучатель, который мне удалось найти, занимает 5 байт:

fc

Идея состоит в том, чтобы повторить это 3 раза, а затем проголосовать большинством:

D7 D7 xlatb / xlatb

0xEB is a prefix for 2-byte commands, but there's no EB D7 D7 jmp -0x29 / db 0xd7 команда, поэтому 28 28 sub [bx + si], ch gets ignored. We'll need it later, though.

Сортировка гарантирует, что большинство голосов окажется в середине массива. Сброс, а затем замена переносят это значение на вершину стека.

Любое облучение в начальной части приводит лишь к ошибке в глобальном массиве, которая решается большинством голосов. Облучения в финале 0xEB bit are much trickier to reason about:

  • 0x28 is ignored anyway, so it's okay to irradiate it

  • Если обратная галочка облучена, EB 28 28 jmp +0x28 / db 0x28 becomes 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 , которая представляет собой расширенную команду «получить середину массива».

  • Если 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 : ... or s облучены, это означает, что больше ничего не облучено, поэтому глобальный массив имеет одно и то же значение три раза. В этом случае нам не нужна сортировка/замена, подойдет любое значение.

 

Mimboqigeowv16


Рег
02 Feb, 2008

Тем
67

Постов
206

Баллов
551
  • 26, Oct 2024
  • #3

Машинный код 8086 (MS-DOS.COM), 83 байта

Запускается в DOSBox или в вашей любимой паровой вычислительной машине. Строка для облучения задается как аргумент командной строки.

Двоичный:

{

Читабельно:

Ås

Наезжать

Активная часть дублируется, так что всегда есть одна, не затронутая радиацией. Методом прыжков выбираем здоровый вариант. Каждый прыжок является коротким, поэтому его длина составляет всего два байта, где второй байт — это смещение (т. е. расстояние прыжка со знаком, определяющим направление).

Мы можем разделить код на четыре части, которые могут быть подвергнуты облучению: переход 1, код 1, переход 2 и код 2. Идея состоит в том, чтобы всегда использовать чистую часть кода. Если одна из частей кода облучается, необходимо выбрать другую, но если облучается один из переходов, обе части кода будут чистыми, поэтому не имеет значения, какая из них будет выбрана.

Причина наличия двух частей прыжка заключается в том, чтобы обнаружить облучение в первой части, перепрыгнув через нее. Если первая часть кода облучается, это означает, что мы прибудем на один байт от отметки. Если мы убедимся, что такая неудачная посадка выберет код 2, а правильная посадка выберет код 1, мы в выигрыше.

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

Совершите первый прыжок:

Å`s

Если любой из Å bytes are removed, it will still jump to the same place. If the {Å`s байт удален, вместо этого мы получим

Å

это вполне безопасная инструкция для MS-DOS (другие версии могут с этим не согласиться), а затем мы переходим к коду 1, который должен быть чистым, поскольку повреждение произошло в прыжке 1.

Если прыжок выполнен, мы приземляемся на втором прыжке:

Å`

Если эта последовательность байтов цела и мы попадаем прямо на отметку, это означает, что код 1 был чистым, и эта инструкция возвращается к этой части. Дублированный байт смещения гарантирует это, даже если один из этих байтов смещения был поврежден. Если мы либо потеряем один байт (из-за поврежденного кода 1 или перехода 1), либо Å byte is the damaged one, the two remaining bytes will also here be benign:

æ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

В любом случае, если мы в конечном итоге выполним эти две инструкции, мы будем знать, что либо переход 1, либо код 1, либо переход 2 были облучены, что делает переход к коду 2 безопасным.

Тестирование

Следующая программа использовалась для автоматического создания всех версий файла .COM. Он также создает BAT-файл, который можно запустить в целевой среде, который запускает каждый облученный двоичный файл и передает их выходные данные в отдельные текстовые файлы. Сравнение выходных файлов для проверки достаточно просто, но в DOSBox нет æ # powerset of the input Ig # length of the input < # - 1 ù # elements of a with length b , so it was not added to the BAT file.

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

Matrixa-neo


Рег
08 Sep, 2007

Тем
71

Постов
203

Баллов
578
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно