Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

การหาตัวเลข n หลักที่หารด้วยทุกตัวในอาร์เรย์ลงตัว (LCM Application) ใน JavaScript

ภาพรวม

บทความนี้สาธิตวิธีหาตัวเลข 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;
};