Скачать бесплатно книги - программирование.

Скачать бесплатно книги - программирование.


загрузка...






Программирование

Программирование

Книги, статьи, руководства и примеры

Автор: Дегтярев Михаил.

Язык программирования Brainfuck Брайнфак

Brainfuck (мозгоеб) является минималистским языком программирования созданным Урбан Мюллер где-то в 1993 году. Язык иногда называют brainf*ck, brainf***, или просто BF в приличном обществе. Программирование для начинающих.
Достижением Мюллера было создание простого языка программирования Тьюринга, который может быть реализован с наименьшим из возможных компиляторов . Язык состоит из восьми управляющих операторов. Оригинальный компилятор 2-ой версии, написанный для Amiga , составлял 240 байт. Программирование для чайников.
Как следует из названия, Brainfuck (мозгоебские) программы, как правило, трудно понять. Тем не менее, это машина Тьюринга , и поэтому Brainfuck, может выполнить любые вычислительные задачи. Пренебрегая очевидной трудностью в программировании определенных задач на языке Brainfuck, почти любая задача под силу этому языку/, не говоря уже про основы рограммирования.
Язык основан на простой модели машины, состоящей, помимо программы, из массива обнуленных байтов, указателя на массив (инициализируется и указывает на первый байт массива), и два потока байт для ввода и вывода данных.
Восемь управляющих операторов языка, каждый из которых состоит из одной буквы, являются следующие:

Символ 	Смысл 
> 		приращение указателя. 
< 		декремент указателя. 
+ 		приращение байт на указатель. 
- 		декремента байтов на указатель. 
. 		Выход из байта указателя (ASCII). 
, 		вклад в байт по указателю (ASCII). 
[ 		Перейти вперед на оператор после соответствующего ] , если байт на указатель равен нулю. 
] 		Перейти обратно на оператор после соответствующего [ если байта на указатель не равно нулю. 

(В качестве альтернативы оператор ] может быть интерпетирован как "перейти обратно к соответствующему [ ". Это краткоее, но менее симметричное и эффективное по времени. Обе версии эквивалентного поведения Brainfuck программы.)
(Третья эквивалентная версия, мало употребляется, является: [ означает "скачок вперед в соответствующие ] ", и ] означает "возврат на заявление после соответствующего [ если байт на указателе отличный от нуля ".)
Brainfuck программы могут быть переведены на язык C с помощью следующей замены, предполагая, ptr имеет тип char* :

BrainfuckC
> ++ptr;
< --ptr;
+ ++*ptr;
- --*ptr;
. putchar(*ptr);
, *ptr = getchar();
[ while (*ptr) {
] }

Примеры
Привет мир!
Программа, которая печатает "Hello World!" на экране:

++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.

Нулевая текущая позиция
[-]

Работа с символами (ввод-вывод)
,.

,[.,]

Непрерывный цикл, который принимает ввод с клавиатуры и отображает его на экране. Отметим, что это предполагает ввод 0 как сигнал конца ввода; в разных реализациях этот момент может изменяться. Версии для -1 и "никаких изменений", будут выглядеть как " ,+[-.,+] "и" ,[.[-],] ".
Манипуляции с указателем
>,[.>,]

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

Сложение
[->+<]

Это добавляет значение текущего местоположения (разрушительно, он остается в нуле) к значению в следующей ячейке.

Условные операторы
,----------[----------------------.,----------]
Этот код получает буквы в нижнем регистре при вводе с клавиатуры и переводит в верхний регистр. Для выхода нажмите клавишу ввода.
Во-первых, для получения первого символа используется «,» и сразу же вычитается 10 от него. (Большинство, но не все, Brainfuck программы используют 10 для возвращения результата.) Если пользователь нажмет ввод, оператор цикла ( [ ) прыгнет в конец прошлого цикла, потому что мы установили значение первого байта в ноль. Если входной символ не был 10, мы смело предполагаем, что было введена строчная буква, и входим в цикл, в котором мы вычитаем еще 22 от него, в общей сложности 32, что представляет собой разницу между ASCII строчными и заглавными буквами.
Следующим действием мы вывели на экран. Теперь ввод следующего символа, и снова вычесть 10. Если этот символ был перевод строки, мы выходим из цикла, в противном случае мы возвращаемся к началу цикла, вычитаем еще 22, выводим на экран, и так далее. Когда мы выходим из цикла, программа завершается, так как команд больше не осталось.
Кроме того
,>++++++[<-------->-],,[<+>-],<.>.

Эта программа добавляет два однозначных числа и отображает результат правильно, если этот результат тоже имеет только одну цифру:
4 +3
7

(Теперь все становится немного сложнее. Мы можем также обратиться к байту в массив [0], [1], [2], и так далее.)
Первый номер вводится в [0], и 48 из него вычитается, чтобы исправить его (ASCII коды для цифр 0-9 являются 48-57). Это делается, положив 6 в ячейку [1] и с помощью цикла вычесть 8 из [0] и повтоярется много раз. (. Это распространенный метод сложения или вычитания больших чисел) Далее, знак плюс вход в [1], затем второй номер на вход, перезаписи знаком плюс.
Следующий цикл [<+>-] делает реальную работу, перемещение второго число на первое, сложив их вместе и обнуленив [1]. Каждый раз, он добавляет единицу к [0] и вычитает один из [1], так что к тому времени [1] обнуляется, так как многие были добавлены [0], как были удалены из [1]. Теперь возврат вклада в [1]. (Мы не проверяем ошибки входных данных во всех случаях.)
Затем указатель перемещается обратно на [0], который затемвыводится. ([0] в настоящее время a + (b + 48), так как мы не правильно b, который совпадает с (a + b) + 48, которая является тем, что мы хотим получить.) Теперь указатель перемещается в [1] , в которой хранится значение окончания программы, введенного с клавиатуры, что приводит к завершению программы.

Умножения

,,>++++++++[<------<------>>-]
 <<[>[>+>+<<-]>>[<<+>>-]<<<-]
 >>>++++++[<++++++++>-],<.>. 

Как и в предыдущем примере, но теперь умножаем, а не складываем.
Первый номер вводится в [0], звездочки, а затем второй номер вводятся в [1], и оба номера исправляются с помощью вычитания 48.
Теперь мы вступаем в основной цикл умножения. Основная идея в том, что каждый раз через него мы вычтем одно из [0] и добавить [1] , текущая сумма хранится в [2]. В частности: первый внутренний движется схема [1] на обе [2], [3], в то время как обнуление [1]. (Это основной способ, чтобы дублировать номер.) Следующего внутреннего движется схема [3] обратно в [1], обнуление [3]. Тогда вычитается из [0], а внешний цикл заканчивается. На выходе из этой петли, [0] равен нулю, [1] до сих пор второй номер в ней, и [2] произведения двух чисел. (Если бы мы заботились о сохранении первого числа, мы могли бы добавить от одного до [4] каждый раз через внешний цикл, а затем переместить значение из [4] к [0] позже.)
Теперь мы добавляем 48 для завершения, вход возвращения в [3], выход ASCII, а затем выход возвращения мы просто сохраняем.





Далее