Одна из наиболее распространенных стандартных задач (особенно при демонстрации эзотерических языков программирования) - реализовать «программу cat» : прочитать весь STDIN и распечатать его в STDOUT. Хотя он назван в честь утилиты оболочки Unix, cat
он, конечно, намного менее мощный, чем реальная вещь, которая обычно используется для печати (и объединения) нескольких файлов, считанных с диска.
задача
Вы должны написать полную программу, которая считывает содержимое стандартного входного потока и записывает их дословно в стандартный выходной поток. Если и только если ваш язык не поддерживает стандартные потоки ввода и / или вывода (как это понимается в большинстве языков), вы можете вместо этого использовать эти термины для обозначения их ближайшего эквивалента на вашем языке (например, JavaScript prompt
и alert
). Это единственные допустимые формы ввода / вывода, поскольку любой другой интерфейс в значительной степени изменит характер задачи и сделает ответы гораздо менее сопоставимыми.
Вывод должен содержать именно вход и ничего больше . Единственным исключением из этого правила является постоянный вывод интерпретатора вашего языка, который не может быть подавлен, например приветствие, цветовые коды ANSI или отступы. Это также относится к трейлингу новых строк. Если входные данные не содержат завершающий символ новой строки, выходные данные также не должны включать его! (Единственное исключение - если ваш язык абсолютно всегда печатает завершающий символ новой строки после выполнения.)
Вывод в стандартный поток ошибок игнорируется, если стандартный поток вывода содержит ожидаемый вывод. В частности, это означает, что ваша программа может завершиться с ошибкой при достижении конца потока (EOF), при условии, что это не загрязняет стандартный поток вывода. Если вы сделаете это, я призываю вас добавить безошибочную версию в ваш ответ (для справки).
Поскольку это задание является вызовом для каждого языка, а не между языками, существует несколько правил для каждого языка:
- Если на вашем языке вообще возможно отличить нулевые байты в стандартном входном потоке от EOF, ваша программа должна поддерживать нулевые байты, как и любые другие байты (то есть они также должны быть записаны в стандартный выходной поток).
- Если на вашем языке вообще возможно поддерживать произвольный бесконечный поток ввода (т. Е. Если вы можете начать печатать байты на выходе до того, как нажмете EOF на входе), ваша программа должна работать правильно в этом случае. В качестве примера
yes | tr -d \\n | ./my_cat
следует вывести бесконечный потокy
s. Вам решать, как часто вы печатаете и очищаете стандартный поток вывода, но это должно гарантированно произойти через определенное время, независимо от потока (это означает, в частности, что вы не можете ждать определенного символа, такого как перевод строки перед печатью).
Пожалуйста, добавьте примечание к своему ответу о точном поведении относительно нулевых байтов, бесконечных потоков и посторонних выводов.
Дополнительные правила
Речь идет не о поиске языка с кратчайшим решением для этого (есть такие, где пустая программа делает свое дело) - речь идет о поиске кратчайшего решения в каждом языке. Поэтому ни один ответ не будет помечен как принятый.
Материалы на большинстве языков будут оцениваться в байтах в соответствующей существующей кодировке, обычно (но не обязательно) UTF-8.
Некоторые языки, такие как папки , немного сложнее оценить. Если вы сомневаетесь, пожалуйста, спросите на Meta .
Не стесняйтесь использовать язык (или языковую версию), даже если он более новый, чем этот вызов. Языки, специально написанные для предоставления 0-байтового ответа на этот вызов, являются честной игрой, но не особенно интересными.
Обратите внимание, что должен быть переводчик, чтобы представление можно было проверить. Разрешается (и даже поощряется) самостоятельно писать этот переводчик для ранее не реализованного языка.
Также обратите внимание , что языки действительно должны выполнять свои обычные критерии для языков программирования .
Если выбранный вами язык является тривиальным вариантом другого (потенциально более популярного) языка, у которого уже есть ответ (например, диалекты BASIC или SQL, оболочки Unix или тривиальные производные Brainfuck, такие как Headsecks или Unary), рассмотрите возможность добавления примечания к существующему ответу, который такое же или очень похожее решение также является самым коротким на другом языке.
Если они не были отменены ранее, применяются все стандартные правила игры в гольф , включая http://meta.codegolf.stackexchange.com/q/1061 .
В качестве примечания, пожалуйста, не понижайте скучные (но действительные) ответы на языках, где не так много в гольфе; они все еще полезны для этого вопроса, так как он пытается собрать каталог настолько полно, насколько это возможно. Тем не менее, делайте в первую очередь upvote ответы на языках, где автор фактически должен был приложить усилия для игры в гольф.
Каталог
Фрагмент стека в нижней части этого поста создает каталог из ответов а) в виде списка кратчайшего решения для каждого языка и б) в качестве общей таблицы лидеров.
Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:
## Language Name, N bytes
где N
размер вашего представления. Если вы улучшите свой счет, вы можете сохранить старые результаты в заголовке, вычеркнув их. Например:
## Ruby, <s>104</s> <s>101</s> 96 bytes
Если вы хотите включить в заголовок несколько чисел (например, потому что ваш результат равен сумме двух файлов или вы хотите перечислить штрафы за флаг интерпретатора отдельно), убедитесь, что фактический результат является последним числом в заголовке:
## Perl, 43 + 2 (-p flag) = 45 bytes
Вы также можете сделать имя языка ссылкой, которая будет отображаться во фрагменте кода:
## [><>](http://esolangs.org/wiki/Fish), 121 bytes
cat
sh
ответ с использованиемcat
более короткого решенияdd
.)Ответы:
Сед, 0
Пустая
sed
программа делает именно то, что требуется здесь:источник
yes | tr -d \\n | sed ''
?yes
в один буфер шаблонов, пока не исчерпает память. Предостережение, я полагаю ...Ziim ,
222201196185182 байтаЭто, вероятно, не будет отображаться правильно в вашем браузере, поэтому вот схема кода:
Я не могу придумать более простую структуру для решения проблемы в Ziim, но я уверен, что реальный код все еще вполне пригоден для игры в гольф.
Ziim не может обрабатывать бесконечные потоки, потому что можно печатать только что-нибудь в конце программы.
объяснение
Поскольку у Ziim есть довольно уникальная декларативная модель потока управления, алгоритм псевдокода с императивным управлением здесь его не обрезает. Вместо этого я объясню основы Ziim и приведенную здесь приведенную в порядок структуру приведенного выше кода (аналогичным графическим образом) как искусство ASCII.
Поток управления в Ziim происходит повсеместно: каждая стрелка, на которую не указывает другая стрелка, инициализирует «поток», который обрабатывается независимо от других (на самом деле не параллельно, но нет никаких гарантий, в каком порядке они обрабатываются , если вы не синхронизируете их через конкатенацию). Каждый такой поток содержит список двоичных цифр, начиная с
{0}
. Теперь каждая стрелка в коде - это какая-то команда, которая имеет один или два входа и один или два выхода. Точная команда зависит от того, сколько стрелок указывает на нее, из какой ориентации.Вот список команд, где
m -> n
указывает, что команда принимаетm
входные данные и производитn
выходные данные.1 -> 1
, no-op : просто перенаправляет поток.1 -> 1
, инвертировать : отменяет каждый бит в потоке (а также перенаправляет его).1 -> 1
, прочитайте : заменяет значение потока следующим битом из STDIN или пустым списком, если мы нажали EOF.2 -> 1
, concatenate : это единственный способ синхронизировать потоки. Когда нить коснется одной стороны стрелки, она будет приостановлена, пока другая нить не коснется другой стороны. В этот момент они будут объединены в один поток и продолжат выполнение.2 -> 1
, label : это единственный способ объединить разные пути выполнения. Это просто неоперативный, который имеет два возможных входа. Таким образом, потоки, входящие в «метку» по любому из маршрутов, будут просто перенаправлены в одном направлении.1 -> 2
, split : берет один поток и отправляет две копии в разных направлениях.1 -> 1
, IsZero? : потребляет первый бит потока и отправляет поток в одном из двух направлений в зависимости от того, был ли бит 0 или 1.1 -> 1
, пусто? : использует весь список (т.е. заменяет его пустым списком) и отправляет поток в одном из двух направлений в зависимости от того, был ли список уже пустым или нет.Итак, имея это в виду, мы можем выработать общую стратегию. Используя concatenate, мы хотим многократно добавлять новые биты в строку, которая представляет весь ввод. Мы можем просто сделать это, зациклив выходные данные конкатенации обратно на один из ее входов (и мы инициализируем это пустым списком, очистив a
{0}
с помощью isEmpty? ). Вопрос в том, как мы можем прекратить этот процесс.Помимо добавления текущего бита, мы также добавим 0 или 1, указывающие, достигли ли мы EOF. Если мы отправим нашу строку через isZero? , он снова избавится от этого бита, но давайте выделим конец потока, и в этом случае мы просто позволим потоку покинуть край сетки (что заставляет Ziim печатать содержимое потока в STDOUT и завершать программу) ,
Достигли ли мы EOF или нет, можно определить с помощью isEmpty? на копии ввода.
Вот схема, которую я обещал:
Некоторые заметки о том, с чего начать чтение:
{0}
верхнем левом углу находится начальный триггер, который запускает цикл ввода.{0}
К верхнему правому углу немедленно сбрасывается в пустой список представляет собой исходную строку , которую мы будем постепенно заполнять с входом.{0}
s подаются в цикл «производитель» (один перевернутый, другой - нет), чтобы дать нам неограниченное количество0
s и1
s, которые нам нужно добавить к строке.источник
Гексагония , 6 байт
Раньше это было 3 байта (см. Ниже), но эта версия больше не работает с момента последнего обновления языка. Поскольку я никогда не вносил преднамеренно ошибку, которую использовала версия, я решил не считать ее.
Безошибочное решение (то есть, которое работает с фиксированным интерпретатором) оказывается намного хитрее. У меня были некоторые проблемы, когда я втиснул его в сетку 2x2, но я нашел одно решение сейчас, хотя мне нужны полные 7 байтов :
После разворачивания получаем:
Поскольку начальный край памяти равен 0,
<
безоговорочно отклоняет указатель команд на северо-восточную диагональ, где он переносится на серый путь. Это.
неоперация. Теперь,
читает байт,)
увеличивает его так, чтобы действительные байты (включая нулевые байты) были положительными, а EOF - 0.Таким образом, на EOF, IP переносится на красный путь, где
@
завершается программа. Но если мы по-прежнему читаем байт, то IP оборачивается зеленым путем, а вместо этого(
уменьшает грань до исходного значения, прежде чем;
печатать его в STDOUT. IP теперь безоговорочно возвращается к серому пути, повторяя процесс.После написания сценария грубой силы для моего ответа Truth Machine я настроил его на поиск безошибочного 6-байтового решения для программы cat. Удивительно, но он нашел одно - да, точно одно решение во всех возможных 6-байтовых программах Hexagony. После 50 решений от машины правды это было довольно удивительно. Вот код:
Раскладывание:
Использование
~
(унарное отрицание) вместо()
интересного, потому что а) это неоперация на нуле, б) она меняет стороны ветки, в) в некоторых кодах один~
может быть использован дважды для отмены операции с самой собой , Итак, вот что происходит:В первый раз (фиолетовый путь) мы проходим через
~
это без операции./
Отражает IP в Северо-Запада по диагонали. Серый путь теперь читает символ и умножает его код символа на-1
. Это превращает EOF (-1
) в истинное (положительное) значение, а все действительные символы в ложные (не положительные) значения. В случае EOF IP получает красный путь, и код завершается. В случае действительного символа, IP~
выбирает зеленый путь, где отменяет отрицание и;
печатает символ. Повторение.Наконец, вот 3-байтовая версия, которая использовалась в оригинальной версии интерпретатора Hexagony.
Как и в случае с ответом Лабиринт, это заканчивается ошибкой, если входной поток конечен.
После развертывания кода он соответствует следующей шестнадцатеричной сетке:
.
Нет-OPS. Казнь начинается на фиолетовой дорожке.,
читает байт,;
пишет байт. Затем выполнение продолжается на пути лосося (ish?). Нам нужно&
сбросить текущий край памяти на ноль, так что IP-адрес переходит обратно к фиолетовому ряду при попадании в угол в конце второго ряда. Как только,
нажмете EOF, он вернется-1
, что приведет к ошибке при;
попытке его распечатать.Диаграммы, созданные с помощью удивительного HexagonyColorer Тимви .
источник
TeaScript , 0 байт
TeaScript - это лаконичный язык игры в гольф, скомпилированный для JavaScript
В недавнем обновлении ввод неявно добавляется как первое свойство.
Попробуйте онлайн
В качестве альтернативы 1 байт
x
содержит входные данные в TeaScript. Вывод неявныйисточник
Брайан и Чак , 44 байта
Первоначально я создал этот язык для создания языка программирования, который кажется непригодным для использования . Оказывается, это очень хорошее упражнение для решения простых проблем в гольфе.
Основы: Каждая из двух строк определяет программу, похожую на Brainfuck, которая работает с исходным кодом другой программы - первая программа называется Brian, а вторая - Chuck. Только Брайан может читать, и только Чак может писать. Вместо циклов Brainfuck у вас есть
?
управление , которое передает управление другой программе (также меняются роли указателя инструкций и заголовка ленты). В дополнение к Brainfuck есть{
и то,}
что сканирует ленту на наличие первой ненулевой ячейки (или левого конца). Также_
заменяются нулевыми байтами.Хотя я не думаю, что это оптимально, я вполне доволен этим решением. Моя первая попытка была 84 байта, и после нескольких сессий игры в гольф с Sp3000 (и, черпая вдохновение из его попыток), мне удалось медленно уменьшить его до 44, по несколько байтов за раз. Особенно блестящей
+}+
уловкой была его идея (см. Ниже).объяснение
Входные данные считываются в первую ячейку на ленте Чака, затем тщательно копируются в конец ленты Брайана, где она печатается. Копируя его до конца, мы можем сохранить байты, установив предыдущий символ в ноль.
Это
#
просто заполнитель, потому что управление переключением не выполняет ячейку, которую мы включили.{<{
гарантирует, что головка ленты находится на первой ячейке Чака.,
читает байт из STDIN или-1
если мы нажмем EOF. Таким образом, мы увеличиваем это с,+
чтобы сделать его нулевым для EOF и ненулевым в противном случае.Давайте пока предположим, что мы еще не в EOF. Таким образом, ячейка положительна и
?
переключит контроль на Чака.}>
перемещает головку магнитофона (на Брайана)+
в_
и?
передает управление обратно Брайану.{-
теперь уменьшает первую ячейку Чака. Если это еще не ноль, мы снова передаем контроль Чаку?
. На этот раз}>
перемещает головку ленты Брайана на две ячейки справа от последней ненулевой ячейки. Изначально это здесь:Но позже у нас уже будут некоторые персонажи. Например, если мы уже прочитали и напечатали
abc
, то это будет выглядеть так:Где
1
s на самом деле 1 байт (мы увидим, что это будет позже).Эта ячейка всегда будет нулевой, поэтому на этот раз контроль
?
не изменится.>
перемещает еще одну ячейку вправо и+
увеличивает эту ячейку. Вот почему первый символ на входе заканчивается тремя ячейками справа от?
(и каждый последующий - на три ячейки справа).<<<
возвращается к последнему символу в этом списке (или,?
если это первый символ), и{>
возвращается к+
ленте Брайана, чтобы повторить цикл, который медленно переносит входную ячейку на конец ленты Брайана.Когда эта входная ячейка пуста,
?
после{-
больше не будет переключать управление. Затем>}<
перемещает головку ленты на Чака_
и переключает управление так, чтобы вместо него выполнялась вторая половина Чака.}>>
перемещается в ячейку, которую мы сейчас записали, после конца ленты Брайана, который является байтом, который мы прочитали из STDIN, поэтому мы печатаем его обратно.
. Для того , чтобы}
пробежать мимо этого нового символа на ленте , мы должны ликвидировать разрыв двух нулевых байтов, поэтому мы увеличиваем их1
с<+<+
(так вот почему есть 1-байт между фактическими символами на финальной ленте). Наконец,{<{
возвращается к началу ленты Брайана и?
начинает все с начала.Вы можете задаться вопросом, что произойдет, если символ, который мы прочитали, был нулевым байтом. В этом случае вновь записанная ячейка сама по себе будет равна нулю, но, поскольку она находится в конце ленты Брайана, и нам все равно, где этот конец, мы можем просто игнорировать это. Это означает, что если бы ввод был
ab\0de
, то лента Брайана в конечном итоге выглядела бы так:Наконец, как только мы нажмем EOF, первым
?
на ленте Брайана будет запрет. На этом этапе мы прекращаем программу. Наивное решение было бы перейти к концу ленты и переключателю управления Чаком, таким образом, что программы termiantes:>}>}<?
. Вот где действительно умная идея Sp3000 экономит три байта:+
превращает первую ячейку Чака в1
. Это означает, что}
имеет отправную точку и находит_
в середине ленты Чака. Вместо того, чтобы пропускать его, мы просто закрываем пробел, превращая его также в1
с+
. Теперь давайте посмотрим, что происходит с остальным кодом Брайана с этим модифицированным Чаком ...{
возвращается к первой ячейке Чака как обычно и-
превращает ее обратно в нулевой байт. Это означает, что?
это неоперация. Но теперь>}<
, который обычно перемещает головку ленты к середине ленты Чака, перемещается прямо за ней до конца ленты Чака и?
затем передает управление Чаку, завершая код. Приятно, когда все получается ... :)источник
Haskell, 16 байт
interact
читает входные данные, передает их функции, указанной в качестве аргумента, и печатает полученный результат.id
является функцией тождества, т.е. она возвращает свой ввод без изменений. Благодаря лени Хаскеллаinteract
можно работать с бесконечным вводом.источник
sh + binutils,
32 байтаНу, не так очевидно. От @ Random832
Оригинал:
Больно очевидно ...: D
источник
dd
.cat
???Funciton , 16 байт
(Закодировано как UTF-16 с спецификацией)
объяснение
Ящик возвращает содержимое STDIN. Свободный конец выводит его.
источник
Motorola MC14500B Машинный код , 1,5 байта
Написано в шестнадцатеричном формате:
Написано в двоичном виде:
объяснение
Операционные коды имеют 4 бита каждый.
источник
Морнингтон Полумесяц , 41 байт
Я понятия не имею, может ли Mornington Crescent обрабатывать нулевые байты, и весь ввод читается перед запуском программы, так как это является природой языка.
источник
Brainfuck, 5 байтов
Эквивалент псевдокоду:
Это обрабатывает бесконечные потоки, но обрабатывает нулевые байты как EOF. То, может ли BF правильно обрабатывать нулевые байты, варьируется от реализации к реализации, но это предполагает наиболее распространенный подход.
источник
+[,.]
правильно?Лабиринт , 2 байта
Если поток конечен, он завершится с ошибкой, но все выходные данные, полученные с ошибкой, поступают в STDERR, поэтому стандартный поток вывода является правильным.
Как в Brainfuck
,
читает байт (помещая его в основной стек Лабиринта) и.
записывает байт (извлекая его из основного стека Лабиринта).Причина, по которой этот цикл повторяется, заключается в том, что оба
,
и.
являются "тупиками" в (очень тривиальном) лабиринте, представленном исходным кодом, так что указатель команды просто поворачивается на месте и возвращается к другой команде.Когда мы нажимаем EOF, вместо этого
,
нажимает-1
и.
выдает ошибку, потому что-1
это недопустимый код символа. Это может измениться в будущем, но я еще не решил это.Для справки, мы можем решить это без ошибки в 6 байтов следующим образом
Здесь
)
увеличивается байт, который мы читаем, что дает0
EOF и что-то положительное в противном случае. Если значение равно0
, IP движется прямо, нажимая на тот,@
который завершает программу. Если значение было положительным, IP вместо этого повернет направо в сторону,(
которая уменьшает вершину стека до ее первоначального значения. IP-адрес теперь находится в углу и будет просто поворачивать направо, печатать с помощью.
, читать новый байт.
, прежде чем он)
снова попадет на развилку .источник
C, 40 байтов
источник
getchar
возвращает -1 , поэтому ваш код будет печатать бесконечный поток байтов 0xFF после (конечного) ввода.> <> , 7 байт
Попробуй это здесь . Объяснение:
Если вы хотите, чтобы продолжать идти , пока вы не дадите ему больше входного сигнала, замените
;
с!
.источник
io
(2 байта) делает то же самое, но вылетает и записываетsomething smells fishy...
в STDERR в конце выполнения, что разрешено.Сборка X86, 70 байт
Разборка с помощью
objdump
:Источник:
источник
objdump
разберите его как 32-битный код, в то время как вы, кажется, скомпилировали как 16-битный. Во что верить? Поскольку вы используетеint 0x80
, я думаю, что это предназначено для Linux, но зачем тогда компилировать как 16-битные?Универсальная лямбда , 1 байт
Универсальная лямбда-программа - это кодирование лямбда-термина в двоичном виде, разбитое на куски по 8 битов, заполнение неполных кусков любыми битами, преобразованными в поток байтов.
Биты переводятся в лямбда-термин следующим образом:
00
вводит лямбда-абстракцию.01
представляет собой применение двух последующих условий.111..10
с n повторениями бита1
относится к переменной n- й родительской лямбды; то есть это индекс Де Брюина в унарном.Под этим преобразованием понимается
0010
функция идентификацииλa.a
, что означает, что любая однобайтовая программа в форме0010xxxx
являетсяcat
программой.источник
!
это0x21
, не0x4_
?PowerShell,
884130 байтРЕДАКТИРОВАТЬ - забыл, что я могу использовать
$input
автоматическую переменную для ввода конвейера ... EDIT2 - не нужно проверять наличие$input
Да, так ... STDIN в PowerShell ... странно, скажем так. Предполагая, что нам нужно принимать входные данные от всех типов STDIN, это один из возможных ответов на этот каталог, и я уверен, что есть и другие. 1
Однако конвейерный ввод в PowerShell не работает так, как вы думаете. Поскольку трубопроводы в PowerShell является функцией языка, а не функцией окружающей среды / оболочки (и PowerShell на самом деле не только язык , во всяком случае), есть некоторые странности в поведении.
Для начинающих, и наиболее подходящих для этой записи, труба не оценивается мгновенно (большую часть времени). То есть, если мы имеем
command1 | command2 | command3
в нашей оболочке,command2
мы не будем принимать ввод или начинать обработку до тех пор, пока не завершимcommand1
... если вы не инкапсулируете свойcommand1
сForEach-Object
..., который отличается отForEach
. (хотяForEach
это псевдоним дляForEach-Object
, но это отдельная проблема, так как я говорюForEach
как утверждение, а не псевдоним)Это будет означать, что что-то вроде
yes | .\simple-cat-program.ps1
(хотя наyes
самом деле не существует, но что угодно) не будет работать, потомуyes
что никогда не завершится. Если бы мы могли сделатьForEach-Object -InputObject(yes) | .\simple-cat-program.ps1
это, должно (в теории) работать.Знакомство с ForEach и ForEach-Object в Microsoft "Эй, сценарист!" блог.
Итак, все эти параграфы объясняют, почему
if($input){$input}
существует. Мы берем входной параметр, который специально создается автоматически, если присутствует конвейерный ввод, проверяем, существует ли он, и, если да, выводим его.Затем мы получаем ввод от пользователя
(read-host)
через отдельный поток STDIN иwrite-host
возвращаем его обратно с-n
флагом (сокращенно-NoNewLine
). Обратите внимание, что это не поддерживает ввод произвольной длины, посколькуread-host
завершится только при вводе перевода строки (технически, когда пользователь нажимает «Enter», но функционально эквивалентен).Уф.
+1 Но есть и другие варианты:
Например, если мы занимались только конвейерным вводом, и нам не требовалась полная программа, вы могли бы сделать что-то подобное,
| $_
что бы просто выводить то, что было введено. (В общем, это несколько избыточно, поскольку PowerShell имеет неявный вывод вещей, «оставленных позади» после вычислений, но это в стороне.)Если нас интересует только интерактивный пользовательский ввод, мы могли бы использовать только
write-host(read-host)-n
.Кроме того, эта функция имеетгалтельособенность приема входных данных из командной строки, например ,.\simple-cat-program.ps1 "test"
будет заполнить (и затем выход) в$a
переменном.источник
Cubix ,
65 байтовТеперь обрабатывает нулевые байты!
Cubix - это двумерный esolang на основе стека. Cubix отличается от других двумерных языков тем, что исходный код обернут снаружи куба.
Проверьте это онлайн! Примечание: между итерациями задержка составляет 50 мс.
объяснение
Первое, что делает интерпретатор, это вычисляет наименьший куб, на который поместится код. В этом случае длина ребра равна 1. Затем код дополняется без операций,
.
пока все шесть сторон не будут заполнены. Пробелы удаляются перед обработкой, поэтому этот код идентичен приведенному выше:Теперь код запускается. IP (указатель инструкций) начинается с крайней левой грани, указывая на восток.
Первый символ, с которым сталкивается IP
_
, - это зеркало, которое переворачивает IP, если он обращен на север или юг; в настоящее время он смотрит на восток, так что это ничего не делает. Далее идетi
ввод байта из STDIN.?
поворачивает IP влево, если верхний элемент отрицательный, или вправо, если положительный. Здесь есть три возможных пути:@
, что завершает программу.o
._
. Это переворачивает его, отправляя обратно в?
, который снова поворачивает вправо и выводит байт.Я считаю эту программу оптимальной. Прежде чем Cubix смог обработать нулевые байты (EOF был 0, а не -1), эта программа работала для всего, кроме нулевых байтов:
Я написал брутфорсер, чтобы найти все 5-байтовые программы для кошек. Хотя для завершения требуется ~ 5 минут, в последней версии найдено 5 программ:
источник
Витси, 2 байта
z
получает весь входной стек и помещает его в стек активной программы.Z
распечатывает весь активный стек в STDOUT.Альтернативный метод:
источник
MarioLANG , 11 байт
Я не совсем уверен, что это оптимально, но это самое короткое, что я нашел.
Это поддерживает бесконечные потоки и завершится с ошибкой при достижении EOF (по крайней мере, эталонная реализация Ruby делает).
Есть еще одна версия, которая превращает Марио в ниндзя, который может дважды прыгать:
В любом случае, Марио начинает падать вниз в левую колонку, где
,
читает байт и.
записывает байт (который выдает ошибку в EOF, потому,
что не возвращает действительный символ).>
гарантирует, что Марио идет направо (=
это просто площадка для него). Затем он движется вверх, либо двойным прыжком с^
лифтом ("
или#
парой) , либо через него, прежде чем он<
скажет ему вернуться в левую колонку.источник
RS , 0 байт
Шутки в сторону. rs просто печатает все, что получает, если данный скрипт полностью пуст.
источник
GolfScript, 3 байта
Пустая программа повторяет стандартный ввод. Язык не может обрабатывать бесконечные потоки. Тем не менее, он добавляет новую строку, как упоминал @Dennis. Это делается путем оборачивания всего стека в массив и вызова
puts
, который определяется какprint n print
, гдеn
находится символ новой строки. Тем не менее, мы можем переопределитьn
STDIN, а затем очистить стек, что и:n;
делает.источник
Полуразбитая машина в интенсивном движении , 9 + 3 = 12 байт
Половина разбитой машины при интенсивном движении (HBCHT) принимает входные данные в качестве аргументов командной строки, поэтому запускайте как
Обратите внимание, что +3 для
-s
флага, который выводит как символы. Кроме того, HBCHT, по-видимому, не обрабатывает NUL, поскольку все нули удаляются из выходных данных (например97 0 98
, выводятся в виде двух символовab
).объяснение
В HBCHT ваша машина начинается с,
o
и ваша цель - выход#
.^>v<
направлять движение автомобиля, одновременно изменяя BF-подобную ленту (^>v<
перевод на+>-<
). Однако, как следует из названия языка, ваш автомобиль может поворачивать только вправо - любые попытки повернуть налево полностью игнорируются (включая их эффекты памяти). Обратите внимание, что это только для поворота - ваш автомобиль отлично способен двигаться вперед / назад.Другие интересные детали о HBCHT - это то, что начальное направление вашего автомобиля рандомизировано, а сетка тороидальная. Таким образом, нам просто нужна машина, чтобы доехать до выхода, не изменяя ленту для всех четырех начальных направлений:
Вверх и вниз прямолинейны, направляясь прямо к выходу.
Для левого мы обертываем и выполняем
<
и увеличиваем с^
. В следующий раз мы не можем повернуть налево,<
поэтому мы оборачиваемся и уменьшаемv
, отменяя предыдущий прирост. Поскольку мы движемся вниз, теперь мы можем повернуть направо на<
выходе и выйти, дважды переместив указатель и не изменив значения ячеек.Для правого мы делаем то же самое, что и левый, но пропускаем первый,
^
так как мы не можем повернуть налево.Редактировать : Оказывается, что интерпретатор HBCHT позволяет вам выполнить только один путь через флаг командной строки, например
Тем не менее, флаг не только слишком дорогой для этого конкретного вопроса (по крайней мере, 5 байт
" -d u"
), но кажется, что все пути все еще должны иметь возможность пройти его до выхода для выполнения кода.источник
Минколанг , 5 байт
Попробуй это здесь.
объяснение
o
читает символ из ввода и помещает его ASCII-код в стек (0
если ввод пуст).d
затем дублирует вершину стека (символ, который был только что прочитан).?
является условным батутом, в который не попадает следующая инструкция вершины стека0
. Если вход был пустым, то.
он не перескочил и программа остановилась. В противном случаеO
выводит вершину стека как символ. Тороидальная природа Минколанга означает, что это происходит в начале.источник
INTERCALL , 133 байта
Wat
источник
500
(не уверен), было быPRINT D
, верно? (исключая заголовок)PUSH XX<newline>PRINT
илиPUSH XX AND PRINT
. О, и я создатель INTERCALLV , 0 байтов
Попробуйте онлайн!
Идея V о «памяти» - это просто гигантский двумерный массив символов. Перед запуском любой программы все входные данные загружаются в этот массив (известный как «Буфер»). Затем в конце любой программы печатается весь текст в буфере.
Другими словами, пустая программа - это программа cat.
источник
Снеговик 1.0.2 , 15 символов
Взято прямо из
examples
каталога Снеговика . Читает строку, печатает строку, читает строку, печатает строку ...Обратите внимание, что из-за деталей реализации, когда STDIN пуст,
vg
вернет то же самое, что и для пустой строки. Следовательно, это будет многократно печатать переводы строк в бесконечном цикле после закрытия STDIN. Это может быть исправлено в будущей версии.Пояснение к коду:
источник
FireType , 7 байт
Требуются некоторые изменения, которые я только что подтолкнул . Правила говорят:
так что я в чистоте!
источник
Деление , 4 байта
Разве это не приятно, когда вы обыгрываете примеры программ в собственном репозитории языка? :) Для справки, он имеет 7-байтовое решение
объяснение
Итак,
R
запускает поток управления с правым атомом.?
читает символ из STDIN в массу атома. До тех пор, пока мы читаем символы, энергия остается нулевой, поэтомуJ
UMP не работает и!
печатает символ. Атом возвращается к началу (R
теперь не работает) и повторяет весь процесс.Когда мы нажмем EOF,
?
установим для энергии атома значение1
, поэтомуJ
теперь ump пропустит команду печати. Но когда атом попадает?
после того, как EOF уже был возвращен, он вместо этого уничтожит атом, что завершит программу.(Решение от автора языка использует явное
;
завершение программы, которое в0
противном случае пропускается двумя -порталами.)источник
Штрипед , 20 байт
Это нагло демонстрирует, что почти любая печатная строка ASCII является допустимым идентификатором в Shtriped.
Как это устроено:
Нет реального способа обнаружить EOF, так что это цикл навсегда, как в ответе Python .
Вы можете легко остановить его, если дана пустая строка (30 байт):
Обратите внимание, что Shtriped I / O поддерживает только печатный ASCII , вкладки, переводы строк, возврат каретки, вертикальные вкладки и переводы форм (всего 100 символов). Это связано с тем, что внутренне строки представляются как неотрицательные целые числа произвольной точности, и должен быть конечный алфавит символов, чтобы иметь возможность кодировать все строки.
источник