Если вы просто пытаетесь подсчитать, сколько раз оно уменьшается, и не заботитесь о рекурсии конкретно ... вы можете просто удалить рекурсию. Приведенный ниже код остается верным Исходному сообщению, поскольку он не считается num <= 9
нуждающимся в сокращении. Следовательно, singleDigit(8)
будет иметь count = 0
и singleDigit(39)
будет count = 3
, так же, как OP и принятый ответ демонстрируют:
const singleDigit = (num) => {
let count = 0, ret, x;
while (num > 9) {
ret = 1;
while (num > 9) {
x = num % 10;
num = (num - x) / 10;
ret *= x;
}
num *= ret;
count++;
console.log(num);
}
console.log("Answer = " + num + ", count = " + count);
return num;
}
Нет необходимости обрабатывать числа 9 или меньше (т.е. num <= 9
). К сожалению, код OP будет обрабатываться, num <= 9
даже если он его не считает. Код выше не будет ни обрабатывать, ни считать num <= 9
. Это просто проходит через.
Я предпочитаю не использовать, .reduce
потому что выполнение математики выполнялось намного быстрее. И, для меня, легче понять.
Дальнейшее размышление о скорости
Я чувствую, хороший код тоже быстро. Если вы используете этот тип сокращения (который часто используется в нумерологии), вам может понадобиться использовать его для огромного количества данных. В этом случае скорость станет самым важным.
Использование обоих .map(Number)
и console.log
(на каждом этапе сокращения) очень и очень долго для выполнения и не нужно. Простое удаление .map(Number)
из OP ускорило его примерно в 4,38 раза. Удаление console.log
ускорило его настолько, что было почти невозможно правильно протестировать (я не хотел ждать этого).
Так что , похоже на customcommander ответ «s, не используя .map(Number)
ни console.log
и толкающие результаты в массив и использовать .length
для count
гораздо гораздо быстрее. К сожалению для ответа customcommander , использование функции генератора действительно очень медленно (этот ответ примерно в 2,68 раза медленнее, чем OP без .map(Number)
и console.log
)
Кроме того, вместо использования .reduce
я просто использовал фактическую математику. Это единственное изменение ускорило мою версию функции в 3,59 раза.
Наконец, рекурсия медленнее, она занимает место в стеке, использует больше памяти и имеет ограничение на количество повторений. Или, в этом случае, сколько шагов сокращения он может использовать, чтобы завершить полное сокращение. Развертывание рекурсии в итеративных циклах сохраняет все это в одном и том же месте в стеке и не имеет теоретического ограничения на количество шагов сокращения, которое можно использовать для завершения. Таким образом, эти функции здесь могут «уменьшить» почти любое целое число, ограниченное только временем выполнения и продолжительностью массива.
Все это в виду ...
const singleDigit2 = (num) => {
let red, x, arr = [];
do {
red = 1;
while (num > 9) {
x = num % 10;
num = (num - x) / 10;
red *= x;
}
num *= red;
arr.push(num);
} while (num > 9);
return arr;
}
let ans = singleDigit2(39);
console.log("singleDigit2(39) = [" + ans + "], count = " + ans.length );
// Output: singleDigit2(39) = [27,14,4], count = 3
Вышеуказанная функция работает очень быстро. Это примерно в 3,13 раза быстрее, чем OP (без .map(Number)
и console.log
), и примерно в 8,4 раза быстрее, чем ответ customcommander . Имейте в виду, что удаление console.log
из OP предотвращает создание числа на каждом шаге сокращения. Следовательно, здесь необходимо поместить эти результаты в массив.
PT
.map(Number)
является избыточным, поскольку*
оператор в любом случае приводит значения к числу. ;-)