Якщо ви просто намагаєтеся порахувати, скільки разів воно зменшується, і конкретно не піклуєтесь про рекурсію ... ви можете просто видалити рекурсію. Наведений нижче код залишається вірним Оригінальній публікації, оскільки він не вважається num <= 9необхідним скорочення. Таким чином, singleDigit(8)буде count = 0, і singleDigit(39)буде count = 3, як і ОП та прийнята відповідь демонструють:
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)з ОП скоротило його приблизно на 4.38 разів. Видаливши console.logйого так швидко, майже неможливо було правильно перевірити (я не хотів його чекати).
Таким чином, подібно до відповіді customcommander , не використовувати .map(Number)ні console.logі не виштовхувати результати в масив і використовувати .lengthдля countнабагато набагато швидше. На жаль для відповіді customcommander , використання функції генератора дійсно дуже повільне (ця відповідь приблизно на 2.68x повільніше, ніж OP без .map(Number)і console.log)
Крім того, замість використання .reduceя просто використав фактичну математику. Сама ця зміна прискорила мою версію функції в 3,5 раза.
Нарешті, рекурсія проходить повільніше, вона займає простір у стеці, використовує більше пам’яті та обмежує кількість разів, коли вона може «повторюватися». Або, у цьому випадку, скільки кроків зменшення він може використати для завершення повного зменшення. Розгортання вашої рекурсії до ітеративних циклів зберігає це все на тому самому місці стека і не має теоретичного обмеження, скільки кроків зменшення може використовувати для завершення. Таким чином, ці функції тут можуть «зменшити» майже будь-яке розмірне ціле число, лише обмежене часом виконання та тим, наскільки тривалим може бути масив.
Все це на увазі ...
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 рази швидше, ніж ОП (без .map(Number)і console.log) і приблизно в 8,4 рази швидше, ніж відповідь користувача. Майте на увазі, що видалення console.logз ОП не дозволяє йому створювати число на кожному кроці скорочення. Отже, необхідність просунути ці результати в масив.
PT
.map(Number)є надмірним, оскільки*оператор примушує значення до нумерації все одно. ;-)