ভূমিকা
একটি সংখ্যা অ্যারে দেওয়া থাকলে, প্রতিটি সংখ্যার ফ্যাক্টোরিয়াল (factorial) গণনা করে একটি নতুন অ্যারে রিটার্ন করার ফাংশন। রিকারসিভ ফ্যাক্টোরিয়াল ফাংশন এবং `map()` ব্যবহার করা হয়েছে।
সম্পূর্ণ কোড
const arr = [4, 8, 2, 7, 6, 20, 11, 17, 12, 9];
const factorial = (num, fact = 1) => {
if (num) {
return factorial(num - 1, fact * num);
}
return fact;
};
const factorialArray = arr => arr.map(element => factorial(element));
console.log(factorialArray(arr));
আউটপুট
[
24, 40320, 2, 5040, 720,
2432902008176640000, 39916800,
355687428096000, 479001600, 362880
]
কোড ব্যাখ্যা
রিকারসিভ ফ্যাক্টোরিয়াল
- টেইল রিকারশন: `fact` আর্গুমেন্টে আকুমুলেট করা হয় (টেইল কল অপ্টিমাইজেশনের সুযোগ)
- বেস কেস: `num === 0` হলে `fact` রিটার্ন
- রিকারসিভ স্টেপ: `factorial(num-1, fact*num)`
অ্যারে ম্যাপিং
- `arr.map(element => factorial(element))` - প্রতিটি এলিমেন্টে ফ্যাক্টোরিয়াল প্রয়োগ
⚠️ বড় সংখ্যার সমস্যা (Integer Overflow)
JavaScript-এ নম্বর ৬৪-বিট ফ্লোটিং পয়েন্ট (IEEE 754)। নিরাপদ ইন্টিজার রেঞ্জ: Number.MAX_SAFE_INTEGER = 2^53 - 1 = 9007199254740991।
- 21! = 51090942171709440000 > MAX_SAFE_INTEGER
- 20! = 2432902008176640000 < MAX_SAFE_INTEGER ✓
- 21! ও তার উপরে প্রিসিশন হারাবে
উন্নত সমাধান: BigInt (ES2020)
const factorialBigInt = (n) => {
if (n <= 1n) return 1n;
return n * factorialBigInt(n - 1n);
};
const factorialArrayBigInt = arr =>
arr.map(n => factorialBigInt(BigInt(n)).toString());
console.log(factorialArrayBigInt([20, 21, 25]));
// ["2432902008176640000", "51090942171709440000", "15511210043330985984000000"]
আইটেরেটিভ ফ্যাক্টোরিয়াল (স্ট্যাক সেফ)
const factorialIterative = (n) => {
let result = 1;
for (let i = 2; i <= n; i++) result *= i;
return result;
};
// BigInt সংস্করণ
const factorialIterativeBigInt = (n) => {
let result = 1n;
for (let i = 2n; i <= n; i++) result *= i;
return result;
};
মেমোইজেশন (ক্যাশিং) - রিপিটেড কলের জন্য
const factorialMemo = (() => {
const cache = { 0: 1, 1: 1 };
return (n) => {
if (cache[n] !== undefined) return cache[n];
return cache[n] = n * factorialMemo(n - 1);
};
})();
স্টারলিং আপক্সিমেশন (বড় n-এর জন্য আনুমানিক)
const stirlingApprox = (n) =>
Math.sqrt(2 * Math.PI * n) * Math.pow(n / Math.E, n);
// 20! ≈ 2.43e18 (actual: 2.4329e18) - খুব কাছাকাছি
সারাংশ
- ছোট সংখ্যা (≤20): সাধারণ রিকারসিভ/ইটেরেটিভ OK
- বড় সংখ্যা (>20): **BigInt বাধ্যতামূলক**
- বারবার কল: মেমোইজেশন ব্যবহার করুন
- প্রোডাকশনে: ইটেরেটিভ + BigInt সেরা