О BrainFuck замолвим слово
Сравнительно недавно выучил BrainFuck и хотел бы с Вами поделиться его простотой и элегантностью. =)
Подробно о нём можно почитать в Википедии, а также в энциклопедии эзотерических языков программирования. IDE для BF качаем тут. Всё ниже сказанное относится именно к этой IDE, так как от разных реализаций языка может зависеть и поведение при выполнении программ, хотя этого мною замечено и не было.
Готовы узнать об одном из самых известных эзотерических языков программирования? Тогда читаем дальше!
Итак, язык имеет всего 8 команд и написание программы на нём является весьма даже интересной головоломкой. Вот эти команды:
+ Увеличить значение текущей ячейки на 1. - Уменьшить значение текущей ячейки на 1. [ Если значение текущей ячейки ненулевое, то перейти внутрь блока. После выполнения всех инструкций внутри блока снова запустить проверку. Простейшая реализация цикла. ] Закрывающая цикл команда. > Перейти к следующей ячейке. < Перейти к предыдущей ячейке. . Вывод значения текущей ячейки. Вывод происходит в ASCII-кодах, запомните! , Ввод с клавиатуры. Значение (код введённого ASCII-символа) заносится в текущую ячейку памяти.
Работать в BF приходится сразу с памятью. Всего 64K, то есть, 65536 ячеек - потенциальных переменных! - с разрядностью 8. То есть, максимальное число, которое Вы спожете записать, - 255. На оперировании этими ячейками и строится весь BF.
Теперь сразу немного практики. И для начала вывод банального “Hello, World!” с пояснениями:
>++++++++[<+++++++++>-]<.
>++++[<+++++++>-]<+.
+++++++.
.
+++.
>++++++[<----------->-]<-.
------------.
>+++++[<+++++++++++>-]<.
>++++[<++++++>-]<.
+++.
------.
--------.
>++++++[<----------->-]<-.
С самого начала у нас есть пустая память и указатель на первом байте. Смещаемся вправо ( > ) и устанавливаем значение счётчика (он нам понадобится для оптимизации) в 8 ( ++++++++ ). После этого запускаем цикл ( [ ). Если значение текущей ячейки не равно нулю, то перейти в блок. У нас значение равно 8, поэтому идём в блок.
В блоке мы возвращаемся на первый байт ( < ) и увеличиваем его значение на 9 единиц, затем возвращаемся в байт-счётчик и уменьшаем его на единицу ( >- ). Снова проверка на равенство нулю и снова цикл, пока счётчик не обнулится. В этот момент у нас в первом байте будет лежать значение 72, что соответствует ASCII-коду символа “H”. Нетрудно догадаться, что мы могли написать 72 плюса и получить тот же самый результат. Только код выглядел бы устрашающе! =) Для этого нам и нужен счётчик. Осталось вывести символ ( . ) и продолжить выполнение программы.
Надеюсь, принцип понятен, остальную часть разобрать следует по аналогии, ничего страшного там нет. =) Теперь пара трюков. В принципе, на BF можно написать что угодно: тут есть 64K памяти, циклы (они же ветвления), перемещения по памяти… Но делать это неудобно, на то BF и эзотерический язык! =) Для облегчения программирования на BF давно выведены некоторые конструкции, которые облегчают жизнь.
[-] - полная очистка (обнуление) текущей ячейки. Работает элементарно: если значение текущей ячейки ненулевое, то уменьшить её значение на 1. Рано или поздно ячейка приобретёт цвет нуля и цикл завершится. =) Также очевидно, что можно использовать конструкцию [+], которая творит то же самое.
[->+<] - перенос значения из одной ячейки памяти в другую.
[->+>+<<]>>[-<<+>>]<< - один из вариантов копирования. Используется третья ячейка.
Вот здесь Вы сможете найти реализации множества самых необходимых и полезных алгоритмов на языке BF, от сложения до псевдослучайных чисел. На этом можно далеко уехать. =)
Теперь разберём пример посложнее. Программа потребует ввод и выведет фразу: “Hello, [имя]!”.
; Ввод в память строки (оставляем две ячейки для вывода строки и счётчика
>>,———-[++++++++++>,———-]
; Возврат на первую ячейку (предшествующую первой непустой слева)
<[<]<
; Вывод "Hello, "
>++++++++[<+++++++++>-]<.
>++++[<+++++++>-]<+.
+++++++.
.
+++.
>++++++[<----------->-]<-.
------------.>>.>[.>]
; Вывод “!”.
<[<]<+.
Код хорошо самодокументирован, разобраться не сложно. Для программирования на BF нужно уметь хорошо работать с памятью, не забывать, в какой ячейке что хранится. Trace и дамп памяти Вам в помощь. =)
В последней версии BrainFuck Developer 1.4.6 добавлена возможность Text Generator, которая позволяет автоматически генерировать код вводимых строк. До выпуска этой версии мне срочно нужна была такая функция и я её написал. Напоследок я выкладываю её Вам для самостоятельного разбора и изучения. Если кто сложет её оптимизировать и документировать, то я с радостью посмотрел бы результат! =)
,———-[++++++++++
[->———>+<[++++++++++>[-]]>[>>+<<[-]>]<<
<]
>>>>[->[-]+++++[>++++++++<-]>+++.[-]<<]<<
[-]+++++++++[>++++++++++<-]>+.[-]<
++++++[>++++++++++<-]>++.[-]<
++++++++++[>+++++[>++++++++<-]>+++.[-]<<-]
++++++[>++++++++++<-]>.[-]<
+++++[>+++++++++<-]>.[-]<
+++++++++[>++++++++++<-]>+++.[-]<
++++++[>++++++++++<-]>++.[-]<
<[->+++++[>++++++++<-]>+++.[-]<<]
[-]++++++[>++++++++<-]>–.[-]<
+++++++++[>++++++++++<-]>+.[-]<
++++++[>++++++++<-]>—.[-]<
+++++++++[>++++++++++<-]>+++.[-]<
++++++++++.[-]<
,----------]
Призываю Вас описать свой опыт работы с BF и примеры своих скриптов. Думаю, это будет познавательно! Если у Вас возникли вопросы, то пишите их в комментариях или мне на почту (контакты в меню справа).
Ссылки по теме:
http://ru.wikipedia.org/wiki/Brainfuck - Русская Википедия о BF.
http://en.wikipedia.org/wiki/Brainfuck - Английская версия. Как всегда, полнее.
http://esoteric.voxelperfect.net/wiki/Brainfuck_algorithms - Набор алгоритмов на все случаи жизни.
http://community.livejournal.com/ru_brainfucker - ЖЖ-сообщество о BF.