Sadece kaç kez azaldığını saymaya çalışıyorsanız ve özellikle özyineleme konusunda umursamıyorsanız ... özyinelemeyi kaldırabilirsiniz. Aşağıdaki kod, Orijinal Posta'ya sadık kalmaya devam etmediği için sadık kalır num <= 9. Bu nedenle, singleDigit(8)sahip olacak count = 0ve singleDigit(39)olacak count = 3sadece OP ve kabul cevap sergilediklerini gibi:
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 veya daha az sayıları işlemek gereksizdir (yani. num <= 9). Ne yazık ki OP kodu num <= 9sayılmasa bile işleyecektir . Yukarıdaki kod hiç işlemeyecek veya sayılmayacaktır num <= 9. Sadece geçiyor.
Kullanmamayı tercih ediyorum .reduceçünkü gerçek matematiği yürütmek çok daha hızlıydı. Ve benim için anlaşılması daha kolay.
Hız hakkında daha fazla düşünme
İyi kodun da hızlı olduğunu hissediyorum. Bu tür bir indirgeme kullanıyorsanız (numerolojide çok kullanılır) büyük miktarda veri üzerinde kullanmanız gerekebilir. Bu durumda, hız en önemlisi olacaktır.
Her ikisini de kullanmak .map(Number)ve console.log(her azaltma adımında) yürütmek çok uzun ve gereksizdir. Sadece .map(Number)OP'den silmek yaklaşık 4.38x hızlandırdı. Silme console.logo kadar çok hızlandı ki düzgün test etmek neredeyse imkansızdı (Ben beklemek istemedim).
Yani, benzer customcommander 'ın cevabı, kullanmayan .map(Number)ne console.logve sonuçları bir diziye bastırıyor ve kullanma .lengthiçin countçok daha hızlıdır. Ne yazık ki customcommander'ın cevabı için bir jeneratör fonksiyonu kullanmak gerçekten çok yavaş (bu cevap OP olmadan yaklaşık 2.68x daha yavaş .map(Number)ve console.log)
Ayrıca, kullanmak yerine .reducegerçek matematiği kullandım. Bu tek değişiklik tek başına fonksiyonumun versiyonunu 3.59 kat artırdı.
Son olarak, özyineleme daha yavaştır, yığın alanı kaplar, daha fazla bellek kullanır ve kaç kez "tekrarlayabileceği" sınırına sahiptir. Ya da, bu durumda, tam indirgeme işlemini tamamlamak için kaç azaltma aşaması kullanabilir? Yinelemenizi yinelemeli döngülere yaymak, hepsini yığın üzerinde aynı yerde tutar ve bitirmek için kaç azaltma adımının kullanılabileceği konusunda teorik bir sınırlama yoktur. Böylece, bu işlevler, yalnızca yürütme süresi ve bir dizinin ne kadar uzun olabileceği ile sınırlı olan hemen hemen her boyutta tamsayıyı "azaltabilir".
Tüm bunları akılda tutarak ...
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
Yukarıdaki fonksiyon son derece hızlı çalışır. Bu OP den (olmadan hızlı 3.13x hakkındadır .map(Number)ve console.logdaha hızlı) ve 8.4x hakkında customcommander 'ın cevabı. OP'den silme işleminin console.logher azaltma adımında bir sayı üretmesini engellediğini unutmayın . Bu nedenle, bu sonuçları bir dizi haline getirme ihtiyacı.
PT
.map(Number)çünkü*operatör değerleri yine de sayıya zorlar. ;-)