Jika Anda hanya mencoba menghitung berapa kali berkurang dan tidak peduli tentang rekursi secara khusus ... Anda bisa menghapus rekursi itu. Kode di bawah ini tetap setia ke Posting Asli karena tidak dianggap num <= 9
perlu dikurangi. Oleh karena itu, singleDigit(8)
akan memiliki count = 0
, dan singleDigit(39)
akan memiliki count = 3
, seperti OP dan jawaban yang diterima menunjukkan:
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;
}
Tidak perlu memproses angka 9 atau kurang (mis. num <= 9
). Sayangnya kode OP akan diproses num <= 9
walaupun tidak dihitung. Kode di atas tidak akan memproses atau menghitungnum <= 9
sama sekali. Itu hanya melewati itu.
Saya memilih untuk tidak menggunakan .reduce
karena melakukan matematika sebenarnya jauh lebih cepat untuk dieksekusi. Dan, bagi saya, lebih mudah dipahami.
Pemikiran lebih lanjut tentang kecepatan
Saya merasa kode yang baik juga cepat. Jika Anda menggunakan jenis pengurangan ini (yang banyak digunakan dalam numerologi), Anda mungkin perlu menggunakannya pada sejumlah besar data. Dalam hal ini, kecepatan akan menjadi yang terpenting.
Menggunakan keduanya .map(Number)
dan console.log
(pada setiap langkah reduksi) keduanya sangat panjang untuk dieksekusi dan tidak perlu. Cukup menghapus .map(Number)
dari OP, mempercepatnya sekitar 4,38x. Menghapus begitu console.log
cepat sehingga hampir tidak mungkin untuk menguji dengan benar (saya tidak ingin menunggu untuk itu).
Jadi, mirip dengan jawaban customcommander , tidak menggunakan .map(Number)
atau console.log
mendorong hasil ke dalam array dan menggunakan .length
untuk count
jauh lebih cepat. Sayangnya untuk jawaban customcommander , menggunakan fungsi generator benar-benar lambat (jawaban itu sekitar 2.68x lebih lambat daripada OP tanpa .map(Number)
dan console.log
)
Juga, alih-alih menggunakan .reduce
saya hanya menggunakan matematika yang sebenarnya. Perubahan tunggal ini saja mempercepat versi fungsi saya dengan faktor 3,59x.
Akhirnya, rekursi lebih lambat, membutuhkan ruang stack, menggunakan lebih banyak memori, dan memiliki batas berapa kali dapat "berulang". Atau, dalam hal ini, berapa banyak langkah reduksi yang dapat digunakan untuk menyelesaikan reduksi penuh. Meluncurkan rekursi Anda ke loop berulang membuat semuanya berada di tempat yang sama di tumpukan dan tidak memiliki batasan teoritis tentang berapa banyak langkah reduksi yang dapat digunakan untuk menyelesaikannya. Dengan demikian, fungsi-fungsi ini di sini dapat "mengurangi" hampir semua bilangan bulat ukuran, hanya dibatasi oleh waktu eksekusi dan berapa lama array dapat.
Semua ini dalam pikiran ...
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
Fungsi di atas berjalan sangat cepat. Ini sekitar 3.13x lebih cepat dari OP (tanpa .map(Number)
dan console.log
) dan sekitar 8.4x lebih cepat dari jawaban customcommander . Ingatlah bahwa menghapus console.log
OP mencegahnya menghasilkan angka pada setiap langkah pengurangan. Oleh karena itu, kebutuhan di sini untuk mendorong hasil ini ke dalam array.
PT
.map(Number)
redundan karena*
operator memaksa nilai ke angka. ;-)