Введение

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 можно написать любую программу…

Если вам понравился этот небольшой урок, хлопните в ладоши и оставьте комментарий.