Недавно кто-то предложил более строгие ограничения для длины строки Python по умолчанию:
Очевидно, что ни одна программа не должна использовать более 80 символов в строке по целому ряду причин. Прежде всего, для удобочитаемости и удобства обслуживания важно иметь твердый стандарт, чтобы мы могли соответствующим образом отрегулировать ширину наших текстовых редакторов. В качестве вторичного преимущества код может быть легко перенесен на носитель, который может иметь ограничения, и когда добавление разрывов строк может отвлекать, например, печать страниц для просмотра на собрании или перфокарты.
Но 80 символов слишком высоко? Некоторые предлагают 79, или даже всего 75, чтобы позволить терминалу шириной 80 символов соответствовать коду с несколькими столбцами, посвященными номерам строк. Понятно, что в конечном итоге чем меньше, тем лучше, поскольку нижние пределы позволяют использовать код в большем количестве ситуаций без переформатирования.
Ваша цель - найти и продемонстрировать минимальную длину строки, требуемую вашим любимым языком, написав вариант FizzBuzz с наименьшим количеством символов в любой строке.
вход
Целое число n через любой желаемый метод.
Выход
Выведите числа от 1 до n , ( n ≥ 1, n ∈ ℤ), разделенных переносами строк, кроме:
- для кратного 3-х отпечатка "Яблоко"
- для кратных 5 оттисков "Пирог"
- для кратных как 3, так и 5 отпечаток "ApplePie"
счет
Максимальную длину строки в байтах, не включая разрыв строки (Cr, CrLf, Lf или другой системный стандартный разрыв, задайте по желанию) и общую длину кода в байтах в качестве прерывателя связей.
правила
Все разрывы строк должны быть значимыми. Разрывы строк, которые могут быть удалены, и смежные строки, непосредственно соединенные без влияния на вывод, должны быть удалены.
Ответы:
> <> , 1 байт на строку,
243161135 байтов-26 байтов благодаря Джо Кингу!
2D языки FTW! Хотя написание циклов и ветвей с использованием goto-инструкций вместо 2D-структуры не очень весело.
Попробуйте онлайн! Или посмотрите на рыбную площадку !
Рыба плывет вниз по коду, используя условные переходы, чтобы пропустить вещи в зависимости от того, что разделяет аккумулятор.
Я считаю, что это соответствует спецификации: все новые строки удаляются, рыба всегда попадает в начальную
v
(единственная существующая инструкция по изменению направления), поэтому рыба всегда плывет вниз в первом столбце. Таким образом, удаление новой строки приводит к простому удалению следующего символа с пути рыбы, и я не думаю, что вы можете удалить любой из символов без изменения вывода.источник
Haskell , 3 байта / строка,
494 471 470 463 453 450461 байтРЕДАКТИРОВАТЬ:
-1+x
наx-1
.--
строка послеx-
.f
используетсяc 47:[]
вместо[c 47&0]
.w
.a="Apple"
иp="Pie"
в#
и использовать фиктивную рекурсию для 15 случая.w
вf
. Удалить лишние--
междуx
и15
.%
функции. Наконец-то сделали несколько автоматических тестов, чтобы убедиться, что больше никаких сюрпризов.f
принимаетInt
и возвращаетString
.Попробуйте онлайн!
Ограничения источника теста!(Строка 70 исключена из тестирования, потому что удаление ее новой строки вызывает бесконечный цикл без вывода.)
Версия с удаленными наиболее важными хитростями:
Как это работает
{}
. Поскольку я на самом деле определяю функцию, а не целую программу, я не совсем уверен, как считать байты; Я выбрал оборонительную рассчитывать как{}
S и дополнительной;
декларации разделитель (последний , как правило , является символом новой строки в обычном режиме Haskell.)--
комментарии к строкам, которые делают следующую строку не удаляемой, а также предыдущий символ новой строки в случае, когда предыдущая строка заканчивается символом оператора (который сам по себе не является частью комментария строки) ,\
обратными слешами в строковых литералах, с отступом для продолжения строки с возможным отступом. Пробел с разделителями удаляется из проанализированной строки."Apple"
и"Pie"
это проявляется прямо в выводе. Для"8"
и"9"
сопоставление с образцом используется для выдачи ошибки, если строка содержит более одного символа.&
and%
, которые позволяют принудительно завершить строку символом оператора для первого приема. Нам нужно это закончить строковые литералы, потому что\"
он слишком широк для добавления--
.&
является общим, определенным так, чтоx&y=x
.%
определяется так, что[a]%y=a
, позволяя ему заменить!!0
и одновременно принудительно установить, что его строковый аргумент должен иметь длину 1.\n
кажется невозможным поместиться в строковый литерал, содержащий только 3 байта в строке.c x=["9"%0,"8"%0..]!!x
используется для преобразования изInt
символа в символ, начиная с цифры'9'
вниз.show
это четыре символа, вывод числа должен осуществляться вручную.d
список из цепочек цифр"1".."9"
.n
является бесконечным списком числовых представлений,["1","2","3",...]
определенных рекурсивно с использованиемd
.#
преобразуетInt
x
его ApplePie форме дали дополнительный первый аргумент , который являетсяgcd
изx
с 15.источник
Haskell , 7 байт / строка, 339 байт
Требование, чтобы разрывы строк были значимыми, делает это нетривиальной задачей в Haskell. Практически нет способов вставить разрывы строк, которые нельзя удалить, поэтому все должно быть сделано с помощью крошечных операторов.
Попробуйте онлайн!
источник
Желе ,
32 байта / строка,1068056 байтовСтроки и столбцы строкового литерала транспонируются, поэтому удаление новых строк портит их порядок.
Остальные строки являются отдельными ссылками / функциями и содержат вызовы функций (
¢
), поэтому их можно объединять, только если вызовы функций также исключены.Попробуйте онлайн!
источник
TI-BASIC, 4 байта на строку
Поскольку цель состоит только в том, чтобы минимизировать максимальную длину строки, некоторые строки длиннее, чем они должны быть, но самая маленькая строка, которую я мог сделать, была 4 байта. Поэтому я чувствовал, что это облегчит чтение кода, если я объединю строки, которые можно объединить, не превышая 4 байта.
Ungolfed
О языке и ограничениях
TI-BASIC - это токенизированный язык, и в этом случае каждый из токенов составляет 1 байт, за исключением
StrN
переменных, которые составляют 2 байта. Кроме того, вы можете оставить закрывающие скобки большую часть времени.remainder(
Функция 2 байта, так что использование этого потребуется , по меньшей мере 5 байт (один для функции, два для аргументов, и один для запятой вremainder(I,3
). Вместо этого я использовалfPart(
иnot(
функцию , чтобы сделать его короче, что оба 1 байты жетонов. Кроме того, вы можете видеть, что я использовал встроенную переменнуюAns
довольно , поскольку любое выражение, которое оценивается в строке, автоматически сохраняется в ней. Итак, я могу сэкономить несколько байтов, разделив выражения и назначения.Другая стратегия заключалась в том, чтобы минимизировать строковые назначения. Мой метод для этого зависел от максимальной длины строки в остальной части кода. Как только я определил, что это 4 байта, я смог собрать как можно больше каждой строки в одной строке, чтобы минимизировать количество необходимых мне назначений. Я сделал это ради удобства чтения.
Ограничивающими факторами в этом коде являются присвоения строковым переменным и конкатенация со строковыми переменными. Линии
Ans→Str1
иStr1+Ans
оба имеют длину 4 байта. Мне нужно было бы найти способ полностью исключить строковые переменные, чтобы дополнительно минимизировать максимальную длину строки в моем коде. Все остальное может быть сокращено до максимум 3 байтов или меньше на строку.Проблема заключается в присвоении числовых переменных, таких как
1→I
. Вы не можете играть дальше, не придумав решения без переменных, длина которых не превышает 2 байта. Это оказывается невозможным для этого вызова.Двоичные операторы типа like
+
требуют символа оператора и левого и правого аргументов. Таким образом, без этого вы не сможете объединить строки. Без конкатенации строк не было бы возможности отобразить строки, необходимые для выполнения этой программы, без превышения длины строки в 2 байта. Поэтому теоретический предел для этой задачи на этом языке будет 3 байта на строку, чего я не смог достичь.источник
If A and B
Ans
Маркер 1 байт, в то время как три последовательных символа :Ans
1, 2, и 2 байта соответственно в общей сложности 5. Это не строка ASCII, это буквально маркер , когда вы вводите его на калькуляторе.C (gcc) , 2 байта на строку,
374368320310262 байтаЯ предполагаю, что это может быть игра в гольф немного больше. Обратная косая черта, экранирующая символы новой строки, делает это своего рода тривиальным.
Попробуйте онлайн!
источник
&&
.Python 3 , 4 байта / строка, 113 байтов
Попробуйте онлайн!
источник
PHP 7, 2 байта на строку
источник
Aceto , 1 байт на строку, 230 байт
Ну, это было не весело писать. Как грибок, управляющие структуры Aceto в значительной степени зависят от его 2D-характера, но мы можем обойти это с помощью множества условных выходов (
`
). Единственная проблема с ними заключается в том, что они влияют на следующую команду, независимо от ее присутствия (все программы Aceto являются квадратами, внутренне), поэтому нам нужно выровнять программу в некоторых местах, вставляя пустые строки в некоторых точках.Строковые литералы на самом деле не могут использоваться, но могут использоваться литералы-символы (в некоторых местах; опять же, нам нужно их выравнивать).
Вызывается с
20
, это печатает:Это никогда не имеет место здесь, потому что это бежит снизу вверх.
Там, по крайней мере , одно место , где мы можем сохранить 2 байта (путем замены
`X
с|
или#
), но я сохранил его как есть из-за затрат времени выполнения, связанных с прохождением относительно большой кривой Гильберта.Я также проигнорировал неявное требование для использования
\r
или\r\n
перевода строки, потому что я считаю, что это непреднамеренная ошибка со стороны ФП. Если есть редактирование или комментарий, подкрепляющий это требование, я могу изменить его без особых проблем, чтобы использовать вместо него новые строки CR.Bytecount основан на кодинговой кодировке Aceto; Latin-7, в котором
£
есть один байт.источник
Perl 5 , 2 байта на строку, 182 байта
Попробуйте онлайн!
Синтаксис Perl очень простителен, поэтому в коде можно добавить много пробелов и добавить комментарии, что делает основную идею довольно простой. Основная цель этого кода - создать строку, содержащую код, который мы хотим запустить, и
eval
его. В Perl можно вызывать функцию, используя строку или переменную с&{...}
нотацией, но, к сожалению,eval
не вызывается в этой форме, но . Чтобы это действовало, в нескольких местах должны были быть размещены комментарии, чтобы удаление новых строк приводило к неработающему коду.evalbytes
выполняется до тех пор, пока вы вызываете ее черезCORE::
пространство имен. Построение этой строки было довольно простым, и программа передается непосредственно этому вызову. Строки строятся с использованием символов новой строки как части XOR, чтобы построить их я использовал этот скриптПрограмма FizzBuzz была взята из превосходного ответа .
Perl 5 , 1 байт на строку, 172 байта
Итак, я (теперь) знаю, что это неверно , потому что кучу новых строк можно удалить, но так как это был мой оригинальный подход к проблеме, я добавляю ее. Было весело видеть, как далеко вы можете продвинуть синтаксис Perl! Мне понравилась эта проблема сама по себе, хотя она недействительна.
Попробуйте онлайн!
источник
SmileBASIC,
97 байт на строку,159155154152 байтаЭто было действительно забавное испытание. К сожалению, правило против ненужных разрывов строк вызывает несколько проблем (хотя, к счастью, оно не влияет на максимальную длину строки здесь.) Мне пришлось добавлять комментарии между строками, подобными
A%=I/3
иA=A%*3
, такA%=I/3A=A%*3
как правильно анализируется в SB. Я смог использовать трюк, чтобы пропустить некоторые комментарии, так как заменаA
наE
делает эту строку недействительной (E
я думаю, что она имеет отношение к числам, написанным с использованием нотации.3E
Считается недопустимым числом, а не числом и именем переменной.)Самое большое ограничение здесь - получение информации.
INPUT x
это самый простой способ, альтернативный - определить функцию с входным значением, таким какDEF F x
но это все еще 7 символов. Делать условные заявления также сложно; Я не могу думать ни о чем корочеWHILE x
.источник
A%=I/3A=A%*3
синтаксически допустимо, но логически нарушено, вам не нужен комментарий char.A%=I/3
иA=A%*3
, поэтому комментарий обязателен.JavaScript (ES6), 3 байта на строку
Использует глобальную переменную
top
для доступа кwindow
объекту, из которого мыeval
следующий код:Вам придется запустить его в консоли, поскольку
top
он недоступен из изолированного фрагмента стека.источник
C #, 9 байтов на строку,
248 242230 байтовТак как C # не заботится о переводе строк, он нуждается в комментариях в конце почти каждой строки (спасибо Орджану Йохансену), чтобы соответствовать правилам. Эта программа ожидает n в качестве аргумента командной строки. Вот как можно больше не удаляемых символов новой строки:
Но так как самая длинная строка составляет 9 байтов, другие строки тоже могут получить такую длину, сбрасывая некоторые байты:
источник
//
между токенами, которые бы слились воедино, напримерstatic
иvoid
.var
s="";if//
(i%3==0//
)s+=//
"Apple"//
;if(i%5//
.A
от первой линии ко второй.Python 2, 5 байт / строка, 93 байта
Стандарт max6 уже устарел.
Попробуйте онлайн!
Python 2 и 3, 5 байт / строка, 100 байт
Попробуйте онлайн!
источник
JavaScript, максимум 6 байт / строка, 528 байт
Идея разорвана отсюда .
Код разорван отсюда .
Спасибо Anders Kaseorg за
g=eval
сохранение байта в строке.Unseperated:
источник
a=""+\n"f"+\n"o"+ ...
и заканчиваетсяeval(\na)
чуть корочеf=eval
иf(a)
.PHP, 4 байта / строка
Попробуйте онлайн!
источник
APL (Дьялог) , 5 байт на строку
Попробуйте онлайн!
источник
Сетчатка , 4 байта / строка
Попробуйте онлайн!
источник
R , 10 байт на строку, 800 байт
Правило «значимых разрывов строк» усложняло задачу. В настоящее время это просто записывает код fizzbuzz в строку, а затем выполняет его.
Попробуйте онлайн!
Вот сцепляются ApplePie код (адаптировано из MickyT в гольф здесь ).
И версия без разбора кода разбора:
Здесь я использую,
toString
чтобы объединить список символовa
в одну строку. Однако поведение по умолчанию состоит в том, чтобы разделять каждый символ,
, поэтому мы вызываем его,gsub
чтобы заменить его на нули. Затем мы передаем егоparse
иeval
делаем грязную работу.Вполне возможно , что есть такой подход , который не использует этот метод строки синтаксического анализа и просто прямо вверх орудия FizzBuzz, но мне кажется , что использование
for
илиwhile
или , образующийfunction
требуется больше строк , чем текущий подход.источник
Ruby,
105 байт / строка,354214 байт-140 байт из необработанного результата @NieDzejkob.
Как это работает
Ruby автоматически объединит последовательности строковых литералов (за исключением односимвольных литералов, таких как
?a
) в одном выражении. Это означает, чтоx = "a" 'b' "c" %q{d}
эквивалентноx = "abcd"
. Мы используем это, чтобы разделить код, похожий на FizzBuzz, на строки меньшего размера для вызоваeval
, так как это+
приведет к аннулированию программы из-за правила удаления новых строк, но\
вызовет синтаксические ошибки, если новые строки будут удалены!источник
eval
строка длиннее остальных, верно?Юлия 0,6 , 5 байт на строку, всего 168 байт
Попробуйте онлайн!
print
Приносит это неизбежно (AFAICT) в 5 байт на территории линии.Ungolfed:
*
является оператором конкатенации строк, поэтомуa*p*"\n"
формирует «ApplePie \ n».|>
является оператором цепочки функций (/ piping), поэтому выбранная строка отправляется в качестве аргументаprint
. Онsin
не используется, он просто существует, потому чтоprint
должен находиться в массиве, чтобы после него было много пробелов (используя#
трюк после того, как максимальное количество байтов в строке до 6).Если разрешено просто возвращать вывод в виде массива, это можно сделать с максимум 4 байтами на строку:
Юлия 0,6 , 4 байта на строку, всего 152 байта
Попробуйте онлайн!
Функция, которая принимает n и возвращает массив, содержащий ожидаемый результат. Максимальная длина строки здесь ограничена
n->
- Юлия нуждается в том, чтобы в одной строке она правильно анализировалась как начало лямбды.источник
Паскаль (FPC)
-Sew
, 6 байтов на строку,348320 байтовПопробуйте онлайн!
Использует FPC для получения 6 байтов на строку; без него результат был бы намного хуже. Это наименьшая возможная ширина линии, поскольку после
write
должно быть либо;
или(
(или ненужный пробел), поэтому для избежания этого вставляется специальный комментарий. Функции от FPC, которые повлияли на этот ответ://
- начало однострочных комментариев.{$<something>...}
являются директивами компилятора. Если директива не существует, FPC выдаст предупреждение (и{$ ...}
в том числе). В этой программе{
и$
разделены новой строкой, которая выдаст предупреждение при удалении.-Sew
- Компилятор также останавливается после предупреждений, чтобы{
и$
присоединившиеся остановили компиляцию.источник
Japt , 3 байта на строку
Почти удалось сократить его до двух байтов на строку, но возврат с карты прерывается, если за ней следует новая строка.
Сама реализация FizzBuzz происходит из канонического потока FizzBuzz .
Попробуйте онлайн!
источник
LOLCODE ,
188 байтов на строку, всего 303 байтаПопробуйте онлайн!
-10 байт на строку с использованием символа продолжения строки
…
, благодаря Орджану Йохансену!источник
Python 2 , 5 байт / строка
Попробуйте онлайн!
источник
'z\"'
означает то же самое, что и'z\
⏎"'
, поэтому избыточное правило новой строки означает, что вы не можете начинать строку продолжения внутри строки с"
.r'...'
сейчасSyntaxError
.FizzBuzz
на использованиеApplePie
.JavaScript (ECMAScript6), 2 байта на строку
Длинное объяснение
То, как мы можем сделать строки короче, - это преобразование кода в строку и экранирование концов строки, это накладывает ограничение в 2 байта на строку.
Так
alert(1)
становитсяНо теперь ваш код является строкой, поэтому нам нужно выполнить строку как код. Я знаю как минимум 4 способа, которыми вы можете выполнить строку как код:
eval(
onclick=""
атрибут, но мне не удалось сделать короткую часть создания элемента короткой.Все родные функция живет внутри окна объекта и в JavaScript вы можете получить доступ свойств объектов с помощью точечной нотации так
eval()
будетwindow.eval()
, или вы можете получить доступ к свойствам с помощью квадратных скобокwindow['eval']()
. Вы можете воспользоваться этим, чтобы разбитьeval
несколько строк, используя метод, описанный ранее. Но вы все равно должны ввести окно , одна хитрость в том, что если вы не находитесь внутри рамки, верх переменная также является окном, поэтому window.eval становится top.eval (на 3 байта меньше).Так что это сделает код минимум 3 байта. Чтобы сделать код 2 байта, я использовал
new Function(/*string*/);
конструктор, но мне пришлось проявить творческий подход, чтобы получить к нему доступ без необходимости набирать его.Во-первых, конструктор Function позволяет вам вызывать его как функцию, опуская ключевое слово new, это сокращает 4 байта, но это также важно по другой причине. Вызов конструктора как функции по-прежнему возвращает экземпляр, что позволяет нам
new Function(code)
кFunction(code)
. Еще одна важная вещь - это то, что конструктор Function имеетcall
метод, который позволяет вам вызывать любую функцию, но переопределяет эту ссылку, а сам конструктор Function является функцией, которую вы можете вызывать для нее сам метод, напримерFunction.call(null, code)
.Все нативные функции являются экземплярами конструктора Function, а все объекты в javascript имеют свойство constructor . Таким образом, вы можете иметь доступ к конструктору функций для любой встроенной функции, например
alert.constructor
, используя вызов метод мы можем выполнить конструктор как функцию. Теперь у нас есть alert.constructor.call (null, code), возвращающий функцию.объединяя предыдущие течиники, мы можем превратить их в
alert['constructor']['call'](null, code)
Теперь нам просто нужно найти функцию или метод с коротким именем, поэтому я выбираю метод big () внутри конструктора String. Так что я могу получить к нему доступ напрямую из пустой строки
"".big
Тогда я просто разбил каждую вещь в 2 байта
Короткий эр объяснение (TLDR)
Я получаю доступ к новому конструктору Function (code) для анализа строки вместо eval (code) . Этот конструктор доступен для любой встроенной функции, выполняя функцию anyFunction. конструктор , вроде
alert.constructor===Function
. Я использую функцию / метод внутри String.prototype.big,String.prototype.big.constructor.call(null, /*string*/)
но обращаюсь к нему напрямую из строкового литерала"".big
и превращаю его в скобочную запись .""['big']['constructor']['call'](0, CODE)
чтобы иметь возможность сломать его с помощью\
.источник
'
и]
может быть удален, и программа все равно будет работать успешно.Пип , 3 байта на строку, всего 72 байта
Попробуйте онлайн!
Pip чрезвычайно гибок в отношении пробелов, поэтому единственная стратегия, которая кажется выполнимой, состоит в том, чтобы создать строку, изменить ее таким образом, чтобы не прерывать переносы строки, и выровнять ее.
Мы создаем строку, где каждый другой символ является новой строкой, и принимаем каждый другой символ, используя
UW
(unweave) и унарный@
(get first element):Результатом
@UW
должен стать наш код ApplePie, адаптированный из решения FizzBuzz здесь . Если какие-либо символы новой строки в строке будут удалены, это не приведет к полному коду, что приведет к ошибке синтаксиса или неверному выводу.Есть еще две строки за строкой. Мы сделали это обязательным, используя
Y
оператор (yank), который в данном случае действует как no-op, а также способ, которым Pip выполняет синтаксический анализ заглавных букв:Поэтому, если эти переводы строк удаляются, программа анализирует по-другому и не делает то, что должна.
источник
Java 8, 7 байт на строку, 171 байт
Пустая лямбда-ап
int
. Я подозреваю, что это соответствует требованию относительно новых строк, но я не могу доказать это, и проверка его грубой силой заняла бы около месяца на моем компьютере. Такие вот дела.Попробуйте онлайн
Довольно скучно из-за комментариев. Единственная интересная вещь здесь - это использование нулевой
System
ссылки, которая, по-видимому, необходима для печати в стандартном формате менее 8 байтов на строку. Также обратите внимание, чтоprint
вызов метода является узким местом.Разгромленный без комментариев:
источник