ภาพรวม
บทความนี้สาธิตวิธีหาตัวเลข n หลักที่น้อยที่สุด ซึ่งหารด้วยทุกตัวในอาร์เรย์ลงตัว (คือหา LCM แล้วหาตัวคูณที่มี n หลัก)
ตัวอย่าง
arr = [12, 4, 5, 10, 9]
LCM = 180
n=2: 180 (3 หลัก? ไป 180 มี 3 หลัก) -> Wait, 180 เป็น 3 หลัก
n=2: ตัวเลข 2 หลักน้อยที่สุดที่หารลงตัว = ไม่มี (180 มี 3 หลัก)
n=3: 180
หมายเหตุ: โค้ดต้นฉบับมี Bug Logic - หา n-digit number แต่ LCM เองอาจมีหลักมากกว่า n
การนำไปใช้ (แก้ไข Logic)
const allDivides = (arr, num) => arr.every(el => num % el === 0);
const smallestMultiple = (arr, numDigits) => {
// หา LCM ของอาร์เรย์ก่อน
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
const lcm = (a, b) => (a * b) / gcd(a, b);
const arrayLCM = arr.reduce(lcm);
// หาตัวเลข n หลักน้อยที่สุด
const smallestN = Math.pow(10, numDigits - 1);
const largestN = Math.pow(10, numDigits) - 1;
// หาตัวคูณของ LCM ที่ >= smallestN
let multiple = Math.ceil(smallestN / arrayLCM) * arrayLCM;
if (multiple <= largestN) {
return multiple;
}
// ไม่มีตัวเลข n หลักที่หารลงตัว -> คืน LCM ตรงๆ (ตามโจทย์)
return arrayLCM;
};
console.log(smallestMultiple([12, 4, 5, 10, 9], 2)); // 180 (fallback)
console.log(smallestMultiple([12, 4, 5, 10, 9], 3)); // 180
console.log(smallestMultiple([12, 4, 5, 10, 9], 4)); // 1080
ผลลัพธ์
180 180
LCM (Least Common Multiple) Implementation
// Euclidean Algorithm สำหรับ GCD
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
// LCM ของ 2 ตัว
const lcm = (a, b) => (a / gcd(a, b)) * b; // ป้องกัน Overflow
// LCM ของอาร์เรย์
const lcmArray = (arr) => arr.reduce(lcm);
การประยุกต์ใช้
- Scheduling: หาเวลาที่ Event หลายอย่างตรงกัน (LCM of Periods)
- Gear Ratios: Mechanical Engineering
- Music: Rhythmic Alignment (Polyrhythms)
- Cryptography: RSA Key Generation
- Project Management: Task Synchronization
ข้อควรระวัง
- Overflow: a * b อาจเกิน Number.MAX_SAFE_INTEGER -> ใช้ BigInt
- Zero ในอาร์เรย์: LCM กับ 0 ไม่ได้定义 (คืน 0 หรือ Error)
- Negative Numbers: ใช้ Math.abs()
เวอร์ชัน BigInt
const lcmBigInt = (a, b) => (a / gcd(a, b)) * b;
const smallestMultipleBigInt = (arr, numDigits) => {
const arrayLCM = arr.map(BigInt).reduce(lcmBigInt);
const smallestN = 10n ** (BigInt(numDigits) - 1n);
const largestN = 10n ** BigInt(numDigits) - 1n;
let multiple = (smallestN + arrayLCM - 1n) / arrayLCM * arrayLCM; // Ceiling Division
return multiple <= largestN ? multiple : arrayLCM;
};