Якщо ви просто намагаєтеся порахувати, скільки разів воно зменшується, і конкретно не піклуєтесь про рекурсію ... ви можете просто видалити рекурсію. Наведений нижче код залишається вірним Оригінальній публікації, оскільки він не вважається 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)
є надмірним, оскільки*
оператор примушує значення до нумерації все одно. ;-)