Простая кошачья программа


84

Одна из наиболее распространенных стандартных задач (особенно при демонстрации эзотерических языков программирования) - реализовать «программу cat» : прочитать весь STDIN и распечатать его в STDOUT. Хотя он назван в честь утилиты оболочки Unix, catон, конечно, намного менее мощный, чем реальная вещь, которая обычно используется для печати (и объединения) нескольких файлов, считанных с диска.

задача

Вы должны написать полную программу, которая считывает содержимое стандартного входного потока и записывает их дословно в стандартный выходной поток. Если и только если ваш язык не поддерживает стандартные потоки ввода и / или вывода (как это понимается в большинстве языков), вы можете вместо этого использовать эти термины для обозначения их ближайшего эквивалента на вашем языке (например, JavaScript promptи alert). Это единственные допустимые формы ввода / вывода, поскольку любой другой интерфейс в значительной степени изменит характер задачи и сделает ответы гораздо менее сопоставимыми.

Вывод должен содержать именно вход и ничего больше . Единственным исключением из этого правила является постоянный вывод интерпретатора вашего языка, который не может быть подавлен, например приветствие, цветовые коды ANSI или отступы. Это также относится к трейлингу новых строк. Если входные данные не содержат завершающий символ новой строки, выходные данные также не должны включать его! (Единственное исключение - если ваш язык абсолютно всегда печатает завершающий символ новой строки после выполнения.)

Вывод в стандартный поток ошибок игнорируется, если стандартный поток вывода содержит ожидаемый вывод. В частности, это означает, что ваша программа может завершиться с ошибкой при достижении конца потока (EOF), при условии, что это не загрязняет стандартный поток вывода. Если вы сделаете это, я призываю вас добавить безошибочную версию в ваш ответ (для справки).

Поскольку это задание является вызовом для каждого языка, а не между языками, существует несколько правил для каждого языка:

  • Если на вашем языке вообще возможно отличить нулевые байты в стандартном входном потоке от EOF, ваша программа должна поддерживать нулевые байты, как и любые другие байты (то есть они также должны быть записаны в стандартный выходной поток).
  • Если на вашем языке вообще возможно поддерживать произвольный бесконечный поток ввода (т. Е. Если вы можете начать печатать байты на выходе до того, как нажмете EOF на входе), ваша программа должна работать правильно в этом случае. В качестве примера yes | tr -d \\n | ./my_catследует вывести бесконечный поток ys. Вам решать, как часто вы печатаете и очищаете стандартный поток вывода, но это должно гарантированно произойти через определенное время, независимо от потока (это означает, в частности, что вы не можете ждать определенного символа, такого как перевод строки перед печатью).

Пожалуйста, добавьте примечание к своему ответу о точном поведении относительно нулевых байтов, бесконечных потоков и посторонних выводов.

Дополнительные правила

  • Речь идет не о поиске языка с кратчайшим решением для этого (есть такие, где пустая программа делает свое дело) - речь идет о поиске кратчайшего решения в каждом языке. Поэтому ни один ответ не будет помечен как принятый.

  • Материалы на большинстве языков будут оцениваться в байтах в соответствующей существующей кодировке, обычно (но не обязательно) 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


52
Баш, 3 байта :cat
TheDoctor

3
@TheDoctor Я думаю, это попадет в правило «не используйте встроенную функцию, которая делает именно то, что нужно».
Паŭло Эберманн

5
@ PaŭloEbermann Нет такого правила, и соответствующая стандартная лазейка больше не принимается. (На самом деле, уже есть shответ с использованием catболее короткого решения dd.)
Мартин Эндер,

1
Если только он использовал стандартные методы ввода и вывода: ///, 0 байт .
Товарищ SparklePony

1
@SparklePony За исключением того, что вы должны избегать слеш и обратный слеш.
Мартин Эндер

Ответы:


73

Сед, 0


Пустая sedпрограмма делает именно то, что требуется здесь:

$ printf "abc\ndef" | sed ''
abc
def$ 

3
Что произойдет, если кто-то пишет yes | tr -d \\n | sed ''?
Бен Голдберг

@BenGoldberg По умолчанию sed работает отдельно для каждой строки, поэтому в этом случае он будет продолжать класть их yesв один буфер шаблонов, пока не исчерпает память. Предостережение, я полагаю ...
Цифровая травма

POSIX предписывает, чтобы пространство шаблонов имело размер не менее 8192 байтов, IIRC. Я знаю, что реализация GNU имеет динамическое пространство шаблонов, ограниченное только доступной памятью, так что вы достаточно безопасны в этом.
Тоби Спейт

59

Ziim , 222 201 196 185 182 байта

    ↓ ↓

 ↓ ↓     ↓
 ↗ ↗↙↔↘↖ ↖
 ↓↓⤡⤢  ⤢↙
↘ ↖⤡ ↖
  ↙
  ↕↘ ↑ ↙
→↘↖↑ ↙ ↑
→↖   ↑
→↖↘ ↙
  ↑↓↑

   ⤡

Это, вероятно, не будет отображаться правильно в вашем браузере, поэтому вот схема кода:

введите описание изображения здесь

Я не могу придумать более простую структуру для решения проблемы в 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} --> isEmpty --> label <--+
              |                            |                    n    |      |
              v                            |                         v      |
    {0} --> label --> read --> split --> split ------------------> concat   |
                                 |                                   |      |
                           n     v     y                             |      |
 inv --> label --> concat <-- isEmpty --> concat <-- label <-- {0}   |      |
  ^        ^          |                     |          ^             |      |
  |        |          v                     v          |             |      |
 {0}       +------- split ---> label <--- split -------+             |      |
                                 |                                   |      |
                                 +-------------> concat <------------+      |
                                                   |                        |
                                              y    v                        |
                         print and terminate <-- isZero --------------------+

Некоторые заметки о том, с чего начать чтение:

  • В {0}верхнем левом углу находится начальный триггер, который запускает цикл ввода.
  • {0}К верхнему правому углу немедленно сбрасывается в пустой список представляет собой исходную строку , которую мы будем постепенно заполнять с входом.
  • Два других {0}s подаются в цикл «производитель» (один перевернутый, другой - нет), чтобы дать нам неограниченное количество 0s и 1s, которые нам нужно добавить к строке.

29
Как вы можете написать такую ​​программу, если ваш мозг не взорвется на миллион маленьких кусочков ткани.
Эшвин Гупта

40

Гексагония , 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 Тимви .


2
6-байтовая версия очень, очень умная. Брутфорсеры могут быть невероятно крутыми.
ETHproductions

У вас есть ссылка на вашего брутфорсера?
MD XF

@MDXF Я не держу различные версии, но это всегда некоторая модификация этого сценария Ruby .
Мартин Эндер

36

TeaScript , 0 байт

TeaScript - это лаконичный язык игры в гольф, скомпилированный для JavaScript


В недавнем обновлении ввод неявно добавляется как первое свойство.

Попробуйте онлайн


В качестве альтернативы 1 байт

x

xсодержит входные данные в TeaScript. Вывод неявный


Я собирался опубликовать это :)
Kritixi Lithos

5
Ха, я думал, что «В качестве альтернативы» было название языка ...
Quelklef

28

Брайан и Чак , 44 байта

#{<{,+?+}_+{-?>}<?
_}>?>+<<<{>?_}>>.<+<+{<{?

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

Основы: Каждая из двух строк определяет программу, похожую на Brainfuck, которая работает с исходным кодом другой программы - первая программа называется Brian, а вторая - Chuck. Только Брайан может читать, и только Чак может писать. Вместо циклов Brainfuck у вас есть ?управление , которое передает управление другой программе (также меняются роли указателя инструкций и заголовка ленты). В дополнение к Brainfuck есть {и то, }что сканирует ленту на наличие первой ненулевой ячейки (или левого конца). Также _заменяются нулевыми байтами.

Хотя я не думаю, что это оптимально, я вполне доволен этим решением. Моя первая попытка была 84 байта, и после нескольких сессий игры в гольф с Sp3000 (и, черпая вдохновение из его попыток), мне удалось медленно уменьшить его до 44, по несколько байтов за раз. Особенно блестящей +}+уловкой была его идея (см. Ниже).

объяснение

Входные данные считываются в первую ячейку на ленте Чака, затем тщательно копируются в конец ленты Брайана, где она печатается. Копируя его до конца, мы можем сохранить байты, установив предыдущий символ в ноль.

Это #просто заполнитель, потому что управление переключением не выполняет ячейку, которую мы включили. {<{гарантирует, что головка ленты находится на первой ячейке Чака. ,читает байт из STDIN или -1если мы нажмем EOF. Таким образом, мы увеличиваем это с, +чтобы сделать его нулевым для EOF и ненулевым в противном случае.

Давайте пока предположим, что мы еще не в EOF. Таким образом, ячейка положительна и ?переключит контроль на Чака. }>перемещает головку магнитофона (на Брайана) +в _и ?передает управление обратно Брайану.

{-теперь уменьшает первую ячейку Чака. Если это еще не ноль, мы снова передаем контроль Чаку ?. На этот раз }>перемещает головку ленты Брайана на две ячейки справа от последней ненулевой ячейки. Изначально это здесь:

#{<{,+?+}_+{-?>}<?__
                   ^

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

#{<{,+?+}_+{-?>}<?11a11b11c__
                            ^

Где 1s на самом деле 1 байт (мы увидим, что это будет позже).

Эта ячейка всегда будет нулевой, поэтому на этот раз контроль ? не изменится. >перемещает еще одну ячейку вправо и +увеличивает эту ячейку. Вот почему первый символ на входе заканчивается тремя ячейками справа от ?(и каждый последующий - на три ячейки справа).

<<<возвращается к последнему символу в этом списке (или, ?если это первый символ), и {>возвращается к +ленте Брайана, чтобы повторить цикл, который медленно переносит входную ячейку на конец ленты Брайана.

Когда эта входная ячейка пуста, ?после {-больше не будет переключать управление. Затем >}<перемещает головку ленты на Чака _и переключает управление так, чтобы вместо него выполнялась вторая половина Чака.

}>>перемещается в ячейку, которую мы сейчас записали, после конца ленты Брайана, который является байтом, который мы прочитали из STDIN, поэтому мы печатаем его обратно .. Для того , чтобы }пробежать мимо этого нового символа на ленте , мы должны ликвидировать разрыв двух нулевых байтов, поэтому мы увеличиваем их 1с <+<+(так вот почему есть 1-байт между фактическими символами на финальной ленте). Наконец, {<{возвращается к началу ленты Брайана и ?начинает все с начала.

Вы можете задаться вопросом, что произойдет, если символ, который мы прочитали, был нулевым байтом. В этом случае вновь записанная ячейка сама по себе будет равна нулю, но, поскольку она находится в конце ленты Брайана, и нам все равно, где этот конец, мы можем просто игнорировать это. Это означает, что если бы ввод был ab\0de, то лента Брайана в конечном итоге выглядела бы так:

#{<{,+?+}_+{-?>}<?11a11b1111d11e

Наконец, как только мы нажмем EOF, первым ?на ленте Брайана будет запрет. На этом этапе мы прекращаем программу. Наивное решение было бы перейти к концу ленты и переключателю управления Чаком, таким образом, что программы termiantes: >}>}<?. Вот где действительно умная идея Sp3000 экономит три байта:

+превращает первую ячейку Чака в 1. Это означает, что }имеет отправную точку и находит _в середине ленты Чака. Вместо того, чтобы пропускать его, мы просто закрываем пробел, превращая его также в 1с +. Теперь давайте посмотрим, что происходит с остальным кодом Брайана с этим модифицированным Чаком ...

{возвращается к первой ячейке Чака как обычно и -превращает ее обратно в нулевой байт. Это означает, что ?это неоперация. Но теперь >}<, который обычно перемещает головку ленты к середине ленты Чака, перемещается прямо за ней до конца ленты Чака и ?затем передает управление Чаку, завершая код. Приятно, когда все получается ... :)


25

Haskell, 16 байт

main=interact id

interactчитает входные данные, передает их функции, указанной в качестве аргумента, и печатает полученный результат. idявляется функцией тождества, т.е. она возвращает свой ввод без изменений. Благодаря лени Хаскелла interactможно работать с бесконечным вводом.


23

sh + binutils, 3 2 байта

dd

Ну, не так очевидно. От @ Random832

Оригинал:

cat

Больно очевидно ...: D


12
Я сделаю один лучше dd.
Random832 30.10.15

Я собирался сделать кошку ... D:
ev3commander

1
Да, это здорово и все ... но 170 повторений для набора текста cat???
MD XF

1
@MDXF а как насчет того, кто знает, сколько повторений из сегфо? ;)
Caird Coneheringaahing

23

Funciton , 16 байт

╔═╗
╚╤╝

(Закодировано как UTF-16 с спецификацией)

объяснение

Ящик возвращает содержимое STDIN. Свободный конец выводит его.


19

Motorola MC14500B Машинный код , 1,5 байта

Написано в шестнадцатеричном формате:

18F

Написано в двоичном виде:

0001 1000 1111

объяснение

1   Read from I/O pin
8   Output to I/O pin
F   Loop back to start

Операционные коды имеют 4 бита каждый.


1
-1 нет скриншота, пример или ссылка «Попробуй онлайн»: P (jk)
MD XF

2
+1. Единственный способ оптимизировать эту ситуацию - это просто припаять входной контакт к выходному контакту и вынуть микросхему из гнезда: P
Wossname

16

Морнингтон Полумесяц , 41 байт

Take Northern Line to Mornington Crescent

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


15

Brainfuck, 5 байтов

,[.,]

Эквивалент псевдокоду:

x = getchar()
while x != EOF:
    putchar(x)
    x = getchar()

Это обрабатывает бесконечные потоки, но обрабатывает нулевые байты как EOF. То, может ли BF правильно обрабатывать нулевые байты, варьируется от реализации к реализации, но это предполагает наиболее распространенный подход.


1
ШТОПАТЬ! Вы избили меня до 5 минут!
kirbyfan64sos

Если первый символ НЕДЕЙСТВИТЕЛЕН, тогда это не будет работать правильно. Так должно быть +[,.]правильно?
Шелваку

6
@Shel Это использует 0x00 как байт EOF. Если первый символ - EOF, он ничего не печатает, работая как положено.
Mego

2
"псевдокод", да ладно, это явно не в скобках, без точки с запятой. C: P
MD XF

14

Лабиринт , 2 байта

,.

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

Как в Brainfuck ,читает байт (помещая его в основной стек Лабиринта) и .записывает байт (извлекая его из основного стека Лабиринта).

Причина, по которой этот цикл повторяется, заключается в том, что оба ,и .являются "тупиками" в (очень тривиальном) лабиринте, представленном исходным кодом, так что указатель команды просто поворачивается на месте и возвращается к другой команде.

Когда мы нажимаем EOF, вместо этого ,нажимает -1и .выдает ошибку, потому что -1это недопустимый код символа. Это может измениться в будущем, но я еще не решил это.


Для справки, мы можем решить это без ошибки в 6 байтов следующим образом

,)@
.(

Здесь )увеличивается байт, который мы читаем, что дает 0EOF и что-то положительное в противном случае. Если значение равно 0, IP движется прямо, нажимая на тот, @который завершает программу. Если значение было положительным, IP вместо этого повернет направо в сторону, (которая уменьшает вершину стека до ее первоначального значения. IP-адрес теперь находится в углу и будет просто поворачивать направо, печатать с помощью ., читать новый байт ., прежде чем он )снова попадет на развилку .


13

C, 40 байтов

main(i){while(i=~getchar())putchar(~i);}

main () {while (255-putchar (getchar ()));} на пару байтов короче.
Алхимик

1
К сожалению, это преждевременно завершает работу с байтами 0xFF и добавляет к входу байт 0xFF, если он не содержит его.
Деннис

Как насчет следующих 36 байтов: main () {for (;; putchar (getchar ()));};
Йохан дю Туа

@ user2943932 Когда он достигает EOF, getcharвозвращает -1 , поэтому ваш код будет печатать бесконечный поток байтов 0xFF после (конечного) ввода.
Деннис

12

> <> , 7 байт

i:0(?;o

Попробуй это здесь . Объяснение:

i:0(?;o
i        Take a character from input, pushing -1 if the input is empty
 :0(     Check if the input is less than 0, pushing 1 if true, 0 if false
    ?;   Pop a value of the top of the stack, ending the program if the value is non-zero
      o  Otherwise, output then loop around to the left and repeat

Если вы хотите, чтобы продолжать идти , пока вы не дадите ему больше входного сигнала, замените ;с !.


О, чувак, я надеялся опубликовать ответ> <> ...: P (+1!)
El'endia Starman

1
io(2 байта) делает то же самое, но вылетает и записывает something smells fishy...в STDERR в конце выполнения, что разрешено.
Линн

@Mauris онлайн-переводчик просто выводит нулевые байты, а не заканчивается ошибкой.
DanTheMan

11

Сборка X86, 70 байт

Разборка с помощью objdump:

00000000 <.data>:
   0:   66 83 ec 01             sub    sp,0x1
   4:   66 b8 03 00             mov    ax,0x3
   8:   00 00                   add    BYTE PTR [eax],al
   a:   66 31 db                xor    bx,bx
   d:   66 67 8d 4c 24          lea    cx,[si+0x24]
  12:   ff 66 ba                jmp    DWORD PTR [esi-0x46]
  15:   01 00                   add    DWORD PTR [eax],eax
  17:   00 00                   add    BYTE PTR [eax],al
  19:   cd 80                   int    0x80
  1b:   66 48                   dec    ax
  1d:   78 1c                   js     0x3b
  1f:   66 b8 04 00             mov    ax,0x4
  23:   00 00                   add    BYTE PTR [eax],al
  25:   66 bb 01 00             mov    bx,0x1
  29:   00 00                   add    BYTE PTR [eax],al
  2b:   66 67 8d 4c 24          lea    cx,[si+0x24]
  30:   ff 66 ba                jmp    DWORD PTR [esi-0x46]
  33:   01 00                   add    DWORD PTR [eax],eax
  35:   00 00                   add    BYTE PTR [eax],al
  37:   cd 80                   int    0x80
  39:   eb c9                   jmp    0x4
  3b:   66 b8 01 00             mov    ax,0x1
  3f:   00 00                   add    BYTE PTR [eax],al
  41:   66 31 db                xor    bx,bx
  44:   cd 80                   int    0x80

Источник:

sub esp, 1
t:
mov eax,3
xor ebx,ebx
lea ecx,[esp-1]
mov edx,1
int 0x80
dec eax
js e
mov eax,4
mov ebx,1
lea ecx,[esp-1]
mov edx,1
int 0x80
jmp t
e:
mov eax,1
xor ebx,ebx
int 0x80

1
Итак, objdumpразберите его как 32-битный код, в то время как вы, кажется, скомпилировали как 16-битный. Во что верить? Поскольку вы используете int 0x80, я думаю, что это предназначено для Linux, но зачем тогда компилировать как 16-битные?
Руслан

@Ruslan Я даже не догадывался, что он был скомпилирован в 16-битном
формате

11

Универсальная лямбда , 1 байт

!

Универсальная лямбда-программа - это кодирование лямбда-термина в двоичном виде, разбитое на куски по 8 битов, заполнение неполных кусков любыми битами, преобразованными в поток байтов.

Биты переводятся в лямбда-термин следующим образом:

  • 00 вводит лямбда-абстракцию.
  • 01 представляет собой применение двух последующих условий.
  • 111..10с n повторениями бита 1относится к переменной n- й родительской лямбды; то есть это индекс Де Брюина в унарном.

Под этим преобразованием понимается 0010функция идентификации λa.a, что означает, что любая однобайтовая программа в форме 0010xxxxявляется catпрограммой.


1
Но !это 0x21, не 0x4_?
wchargin

Исправлена. --------
Линн

10

PowerShell, 88 41 30 байт

$input;write-host(read-host)-n

РЕДАКТИРОВАТЬ - забыл, что я могу использовать $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переменном.


не забывайте свои встроенные псевдонимы!
Чед Бакстер

10

Cubix , 6 5 байтов

Теперь обрабатывает нулевые байты!

@_i?o

Cubix - это двумерный esolang на основе стека. Cubix отличается от других двумерных языков тем, что исходный код обернут снаружи куба.

Проверьте это онлайн! Примечание: между итерациями задержка составляет 50 мс.

объяснение

Первое, что делает интерпретатор, это вычисляет наименьший куб, на который поместится код. В этом случае длина ребра равна 1. Затем код дополняется без операций, .пока все шесть сторон не будут заполнены. Пробелы удаляются перед обработкой, поэтому этот код идентичен приведенному выше:

  @
_ i ? o
  .

Теперь код запускается. IP (указатель инструкций) начинается с крайней левой грани, указывая на восток.

Первый символ, с которым сталкивается IP _, - это зеркало, которое переворачивает IP, если он обращен на север или юг; в настоящее время он смотрит на восток, так что это ничего не делает. Далее идет iввод байта из STDIN. ?поворачивает IP влево, если верхний элемент отрицательный, или вправо, если положительный. Здесь есть три возможных пути:

  • Если введенный байт равен -1 (EOF), IP поворачивается влево и нажимает @, что завершает программу.
  • Если введенный байт равен 0 (нулевой байт), IP просто продолжается прямо, выводя байт с помощью o.
  • В противном случае IP поворачивает направо, проходит через нижнюю грань и ударяется о зеркало _. Это переворачивает его, отправляя обратно в ?, который снова поворачивает вправо и выводит байт.

Я считаю эту программу оптимальной. Прежде чем Cubix смог обработать нулевые байты (EOF был 0, а не -1), эта программа работала для всего, кроме нулевых байтов:

.i!@o

Я написал брутфорсер, чтобы найти все 5-байтовые программы для кошек. Хотя для завершения требуется ~ 5 минут, в последней версии найдено 5 программ:

@_i?o   (works as expected)
@i?o_   (works in exactly the same way as the above)
iW?@o   (works as expected)
?i^o@   (false positive; prints U+FFFF forever on empty input)
?iWo@   (works as expected)

Пожалуйста, не редактируйте дюжину постов одновременно. Вы наводнили первую страницу. 3 за раз не проблема, но если вам нужно сделать больше, пожалуйста, вносите изменения небольшими партиями каждые 12 часов или около того.
Мартин Эндер

@MartinEnder Извините, я только что заметил это. Я разложу их в будущем.
ETHproductions

9

Витси, 2 байта

ZZ

zполучает весь входной стек и помещает его в стек активной программы. Zраспечатывает весь активный стек в STDOUT.

Альтернативный метод:

I \ иль \ O
Я \ Повторить следующий символ для длины стека ввода.
  Я возьму предмет из ввода.
   l \ Повторите следующий символ для длины текущего активного программного стека.
     O Выведите верхний элемент стека как символ.

2
^ _ ^ В любом случае +1! :)
El'endia Starman

Жалко голосов, мой любимый!
Эддисон Крамп

Почему отрицательные? Похоже, это совершенно правильная запись
Конор О'Брайен,

1
Он является действительным всеми спецификациями.
Эддисон Крамп

9

MarioLANG , 11 байт

,<
."
>!
=#

Я не совсем уверен, что это оптимально, но это самое короткое, что я нашел.

Это поддерживает бесконечные потоки и завершится с ошибкой при достижении EOF (по крайней мере, эталонная реализация Ruby делает).

Есть еще одна версия, которая превращает Марио в ниндзя, который может дважды прыгать:

,<
.^
>^
==

В любом случае, Марио начинает падать вниз в левую колонку, где ,читает байт и .записывает байт (который выдает ошибку в EOF, потому ,что не возвращает действительный символ). >гарантирует, что Марио идет направо ( =это просто площадка для него). Затем он движется вверх, либо двойным прыжком с ^лифтом ( "или #парой) , либо через него, прежде чем он <скажет ему вернуться в левую колонку.


8

RS , 0 байт


Шутки в сторону. rs просто печатает все, что получает, если данный скрипт полностью пуст.


7

GolfScript, 3 байта

:n;

Пустая программа повторяет стандартный ввод. Язык не может обрабатывать бесконечные потоки. Тем не менее, он добавляет новую строку, как упоминал @Dennis. Это делается путем оборачивания всего стека в массив и вызова puts, который определяется как print n print, где nнаходится символ новой строки. Тем не менее, мы можем переопределить nSTDIN, а затем очистить стек, что и :n;делает.


7

Полуразбитая машина в интенсивном движении , 9 + 3 = 12 байт

#<
o^<
 v

Половина разбитой машины при интенсивном движении (HBCHT) принимает входные данные в качестве аргументов командной строки, поэтому запускайте как

py -3 hbcht cat.hbc -s "candy corn"

Обратите внимание, что +3 для -sфлага, который выводит как символы. Кроме того, HBCHT, по-видимому, не обрабатывает NUL, поскольку все нули удаляются из выходных данных (например 97 0 98, выводятся в виде двух символов ab).

объяснение

В HBCHT ваша машина начинается с, oи ваша цель - выход #. ^>v<направлять движение автомобиля, одновременно изменяя BF-подобную ленту ( ^>v<перевод на +>-<). Однако, как следует из названия языка, ваш автомобиль может поворачивать только вправо - любые попытки повернуть налево полностью игнорируются (включая их эффекты памяти). Обратите внимание, что это только для поворота - ваш автомобиль отлично способен двигаться вперед / назад.

Другие интересные детали о HBCHT - это то, что начальное направление вашего автомобиля рандомизировано, а сетка тороидальная. Таким образом, нам просто нужна машина, чтобы доехать до выхода, не изменяя ленту для всех четырех начальных направлений:

  • Вверх и вниз прямолинейны, направляясь прямо к выходу.

  • Для левого мы обертываем и выполняем <и увеличиваем с ^. В следующий раз мы не можем повернуть налево, <поэтому мы оборачиваемся и уменьшаем v, отменяя предыдущий прирост. Поскольку мы движемся вниз, теперь мы можем повернуть направо на <выходе и выйти, дважды переместив указатель и не изменив значения ячеек.

  • Для правого мы делаем то же самое, что и левый, но пропускаем первый, ^так как мы не можем повернуть налево.


Редактировать : Оказывается, что интерпретатор HBCHT позволяет вам выполнить только один путь через флаг командной строки, например

py -3 hbcht -d left cat.hbc

Тем не менее, флаг не только слишком дорогой для этого конкретного вопроса (по крайней мере, 5 байт " -d u"), но кажется, что все пути все еще должны иметь возможность пройти его до выхода для выполнения кода.


7

Минколанг , 5 байт

od?.O

Попробуй это здесь.

объяснение

oчитает символ из ввода и помещает его ASCII-код в стек ( 0если ввод пуст). dзатем дублирует вершину стека (символ, который был только что прочитан). ?является условным батутом, в который не попадает следующая инструкция вершины стека 0. Если вход был пустым, то .он не перескочил и программа остановилась. В противном случае Oвыводит вершину стека как символ. Тороидальная природа Минколанга означает, что это происходит в начале.


2
Grar! Вы победили мой язык! НЕПРИЕМЛЕМО! +1
Эддисон Крамп

7

INTERCALL , 133 байта

Wat

INTERCALL IS A ANTIGOLFING LANGUAGE
SO THIS HEADER IS HERE TO PREVENT GOLFING IN INTERCALL
THE PROGRAM STARTS HERE:
READ
PRINT
GOTO I

Похоже, что кто-то действительно играет в гольф на языке, абсолютно не противоречащем игре в гольф ... 133-116 = 17
Эрик Игрок в гольф

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Так как программа cat довольно проста, это не относится ко всем программам ... codegolf.stackexchange.com/a/82748/53745
TuxCrafting

Человек, создавший язык, намеревался использовать римские цифры, но если бы это было так, чтобы печатать 500(не уверен), было бы PRINT D, верно? (исключая заголовок)
Эрик Outgolfer

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Нет, INTERCALL может печатать только символы ASCII и использовать стек, поэтому, например, для печати символа со значением 20 ascii, код равен PUSH XX<newline>PRINTили PUSH XX AND PRINT. О, и я создатель INTERCALL
TuxCrafting

7

V , 0 байтов

Попробуйте онлайн!

Идея V о «памяти» - это просто гигантский двумерный массив символов. Перед запуском любой программы все входные данные загружаются в этот массив (известный как «Буфер»). Затем в конце любой программы печатается весь текст в буфере.

Другими словами, пустая программа - это программа cat.


6

Снеговик 1.0.2 , 15 символов

(:vGsP10wRsp;bD

Взято прямо из examplesкаталога Снеговика . Читает строку, печатает строку, читает строку, печатает строку ...

Обратите внимание, что из-за деталей реализации, когда STDIN пуст, vgвернет то же самое, что и для пустой строки. Следовательно, это будет многократно печатать переводы строк в бесконечном цикле после закрытия STDIN. Это может быть исправлено в будущей версии.

Пояснение к коду:

(        // set two variables (a and f) to active—this is all we need
:...;bD  // a "do-loop" which continues looping as long as its "return value"
         // is truthy
  vGsP   // read a line, print the line
  10wRsp // print a newline—"print" is called in nonconsuming mode; therefore,
         // that same newline will actually end up being the "return value" from
         // the do-loop, causing it to loop infinitely


5

Деление , 4 байта

R?J!

Разве это не приятно, когда вы обыгрываете примеры программ в собственном репозитории языка? :) Для справки, он имеет 7-байтовое решение

R?J0;0!

объяснение

Итак, Rзапускает поток управления с правым атомом. ?читает символ из STDIN в массу атома. До тех пор, пока мы читаем символы, энергия остается нулевой, поэтому JUMP не работает и !печатает символ. Атом возвращается к началу ( Rтеперь не работает) и повторяет весь процесс.

Когда мы нажмем EOF, ?установим для энергии атома значение 1, поэтому Jтеперь ump пропустит команду печати. Но когда атом попадает ? после того, как EOF уже был возвращен, он вместо этого уничтожит атом, что завершит программу.

(Решение от автора языка использует явное ;завершение программы, которое в 0противном случае пропускается двумя -порталами.)


5

Штрипед , 20 байт

e )
"
 r )
 s )
 "
"

Это нагло демонстрирует, что почти любая печатная строка ASCII является допустимым идентификатором в Shtriped.

Как это устроено:

e )   \ declares a variable named )
"     \ defines a function with 0 arguments named "
 r )  \ gets a line of string input, saving it to )
 s )  \ prints ) as a string
 "    \ recursively calls ", effectively looping forever
"     \ calls " from the main scope to get things started

Нет реального способа обнаружить EOF, так что это цикл навсегда, как в ответе Python .

Вы можете легко остановить его, если дана пустая строка (30 байт):

e )
"
 r )
 d ) \ tries to decrement ), if it was the empty string, aka 0, it can't, so 0 is returned all the way up
 i ) \ increment ) to put it back to normal after possibly decrementing
 s )
 "
"

Обратите внимание, что Shtriped I / O поддерживает только печатный ASCII , вкладки, переводы строк, возврат каретки, вертикальные вкладки и переводы форм (всего 100 символов). Это связано с тем, что внутренне строки представляются как неотрицательные целые числа произвольной точности, и должен быть конечный алфавит символов, чтобы иметь возможность кодировать все строки.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.