Pull to refresh

Comments 10

Конкретно для этой задаче - не проще сделать мэп с [m,n] -> value, и если в мэпе уже есть значение - возвращать его, а если нет - вызываться рекурсивно?

Мемоизация решает другой набор проблем с рекурсией. В данном случае она может ускорить функцию и немного отложить пробитие стека, но глобально проблему не решит.

наивная версия с мемоизацией
let cache = new Map();
let has = (m, n) => cache.get(m).has(n);
let get = (m, n) => cache.get(m).get(n);
let set = (m, n, value) => cache.get(m).set(n, value);

const ackermann1 = (m, n) => {
  if (!cache.has(m)) {
    cache.set(m, new Map());
  }

  if (!has(m, n)) {
    if (m === 0) {
      set(m, n, n + 1);
    } else if (n === 0) {
      set(m, n, ackermann1(m - 1, 1));
    } else {
      set(m, n, ackermann1(m - 1, ackermann1(m, n - 1)));
    }
  }
  
  return get(m, n);
};

В таком виде она будет проваливать стек при m = 3, n = 13.

Глубина стека - всего 16 элементов? Тут же в рекурсии в любой момент времени уменьшается или n, или m - значит, в любой момент времени глубина стека не более n+m.

Такая задача может по времени обламываться, т.к. без кэширования результатов "дерево" получается очень широкое.

Глубина стека - всего 16 элементов? Тут же в рекурсии в любой момент времени уменьшается или n, или m - значит, в любой момент времени глубина стека не более n+m.

Не уменьшается. ackermann(m - 1, ackermann(m, n - 1)) - здесь второй параметр может быть гораздо больше исходного n

Для ackermann(3, n) глубина рекурсии будет 2^(n+3)

Функция Аккермана славна тем, что даёт огромные значения для довольно скромных аргументов и огромную глубину рекурсии, почему удобна для подобных экспериментов.

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

К чему вообще все это? Хвостовая рекурсия решает стековые проблемы, так зачем огород городить?

Решает (но не в js, там нет этого). Однако в общем случае перековка рекурсии в хвостовую точно такая же, как в цикл. И не имеет смысла, если в языке есть цикл.

Хвостовая рекурсия решает стековые проблемы

Хвостовая рекурсия это по сути просто цикл. Соответственно, если что-то сложно написать с помощью цикла, будет сложно и с помощью хвостовой рекурсии (можете сами попробовать).

К чему вообще все это?

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

Таким образом на стандартных настройках стек стал больше в 2792 раза.

Почему так скромно получилось?

Не, это, конечно, сильно лучше, чем при стандартном подходе, но всё же скромно.

Отношение размера кучи к размеру стека ограничивает. У меня параметры ноды следующие: стек почти 1мб, куча чуть больше 4гб. Получается, верхняя граница это 4000. В статье вышло 2792, то есть, примерно, в 1.5 раза меньше максимально возможного

Sign up to leave a comment.

Articles