Введение
BrainFuck — язык программирования, созданный Урбаном Мюллером.
Я недавно узнал об этом и подумал, что создам свой собственный учебник по нему, рассказывая об основах, а также о том, как кодировать более сложные программы и даже свой собственный компилятор.
Говоря о компиляторах… вам понадобится один для начала. Это мой любимый: https://copy.sh/brainfuck/
Вам также будет полезна таблица ASCII. Вот мой любимый:
О BrainFuck
BrainFuck полностью посвящен манипулированию памятью. Вам дан оооочень длинный массив из 30 000 байтов, для всех которых задано значение 0, с указателем на первый байт.
Операторы
Всего 8 операторов. Это как… ничего! Вот они:
+ - > < [ ] . ,
Просто, верно? Пройдемся по всем…
Оператор +
Оператор + просто добавляет 1 к текущему байту.
Оператор
Оператор - вычитает 1 из текущего байта.
Оператор
Оператор › перемещает указатель вперед к следующему байту.
Оператор
Оператор ‹ перемещает указатель назад к предыдущему байту.
Операторы [ и ]
Операторы [ и ] являются операторами цикла. Если текущий байт не равен 0, цикл запускается и повторяется до тех пор, пока текущий байт не станет равным 0.
Вот эквивалент Python:
while current_byte != 0: # do stuff
Итак, если мы напишем этот код:
[+]
Мы бы получили это:
Байт увеличивается до 1… затем 2… 3… 4… 5… 255… и снова до 0.
Поскольку каждый блок памяти представляет собой всего лишь байт, диапазон чисел составляет только 0–255, поэтому, когда он достигает 255, он возвращается к 0.
. оператор
. оператор является оператором вывода. Он выводит текущий десятичный байт, преобразованный в его символ ASCII.
Допустим, у нас есть этот код:
+++++++++++++++++++++++++++++++++
Это память:
И это вывод:
!
Преобразование 33 в символ ASCII равно !
Оператор
Оператор , является оператором ввода. Он принимает ввод от пользователя, преобразует его в байтовую десятичную форму и помещает в текущий байтовый блок памяти.
Допустим, у нас есть этот код:
+++,
Это память:
Это вывод (запрашиваемый ввод):
_
И допустим, мы вводим цифру 8, теперь это память:
Введенный символ ASCII, 8, преобразуется в его десятичное число байтов, 56, и перезаписывает текущий блок памяти.
Основной вывод
Вывод символов с помощью операторов + и - может очень быстро стать очень утомительным. Если бы мы хотели вывести букву H, это был бы код:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
Если бы мы хотели вывести Hello World!, это был бы код:
++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++.+++++++++++++++++++++++++++ ++.+++++++..+++.---------------------------------- ---------------------------------------------.++++ ++++++++++++++++++++++++++++++++++++++++++++++++++ +.++++++++++++++++++++++++.+++.------.--------.--- -------------------------------------------------- --------------.
Поэтому я разработал простой скрипт на Python для генерации BrainFuck гораздо более простым способом… с использованием циклов!
Мой код
Вот мой генератор BrainFuck:
def brainfuck(string, clearmemory): import math brainfuck_full = "" prev_ascii = 0 for char in string: # find decimal decimal = ord(char) - prev_ascii # check decimal for =0, =1, =-1, <0, >0 if decimal == 0: brainfuck_full += "." prev_ascii = ord(char) continue elif decimal == 1: brainfuck_full += "+." prev_ascii = ord(char) continue elif decimal == -1: brainfuck_full += "-." prev_ascii = ord(char) continue elif decimal < 0: decimal = abs(decimal) negativeBool = True elif decimal > 0: negativeBool = False # list factors factors = [] for i in range(1, decimal + 1): if decimal % i == 0: factors.append(i) # check if prime if len(factors) == 2: if negativeBool: brainfuck = "" for _ in range(decimal): brainfuck += "-" brainfuck += "." prev_ascii = ord(char) brainfuck_full += brainfuck continue else: brainfuck = "" for _ in range(decimal): brainfuck += "+" brainfuck += "." prev_ascii = ord(char) brainfuck_full += brainfuck continue # check if square, find median(s) root = math.sqrt(decimal) if int(root + 0.5) ** 2 == decimal: nums = (factors[int((len(factors)/2)-0.5)], factors[int((len(factors)/2)-0.5)]) else: nums = (factors[int(len(factors)/2)], factors[int((len(factors)/2)-1)]) # generate brainfuck if negativeBool: brainfuck = f">" for _ in range(nums[0]): brainfuck += "-" brainfuck += "[<" for _ in range(nums[1]): brainfuck += "-" brainfuck += ">+]<." else: brainfuck = f">" for _ in range(nums[0]): brainfuck += "+" brainfuck += "[<" for _ in range(nums[1]): brainfuck += "+" brainfuck += ">-]<." prev_ascii = ord(char) brainfuck_full += brainfuck # clear memory if clearmemory: # list factors factors = [] for i in range(1, prev_ascii + 1): if prev_ascii % i == 0: factors.append(i) # check if prime if len(factors) == 2: brainfuck = "" for _ in range(decimal): brainfuck += "-" brainfuck += "." brainfuck_full += brainfuck # check if square, find median(s) root = math.sqrt(prev_ascii) if int(root + 0.5) ** 2 == prev_ascii: nums = (factors[int((len(factors)/2)-0.5)], factors[int((len(factors)/2)-0.5)]) else: nums = (factors[int(len(factors)/2)], factors[int((len(factors)/2)-1)]) # generate ascii brainfuck = f">" for _ in range(nums[0]): brainfuck += "-" brainfuck += "[<" for _ in range(nums[1]): brainfuck += "-" brainfuck += ">+]<." brainfuck_full += brainfuck return f"{brainfuck_full}\n\nCreated by Aaron Chauhan"
А вот и мой интерпретатор BrainFuck: https://github.com/aaronjc15128/BrainFuck-Interpreter/blob/main/brainfuck_interpreter.py
Заворачивать
Я подумал, что поделюсь своим опытом работы с BrainFuck и основами. Как и в случае с любым другим языком программирования, здесь есть огромный айсберг, который нужно исследовать, на BrainFuck можно написать любую программу…
Если вам понравился этот небольшой урок, хлопните в ладоши и оставьте комментарий.