Помещать один совет за ответ было бы слишком много ответов.
Учись думать в Brainfuck. Это сильно отличается от всего остального. Читайте и пишите, и переписывайте, и переписывайте множество программ для мозга. Язык не дает вам много работы, поэтому важно использовать то, что он дает вам гибко и эффективно. Не позволяйте никаким абстракциям встать между вами и языком - зайдите туда и боритесь с этим.
Получите очень удобно с неразрушающим контролем потока. Чтобы выйти из цикла принятия решения, вместо того, чтобы обнулять начальную ячейку, копируя ее в другое место и затем копируя ее обратно после выхода из цикла, часто лучше переместить указатель на уже существующий ноль поблизости. Да, это означает, что указатель будет находиться в разных местах в зависимости от того, проходили ли вы через цикл, но это также означает, что эти места, вероятно, имеют различные расположения соседних нулей и ненулевых элементов, которые можно использовать для повторной синхронизации расположения указателя с помощью другого цикла. Эта техника является фундаментальной для хорошего программирования Brainfuck, и различные ее формы будут постоянно полезны.
Это и тот факт, что каждый >
или <
расходы означают, что детали расположения памяти важны. Попробуйте столько вариантов вашего макета, сколько у вас есть терпение. И помните, ваш макет памяти не должен быть жестким отображением данных в местах. Это может измениться в процессе исполнения.
В более широком масштабе рассмотрите и даже попробуйте реализовать множество различных алгоритмов. Изначально не будет очевидно, какой именно алгоритм будет наилучшим; может даже не быть очевидным, какой базовый подход будет наилучшим, и он, вероятно, будет отличаться от того, что было бы лучше всего на обычном языке.
Если вы имеете дело с большими данными или данными переменного размера, посмотрите, есть ли какой-нибудь способ, которым вы можете иметь дело с ними локально, без необходимости отслеживать, насколько они велики или ваше числовое местоположение в них.
Одни и те же данные могут быть двумя разными вещами. (Чаще всего это число или символ, а также ненулевой позиционный маркер. Но см. Random.b , где счетчик битов удваивается как значение одной ячейки клеточного автомата.)
Один и тот же код может делать две разные вещи, и намного проще сделать это на языке, где код такой же общий, как и <+<
. Будьте внимательны к таким возможностям. На самом деле, вы можете иногда замечать, даже в том, что кажется хорошо написанной программой, что есть небольшие фрагменты, которые можно полностью удалить, ничего не добавить, и что, случайно, все равно будет работать безупречно.
В большинстве языков вы часто используете компилятор или интерпретатор для проверки поведения вашей программы. Язык Brainfuck требует большего концептуального контроля; если вам нужен компилятор, чтобы рассказать вам о том, что делает ваша программа, у вас недостаточно четкого понимания вашей программы, и вам, вероятно, нужно еще на нее взглянуть - по крайней мере, если вы хотите иметь достаточно четкое изображение концептуальный ореол подобных программ, чтобы быть хорошим в гольфе. С практикой вы будете выпускать дюжину версий вашей программы, прежде чем пытаться ее запустить, и к этому моменту вы будете на 95% уверены, что ваша самая короткая версия будет работать правильно.
Удачи! Очень немногие люди стараются писать Brainfuck кратко, но я думаю, что это единственный способ, которым язык может оправдать постоянное внимание - как потрясающе малоизвестная форма искусства.
Несколько советов здесь:
Константы:
Страница константы Esolangs' имеет чрезвычайно полезный список самых коротких путей для создания ценности конкретных. Я нахожу себя просматривающим эту страницу по крайней мере дважды для каждой программы.
Начало всего:
Это устанавливает ленту в формате 3 * n ^ 2, которая выглядит как
3 6 12 24 48 96 192 128 0 0 '
Почему это так важно?
Давайте спустимся по списку:
0
a
A
.Из этого одного алгоритма мы находимся в начале практически каждой последовательности в диапазоне ASCII, вместе со счетчиком для каждой и новой строкой в легкодоступном месте.
Практический пример:
Печать всех прописных и строчных букв и цифр.
С алгоритмом:
Без:
Мы тратим большую часть байтов, просто инициализируя ленту во втором примере. Отчасти это компенсируется дополнительными движениями в первом примере, но этот метод явно имеет преимущество.
Пара других интересных алгоритмов в том же духе:
3 * 2 ^ п + 1:
Это смещает значения на 1, что выполняет несколько вещей. 12 делает возврат каретки, 64 - фактическое начало прописного алфавита, а 24 ближе к 26.
2 ^ п:
Поскольку 64 подходит для заглавных букв, 32 - это ASCII для пробела, а 128 можно использовать в качестве счетчика для 26 (130/5 = 26). Это может сохранить байты в определенных ситуациях, когда цифры и строчные буквы не нужны.
Выберите реализацию, которая подходит для вопроса:
+[[-<+>>+>+<<]>]
) или обработка больших / отрицательных чисел. Недостатком является то, что некоторые распространенные методы, такие как[-]
и на[->+<]
которые нельзя положиться, на случай, если число отрицательное.Следите за тем, что происходит:
У вас всегда должны быть комментарии о том, где должен находиться указатель относительно данных вокруг него, и убедитесь, что вы знаете диапазон возможных значений каждой ячейки. Это особенно важно, когда вы разбиваете указатель перед циклом, потому что вы захотите объединить две возможности позже.
В любой момент мой код полон комментариев к каждой строке, которая выглядит следующим образом:
Некоторый дополнительный совет должен назначить символам специальные значения. В приведенном выше примере,
'
где указатель,*
означает повторение в этом направлении,?
означает ячейку с неизвестным значением,!0
означает ненулевую ячейку,_
является заменой-
иp
заменой+
.or
подразумевает, что лента может выглядеть как любое из представлений и должна обрабатываться как таковая.Ваша схема символов не обязательно должна быть такой же, как моя (у которой есть несколько недостатков), она просто должна быть последовательной. Это также чрезвычайно полезно при отладке, потому что вы можете запустить его до этой точки и сравнить фактическую ленту с тем, что у вас должно быть, что может указать на потенциальные недостатки в вашем коде.
источник
Мой главный совет - не надо.
Хорошо, хорошо, вы хотите что-то более полезное, чем это. BF уже очень лаконичен, но то, что вас действительно убивает, - это арифметика, которую нужно делать в унарном виде. Стоит прочитать на странице констант в Esolang, чтобы точно определить, как эффективно писать большие числа, и использовать обертку, где это возможно.
Доступ к памяти тоже очень дорогой. Поскольку вы читаете с кассеты, вам нужно помнить, куда движется ваша голова в любой момент времени. В отличие от других языков , где вы можете просто написать
a
,b
,c
в БФ вы должны явно переместить голову некоторое количество байт влево или вправо, так что вы должны помнить о том, где вы храните что. Я уверен, что оптимальной организацией вашей памяти является NP-сложная задача, так что удачи вам в этом.источник
В этом ответе я собираюсь сослаться на определенную ячейку на ленте много раз. Неважно, какая это ячейка, но это одна и та же ячейка на протяжении всего ответа. Для целей этого поста я назову эту ячейку "Тодд".
При попытке установить ячейку в постоянное значение иногда возникает необходимость не завершить ее немедленно. Например, допустим, что вы хотите, чтобы в Todd содержалось 30. Позже в вашем коде (который может изменить значение Todd, но никогда не читает его) вы возвращаетесь к Todd. Если значение Тодда равно 0, программа завершается. В противном случае значение Тодда печатается навсегда.
Согласно странице esolangs.org о константах мозгового мошенничества (которая, возможно, сама по себе может быть предметом подсказки!), Самый короткий способ получить 30 - это
>+[--[<]>>+<-]>+
. Это>
ведение только для того, чтобы гарантировать, что ничего слева от указателя не будет изменено, но в этом случае мы будем считать, что нам это безразлично, и отбросим его. Используя этот код, ваш код будет выглядеть примерно так:Вы можете думать о первом фрагменте кода следующим образом:
Но помните , последние два символа в этом фрагменте:
>+
. Это так же правильно думать об этом так:Обратите внимание, что вы
(GO TO TODD)
дважды! Вместо этого вы можете написать свой код следующим образом:Предполагая, что количество байт, которое требуется,
(GO TO TODD)
является тем же самым прежде, на один ход меньше == на один байт меньше! Иногда тот факт, что ваша стартовая позиция изменилась, лишает вас этой выгоды, но не всегда.источник
Маленький совет для проблем без участия. Вы можете использовать
,
вместо[-]
, если вам нужно быстро очистить ячейку, так как большинство интерпретаторов (включая TIO.run) установят для содержимого ячейки значение EOF, равное нулю. Это делает программы немного непереносимыми, но кого это волнует в коде гольф?источник