Счетчик Гейгера - это устройство, которое используется для обнаружения радиации.
Мы будем делать счетную программу Гейгера.
Как мы все знаем, когда излучение попадает в компьютерную программу, оно удаляет ровно 1 байт случайным образом. Таким образом, программа счетчика Гейгера - это программа, которая сама по себе ничего не делает, но когда удаляется любой байт, распечатывается измененная программа beep
, указывающая на наличие излучения.
Ответы будут оцениваться в байтах, причем меньшее количество байтов будет лучше. Ответы должны быть не менее 1 байта.
Ваша программа может печатать beep
с завершающим символом новой строки или печатать одну новую строку для пустого вывода, если это происходит последовательно. Ваша программа может также использовать другой случай для beep
таких , как BEEP
, bEEP
или Beep
до тех пор , как она делает это последовательно.
источник
Ответы:
Потерянный ,
303 293 263 253 238228 байтПопробуйте онлайн!
Скрипт проверки (заимствовано из ответа пользователя 202729 ). К сожалению, это может проверить только половину кода за раз, но будьте уверены, я протестировал всю программу.
Ой, это было сложно. Я процитирую удаленный ответ WW:
К сожалению, его ответ не принял во внимание удаление новых строк, которые все испортили.
Объяснение:
(обратите внимание, что несколько байтов могут быть здесь и там)
Сначала поговорим об общей структуре кода:
Все, кроме технологической линии, должно целиком состоять из одного
>
или одного из них\/
. Зачем? Ну, в качестве примера, давайте удалим новую строку:Первая строка теперь намного длиннее, чем остальная часть блока. Если бы указатель появлялся на не
>\/
персонаже с вертикальным движением, он застрял бы в бесконечном цикле.Самая большая часть детектора излучения - это сечение в конце каждой строки.
Обычно IP, проходящий через это из первой строки, выходит из последней строки. Однако, если какой-либо символ в строке удаляется, то эта строка сдвигается вниз на один, например:
И вместо этого IP выходит из строки, в которой отсутствует байт (за исключением последней строки, где он выходит со второго до последнего).
Оттуда каждая из первых четырех строк будет перенаправлена на вторую строку:
Который затем приведет к любому из двух
beep
.Если какой-либо из байтов в первом
beep
er был удален, он вместо этого переходит ко второму:beep
Затем оба приводят к первой строке и завершению@
.Некоторые другие разные части:
(((((([[[[[[[
Используются для очистки стеки , когда указатель начинается внутри пару кавычек и в конечном итоге толкает всю первую строку в стек. К сожалению, это должно быть очень долго, потому что первая новая строка может быть удалена, чтобы первая строка удвоилась. Эксперимент по генерации сbeep
использованием арифметики вместо кавычек закончился дольше.\
S и/
збросанные по линии есть для гольфа байтов в верхней строке кода, перенаправив указатель на правильные линии. Поскольку большинство нижних строчек являются просто наполнителями, только верхняя линия может быть в гольфе. Если у кого-то есть идеи относительно более короткого стека радиационной защиты, более ясного, чем то, что я имею сейчас, не стесняйтесь комментировать.источник
\/
разделитьbeep
толчки и тот факт, что только одна из цитат нуждалась в условии выхода, помоглоГексагония , 38 байт
Попробуйте онлайн!
Программа проверки.
объяснение
Мы используем автоопределение Hexagony длины шестиугольника здесь.
Если никакие байты не удалены, программа имеет длину стороны 4 и выглядит следующим образом:
Однако, если байт удаляется. Есть 2 случая.
Удаленный байт идет после второго
<
.Поток выполнения будет:
На
@
5-й строке их 2 подряд , поэтому, даже если один из них будет удален, IP-адрес благополучно попадет в точку@
.Удаленный байт находится на или перед вторым
<
.Тогда вторая половина останется нетронутой, и IP больше не будет перенаправляться вверх
<
. Изображение потока выполнения:источник
Гексагония ,
3429 байтПопробуйте онлайн! Проверка!
Объяснение:
Вот обычный код, отформатированный в правильный шестиугольник с использованием HexagonyColorer :
Двойной
//
в начале гарантирует, что этот путь всегда выбран. Если удаляется какой-либо символ,@
он удаляется с пути, либо смещается на один назад, либо удаляется сам:В этом случае мы удалили символ после
|
, который заставляет его следовать этому пути, печатаяbeep
:Если вместо этого мы удалим символ перед
|
(или|
самим собой), мы последуем за другим звуковым принтером:Затем мы учли все возможности и
beep
используем только необлученные части программы.источник
Самомодифицирующийся Brainfuck ,
7363 байтаПопробуйте онлайн! Проверка!
Пробелы в середине кода на самом деле представляют байты NUL.
Объяснение:
Код разбит на два раздела по 3 байта NUL в середине. Оба они в основном печатают,
beep
если облучают другой раздел (с несколькими исключениями).Во-первых,
<<[[
в начале необходимо убедиться, что все]
s совпадают в любое время.[
s не будет пытаться найти соответствие,]
если ячейка положительна, в то время как]
s делает . Если какой-либо]
из них возвращается к одному из этих скобок, он обычно сразу возвращается назад, потому что ячейка есть0
.Следующая часть
[[<<]]>
затем проверяет, является ли длина секции 2 четной. Если это так, он выполняет вторую половину раздела 1, который печатаетсяbeep
с использованиемbbeepp
в начале раздела 2.Затем он очищает весь раздел 2, поэтому он не выполняется.
В разделе 2 мы проверяем , если длина секции 1 и NUL байт делится на
3
с+[<<<]>>
.Точно так же мы печатаем
beep
.источник
Z80Golf ,
533634 байта-16 байт благодаря @Lynn
-2 байт благодаря @Neil
Так как это всего лишь машинный код Z80, в нем много непечатаемых файлов, поэтому используйте
xxd -r
-reversible hexdump:Попробуйте онлайн! (исчерпывающий тестер в Python)
объяснение
z80golf - гипотетическая машина Z80 от Anarchy Golf, где
call $8000
есть путчар,call $8003
гетчер,halt
выход интерпретатора, ваша программа размещена$0000
, а вся остальная память заполнена нулями. Создание радиационно-стойких программ при сборке довольно сложно, но в целом полезный метод - использование однобайтовых идемпотентных инструкций. Например,только один байт, и
a | c | c == a | c
, таким образом, он может быть защищен от радиации, просто повторяя инструкцию. На Z80 8-битная немедленная загрузка составляет два байта (где непосредственная находится во втором байте), поэтому вы можете также надежно загрузить некоторые значения в регистры. Это то, что я первоначально делал в начале программы, так что вы можете проанализировать более длинные варианты, которые я заархивировал внизу ответа, но потом я понял, что есть более простой способ.Программа состоит из двух независимых полезных нагрузок, одна из которых могла быть повреждена радиацией. Я проверяю, был ли удален байт и был ли удаленный байт перед второй копией полезной нагрузки, проверяя значения некоторых абсолютных адресов памяти.
Во-первых, нам нужно выйти, если радиации не наблюдалось:
Если какой-либо байт был удален, то все байты будут сдвинуты и
$0020
будут содержать последний76
, поэтому$0021
будет ноль. Мы можем позволить себе излучать начало программы, даже при том, что практически нет избыточности:$10
будет удалено, то излучение будет правильно обнаружено, скачок не будет выполнен, и смещение не будет иметь значения. Первый байт следующей инструкции будет израсходован, но поскольку он разработан так, чтобы быть устойчивым к удалению байтов, это не имеет значения.$20
удален, то смещение перехода$10
будет декодироваться какdjnz $ffe4
(использование следующего байта инструкции в качестве смещения - см. Выше), которое является инструкцией цикла - уменьшение B, и переходить, если результат не равен нулю. Посколькуffe4-ffff
он заполнен нулямиnop
, а счетчик программ обернутся, он запустит начало программы 256 раз, а затем, наконец, продолжит работу. Я поражен, что это работает.$dd
оставшаяся часть фрагмента будет расшифрована какor (hl) / ld ($1020), hl
, а затем вставлена в следующую часть программы. Значениеor
не изменит никаких важных регистров, и поскольку HL на этом этапе равен нулю, запись также будет отменена.$b6
заставит остальные декодировать какld ($1020), ix
и продолжить, как описано выше.$21
заставит декодер съесть$20
, вызвавdjnz
поведение.Обратите внимание, что использование
or a, (ix+*)
экономит два байта заld a, (**) / and a / and a
счет встроенной проверки на ноль.Теперь нам нужно решить, какую из двух копий полезной нагрузки выполнить:
Две копии разделены nop, поскольку для выбора между ними используется относительный переход, и радиация могла бы сдвинуть программу таким образом, чтобы переход пропустил первый байт после места назначения. Кроме того, nop кодируется как ноль, что облегчает обнаружение сдвинутых байтов. Обратите внимание, что не имеет значения, какая полезная нагрузка выбрана, если сам коммутатор поврежден, потому что тогда обе копии безопасны. Давайте удостоверимся, что он не попадет в неинициализированную память, хотя:
$dd
следующие два байта будут декодированы какor (hl) / dec d
. Клобберс Д. Ничего страшного.$b6
создаст недокументированную более длинную кодировку дляdec d
. То же, что и выше.$15
будет читать$28
вместо этого как смещение, и выполнение будет продолжаться в$0c
, как показано ниже.$28
исчезает,$0c
декодируется какinc c
. Полезная нагрузка не заботитсяc
.$0c
- вот для чего нужен nop. В противном случае первый байт полезной нагрузки будет считан как смещение перехода, и программа перейдет в неинициализированную память.Сама полезная нагрузка довольно проста. Я думаю, что небольшой размер строки делает этот подход меньшим, чем цикл, и легче сделать независимым от позиции таким образом.
e
Вbeep
повторах, так что я могу сбрить одинld a
. Кроме того , поскольку вся память между$0038
и$8000
обнуляется, я могу упасть через него и использовать более короткийrst
вариантcall
инструкции, которая работает только$0
,$8
,$10
и так далее, вплоть до$38
.Старые подходы
64 байта
58 байт
53 байта
У этого есть объяснение в истории редактирования, но оно не слишком отличается.
Что, если: любой непустой вывод был в порядке вместо звукового сигнала
1 байт
halt
Если программа работает нормально, но если радиация удаляет ее, то память будет заполнена нулями, что будет$8000
выполнять бесконечное число раз, печатая много нулевых байтов.источник
a
начинается с нуля, вы не можете использоватьor a, (N);
вместоld a, (N); and a;
? Похоже, вы можете сохранить пару байтов таким образом.or a, (ix + N)
?20 19
в начале становится20 18
, а удаление20
создает безусловный переход назад, поэтому После первого перехода в программу необходимо добавить nop, полностью изменив сохранение байта.> <> , 23 байта
Попробуйте онлайн! Проверка.
Честно говоря, удивительно, как коротко я получил это. Заканчивается с ошибкой.
Версия без ошибок, 29 байт
Попробуйте онлайн!
источник
Кляйн , по одной топологии, всего 291 байт
Увидев ответ WW с использованием
001
топологии, я решил посмотреть, насколько сложно будет создать счетчик Гейгера для каждой топологии. (Спойлер: очень сложно. Трудно понять, куда пойдет указатель без жестов, которые заставляют меня выглядеть так, будто я выясняю, какая рука слева от меня)Проверка!
(Я также подумал о написании программы, которая является действительным счетчиком Гейгера для всех топологий, но, возможно, придется подождать. Если кто-то еще захочет попробовать, я предлагаю награду в 500 представителей)
000 и 010, 21 байт
Попробуйте 000 онлайн! и попробуйте 010 онлайн!
Это перенесено из моего
><>
решения . Это, очевидно, работает000
, так как это топология по умолчанию для большинства 2D-языков, но я был удивлен, что она также работает010
.001 и 011, 26 байтов
Попробуйте 001 онлайн! и попробуйте 011 онлайн!
Этот скопирован прямо из ответа WW . Благодарность!
100, 21 байт
Попробуйте онлайн!
101, 21 байт
Попробуйте онлайн!
110, 26 байт
Попробуйте онлайн!
111, 24 байта
Попробуйте онлайн!
200, 21 байт
Попробуйте онлайн!
201, 31 байт
Попробуйте онлайн!
Безусловно самый раздражающий.
210, 26 байт
Попробуйте онлайн!
211, 27 байт
Попробуйте онлайн!
Единственный, где мне приходилось справляться, входя в бипер через правую сторону.
источник
Самомодифицирующийся Brainfuck ,
144102 байтаНепечатные таблицы отображаются как escape-последовательность (например
\x01
).Проверка!
источник
Рунические чары , 29 байт
Попробуйте онлайн!
По сути то же самое, что ответ Klein 000 или> <> ответ (я начал с ответа Klein). Единственное действительно нужное изменение - это превращение
<
вL
и.
в(перевод символов команды), вставка точек входа IP (необходимо 2, в противном случае удаление приведет к некомпилируемой программе) и вставка команды dela
y
для получения два IP-адреса для объединения (таким образом, печатая только одинbeep
), опять же, нужно два. Также необходимо вставить дополнительные NOP, чтобы длина строк оставалась неизменной. Кляйн также удобно использовать@
для «печати и завершения».Отсутствует возможность использовать пробелы в левом нижнем углу, поскольку любые отражатели для изменения направления препятствуют обнаружению излучения. например (облучено 26 байт
y
):Не выводит выходные данные, поскольку изогнутый входной сегмент вызывает повторное отражение обратно в терминатор нижней линии.
источник
Befunge-93 , 55 байт
Попробуйте онлайн! Проверка!
Я надеялся получить его немного меньше, чем это, но
beep
узким местом является длина принтера.источник
Wumpus ,
37 34 3231 байтПопробуйте онлайн! Проверка!
Это решение использует тот факт, что
.
прыгает на позицию модуля длины программы.Альтернативно для того же количества байтов
Попробуйте онлайн! Проверка!
Этот использует разницу в направлении указателя для нечетных и четных длин строк. (Я не знаю, как на
"
самом деле работает первый, когда удаляется символ новой строки)источник
Кляйн (001), 26 байт
Попробуйте онлайн!
Проверьте!
объяснение
Эта программа использует уникальную топологию Кляйна, в частности, 001 топологию , которая представляет собой бутылку Klein.
Неотредактированная программа следует по пути выполнения:
Удаление байта из программы может повлиять на программу четырьмя способами (каждый в своем цвете):
Первое, на что стоит обратить внимание, это то, что
<<
в начале всегда будет отклоняться IP-адрес слева от источника. Если один из<
s удален, другой занимает его место. Таким образом, если какой-либо байт будет удален из красной секции, будет следовать следующий путь выполнения:Если синий байт удален, мы получаем очень простой путь:
Если новая строка удалена, мы получаем путь:
Желтый путь немного сложнее. Поскольку нижняя строка на один длиннее верхней строки, когда программа возводится в квадрат в начале выполнения, виртуальный символ добавляется в конец первой строки, чтобы сделать их одинакового размера. Если какой-либо байт во второй строке удален, строка укорачивается, и этот виртуальный символ не добавляется. Это важно, потому что
!
обычно перепрыгивает через виртуального персонажа, но/
вместо этого он перепрыгивает .источник
><>
решение000
на 21 байтBackhand ,
2521 байтПопробуйте онлайн! Проверка!
При этом используется способность Backhand изменять значение шага указателя, чтобы пропустить инструкцию на каждом шаге и аккуратно решить проблему избыточности. Затем он использует
j
команду, чтобы проверить, облучается ли код, переходя к последнему символу (@
, остановка), если нет, и переходя ко второму последнему (H
остановка и выходной стек), если так.источник