Алгоритм Divmod в brainfuck

Может кто-нибудь объяснить мне этот код? Я понимаю, что он делает, но я не понимаю, как это работает.

# >n 0 d
[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]
# >0 n d-n%d n%d n/d

person Dr. John A Zoidberg    schedule 12.01.2015    source источник


Ответы (1)


Вот что происходит:

# >n 0 d

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

Для облегчения понимания я буду использовать в качестве примера 25/4:

ptr 000 001 002 003 004 005 006
val 025 000 004 000 000 000 000

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

Эту строку можно разбить на части для облегчения наблюдения, но если вы просто используете ее, это будет волшебный цикл:

[->+>-

Эта часть вычитает делимое, добавляет его обратно в следующую ячейку для сохранения и вычитает делитель. Теперь память такая:

ptr 000 001 002 003 004 005 006
val 024 001 003 000 000 000 000

[>+>>]

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

ptr 000 001 002 003 004 005 006
val 024 001 003 001 000 000 000

Затем он перемещается на 2 шага вправо к ячейке 005, затем к 006 из-за промежуточного >, пропуская [+[-<+>]>+>>], так как ячейка пуста, затем обратно к ячейке 000 из-за этой строки:

<<<<<<

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

Пропустим несколько шагов и будем двигаться вперед, пока делитель не станет равным 0.

ptr 000 001 002 003 004 005 006
val 021 004 000 003 000 000 000

Он пропускает [>+>>], так как ячейка 2 сейчас пуста, а затем переходит к ячейке 003.

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

Поскольку 003 имеет значение, эта строка должна быть запущена. добавив единицу к значению, чтобы сделать его полным циклом, затем сдвиньте значение обратно к 002 с помощью [-<+>]. Указатель заканчивается на 003, поэтому он перемещается на 004 и добавляет значение на единицу, чтобы указать полный цикл и, следовательно, еще один к частному. Он движется к 006 и обратно к 000.

Повторяем все это дело, тогда получаем:

ptr 000 001 002 003 004 005 006
val 000 025 003 001 006 000 000

что похоже на последнюю строку

# >0 n d-n%d n%d n/d

поскольку цикл завершается, потому что 000 теперь пусто. n теперь полностью смещено к 001, 002 и 003 показывает циклический процесс делителя, когда n полностью обнулено. 004 показывает общее количество завершенных итераций цикла делителя.

person Logo    schedule 14.01.2015