Brainfuck, вероятно, это самый безумный язык
программирования, который встречается на
свете. Сам язык состоит всего из 8
операторов, которыми можно написать
практически любую программу, которую вы
хотите. Для работы вам понадобится:
компилятор или интерпретатор (приводятся в
конце статьи - компилятор на ассемблере,
интерпретатор Brainfuck-C); ASCII таблица; вероятно
калькулятор :).
Основы
Главная идея Brainfuck - манипулирование
памятью. Вам выдается 30.000 массив 1 байтовых
блоков, хотя на самом деле размер массива
зависит от компилятора или интерпретатора,
но стандартный размер - 30.000. Внутри этого
массива вы можете увеличивать указатель,
значение в ячейке и так далее. Для работы,
как я уже говорил, используется 8
операторов:
> = увеличение указателя памяти или
смещение право на 1 блок
< = уменьшение или смещение влево на 1 блок
+ = увеличение значения в ячейке памяти, на
которую ссылается указатель
- = соответственно уменьшение на единиц
[ = аналог цикла while(cur_block_value != 0)
] = если значение в ячейке на которую
указывает указатель не равно нулю, то
переход на [
, = аналог getchar(), ввод одного символа
. = аналог putchar(), вывод одного сивола на
кончоль
Вводные правил
- Любые символы кроме описанных выше
игнорируются - Все значения в памяти устанавливаются
на 0 в начале работы программы - Циклов может быть сколько угодно, однако
каждая [ должна заканчиваться]
И вернемся к нашим баранам. Напишем
простую программу:
[-]
Что делается? По идее открывается цикл,
уменьшается значение текущей ячейки на 1 и
цикл продолжается до тех пор, пока значение
не достигнет 0. Однако так как изначально
все значения в памяти и есть 0, цикл никогда
не начнется.
Напишем другую программу:
+++++[-]
На С это аналогично такой программе:
*p=+5;
while(*p != 0){
*p--;
}
В этой программе мы увеличили значение по
указателю на 5, потом открыли цикл, который
уменьшал значение до 0.
>>>>++
На выходе мы получим такой вид памяти.
Очевидно, что сначала мы увеличиваем
указатель на 4 и затем два раза увеличиваем
значение на 1 два раза. Разнообразим?
>>>>++<<+>>+
Получаем:
Опять же понятно, что сначала 2
записывается в четвертую ячейку, потом 1 во
вторую и затем еще раз 1 прибавляется к 4.
Давайте напишем программу, которая будет
уже выводить нечто в консоль, например
любимый всеми нами "Hello world". Выглядит
она так:
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.
+++++++..+++.[-]>++++++++[<++++>-] <.
>+++++++++++[<++++++++>-]<-.--------.+++
.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.
Круто? Настоящий Brainfuck... Разберем что
происходит. Надо помнить, что мы имеем дело
с кодами ASCII для вывода, так что надо
оперировать именно такими кодами.
Первая часть:
>+++++++++[<++++++++>-]<.
Сдвигаемся вправо, оставляя первую ячейку
пустой, записываем туда 9, открываем цикл. В
цикле смещаемся влево, записываем туда 8,
смещаемся вправо и уменьшаем значение на единицу.
Цикл идет до тех пор, пока во второй ячейке
не станет 0. Не слишком трудные вычисления
покажут, что в конце работы программы в
первой ячейки памяти будет 72, во второй 0.
Это код буквы Н, поэтому выводим ее в
консоль. Продолжаем для каждого символа и в
конце концов получаем заветные Hello world!
Занятно, не правда ли? 🙂
(Продолжение следует)