Обнулить произвольно большую ячейку в Brainf ***

28

Ваша задача состоит в том, чтобы написать кусок кода , который нули текущей ячейки в варианте Brainfuck , что каждая ячейка может содержать подписанное целое сколь угодно большой величину, вместо нормальных 0 до 255.

Вы можете предположить, что слева находятся l ячеек и r ячеек справа от текущей ячейки, которые изначально равны нулю. Ваша программа может получить доступ только к этим ячейкам l + r +1. После того, как ваш код заканчивается, он должен оставить ноль дополнительных ячеек l + r и указатель на текущую ячейку в исходной позиции.

Вы не можете использовать любой ввод / вывод.

Код с наименьшим l + r выигрывает. Если есть связь, выигрывает самый короткий код. Рекомендуется также указать временную сложность вашей программы для справки, где n - абсолютное значение исходного целого числа в текущей ячейке.

Полезные инструменты

Вы можете протестировать программу Brainfuck в этом варианте, используя этот интерпретатор на TIO от mbomb007 .

Вы также можете использовать переводчика в этом ответе по будке (другие ответы Python, вероятно, также работают, но я не проверял).

jimmy23013
источник
Я пометил это code-golf, потому что я думаю, что мы быстро достигнем оптимального l + r.
jimmy23013,
2
Похоже, из вашего комментария вы имели в виду произвольно большое целое число, которое может быть положительным или отрицательным. Это разница в английском диалекте для некоторых людей, поэтому может быть полезно уточнить, что он может быть очень позитивным или очень негативным.
Исаак
4
@ jimmy23013 У вас есть переводчик BF с подписанными ячейками, который мы можем использовать для этого?
mbomb007
@ mbomb007 codegolf.stackexchange.com/a/3085/25180, но, вероятно, слишком гольфы ...
jimmy23013
1
@ Мего, почему? В «реальной» задаче вы также должны получить оптимальный l + r, что, вероятно, затруднит уменьшение размера кода.
jimmy23013,

Ответы:

17

l + r = 0 + 2 = 2, 55 53 51 байт

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

l + r = 1 + 2 = 3, 46 44 байта

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

Мой собственный алгоритм. Указатель должен начинаться с номера, который нужно обнулить. Временная сложность O (n ^ 2).

Как это работает:

  • Начнем с номера n.
  • Мы увеличиваем единицу, так что число становится n+1.
  • Мы уменьшаем два, так что число становится n+1-2 = n-1
  • Мы увеличиваем три, так что число становится n-1+3 = n+2.
  • Мы уменьшаем четыре, так что число становится n+2-4 = n-2.

Мы повторяем этот процесс, увеличивая / уменьшая каждый шаг, пока не получим ноль.

Юнг Хван Мин
источник
2
Именно алгоритм, который я придумал после того, как прошел этап «это даже невозможно»: P
ETHproductions
9

l + r = 0 + 2 = 2; 58 байт

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

Сложность O (n ^ 2).

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

p='''
>+<
[
>
[<->>+<-]
>+<
<[>]>
[<<+>+>-]
<
[->+<]
>[<]>
+ [-<+>]
<<
]
> [-] <
'''

p = ''.join(p.split())

cpp = '''
#include <bits/stdc++.h>
using namespace std;
void test(int q) {
long long t[3] = {q, 0, 0};
int i = 0;
ZZZ
printf("q=%d %lld %lld %lld\\n", q, t[0], t[1], t[2]);
}
int main() {
while(true) {
    int q; cin >> q; test(q);
}
}
'''

d = {
'>': '++i; assert(i<3);',
'<': '--i; assert(i>=0);',
'+': '++t[i];',
'-': '--t[i];',
'[': 'while(t[i]){',
']': '}',
}

print cpp.replace('ZZZ', ''.join(d[c] for c in p))
feersum
источник
Вы можете проверить это с помощью только что созданного мной переводчика. Смотрите комментарий
mbomb007
Похоже, это работает для меня.
mbomb007
2
Это должно быть оптимальным l + r. Быстрое доказательство того, что 1 невозможно: в каждой точке, в которой запасная ячейка достигает нуля, вы можете хранить только конечное количество данных в дополнение к значению исходной ячейки (в положении головки ленты и указателе инструкций), что означает, что Вы ограничены в том, как далеко вы можете отрегулировать основную ячейку от этой точки, по крайней мере, в одном направлении.
@ ais523 Могут быть и другие эквивалентные. Было бы интересно, если кто-то создаст l + r = 1 + 1.
mbomb007