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 = 0
ve singleDigit(39)
olacak count = 3
sadece 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 <= 9
sayı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.log
o 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.log
ve sonuçları bir diziye bastırıyor ve kullanma .length
iç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 .reduce
gerç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.log
daha hızlı) ve 8.4x hakkında customcommander 'ın cevabı. OP'den silme işleminin console.log
her 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. ;-)