কম্পিউটার টিউটোরিয়াল

C++ দিয়ে সবচেয়ে বড় সাবসেট বের করা যাতে প্রতিটি জোড়ার যোগফল প্রাইম (Prime)

দেওয়া অ্যারেতে থেকে সবচেয়ে বড় সাবসেট (subset) বের করতে হবে যাতে সাবসেটের প্রতিটি জোড়ার (pair) যোগফল একটি প্রাইম সংখ্যা (prime number) হয়। ধরি সর্বোচ্চ উপাদান ১০০০০০। উদাহরণ −

ইনপুট: nums[] = { 3, 2, 1, 1 } আউটপুট: size = 3, subset = { 2, 1, 1 } ব্যাখ্যা: সম্ভাব্য সাবসেট: {3, 2}, {2, 1}, {2, 1, 1}। {2, 1, 1}-এ (2,1) জোড়ার যোগফল ৩ (প্রাইম), (1,1) জোড়ার যোগফল ২ (প্রাইম)।
ইনপুট: nums[] = {1, 4, 3, 2} আউটপুট: size = 2, subset = {1, 4} ব্যাখ্যা: সাবসেট: {1, 4}, {4, 3}, {3, 2} সবই সাইজ ২, যেকোনো একটি নেওয়া যায় যেমন 1+4=5 (প্রাইম)।
সমাধানের পদ্ধতি

জোড়ার যোগফল প্রাইম কিনা চেক করতে প্রথমে দেখতে হবে যোগফল বিজোড় নাকি জোড়, কারণ ২ ছাড়া কোনো জোড় সংখ্যা প্রাইম নয়। দুটি সংখ্যার যোগফল জোড় হয় যদি দুটোই জোড় হয় বা দুটোই বিজোড় হয়।

এই সমস্যায় আমরা তিনটি সংখ্যা x, y, z ধরি যেকোনো দুটি যেন জোড় বা বিজোড় হয়। তারপর এই সাবসেটকে প্রাইম যোগফল জোড়া জন্য চেক করব, যা সম্ভব যদি −

  • সাবসেটে কিছু ১ (ones) থাকে এবং কিছু অন্য সংখ্যা থাকে যাতে NUM + 1 প্রাইম হয়।

  • বা সাবসেটে শুধু দুটি সংখ্যা থাকে যাদের যোগফল প্রাইম।

উদাহরণ
  #include <bits/stdc++.h> using namespace std; #define M 100001 bool check_prime[M] = { 0 }; int sieve_of_eratosthenes(){     for (int p = 2; p * p < M; p++){         if (check_prime[p] == 0){ // মার্ক করা নেই             for (int i = p * 2; i < M; i += p)             check_prime[i] = 1; // মাল্টিপ্লাস মার্ক         }     }     return 0; } int main(){     sieve_of_eratosthenes();     int nums[] = { 3, 2, 1, 1 };     int n = sizeof(nums) / sizeof(nums[0]);     int ones = 0;     for (int i = 0; i < n; i++) if (nums[i] == 1) ones++;     // ১ আছে এবং ১ ছাড়া অন্য উপাদানও আছে     if (ones > 0){         for (int i = 0; i < n; i++){             if ((nums[i] != 1) && (check_prime[nums[i] + 1] == 0)){                 cout << ones + 1 << endl;                 for (int j = 0; j < ones; j++) cout << 1 << " ";                 cout << nums[i] << endl; return 0;         }         }     }     // শুধু ১-ই থাকলে     if (ones >= 2){         cout << ones << endl;         for (int i = 0; i < ones; i++) cout << 1 << " ";         cout << endl; return 0;     }     // ১ নেই     for (int i = 0; i < n; i++){         for (int j = i + 1; j < n; j++){             if (check_prime[nums[i] + nums[j]] == 0){                 cout << 2 << endl;                 cout << nums[i] << " " << nums[j] << endl; return 0;             }         }     }     // শুধু এক এলিমেন্ট থাকলে     cout << -1 << endl; return 0; }
আউটপুট
3 1 1 2
কোডের ব্যাখ্যা
  • প্রথমে অ্যারেতে ১ (ones) এর সংখ্যা গড়ে নেওয়া।

  • যদি ১ থাকে (>0), তবে অ্যারে ট্রাভার্স করে ১ ছাড়া প্রতিটি উপাদানের সাথে ১ যোগ করলে প্রাইম হয় কিনা চেক করা। হ্যাঁ হলে (ones + 1) সাইজ এবং সব ১ ও সেই সংখ্যা প্রিন্ট।

  • যদি শুধু ১-ই থাকে (ones >= 2), তবে সব ১ প্রিন্ট (যেহেতু ১+১=২ প্রাইম)।

  • যদি ১ নেই, তবে সব জোড়া চেক করা যাদের যোগফল প্রাইম।

  • অন্যথায় -1 প্রিন্ট।

উপসংহার

এই টিউটোরিয়ালে আমরা একটি অ্যারেতে থেকে সবচেয়ে বড় সাবসেট বের করার সমস্যা আলোচনা করেছি যাতে প্রতিটি জোড়ার যোগফল প্রাইম। এর্যাটোस्थেনিস ছাঁনী (Sieve of Eratosthenes) এবং অ্যারেতে ১-এর সংখ্যা চেক করে সমাধান করা হয়েছে। এই সমস্যার C++ প্রোগ্রামও দেওয়া আছে যা C, Java, Python ইত্যাদি ভাষায়ও করা যাবে। আশা করি আপনি এই টিউটোরিয়ালটি সহায়ক পাবেন।

  1. ব্যালেন্সড BST-এ দেওয়া সমের সাথে একটি জোড়া খুঁজে বের করা C++-তে

  2. C++-এ প্রাইম P-এর পরের প্রাইম নম্বর जिनका যোগফল S

  3. C++-এ প্রাইম স্ট্রিং (ASCII ভ্যালু যোগফল প্রাইম কিনা)

  4. C++-এ দেওয়া যোগফলের সাথে সর্বোচ্চ আকারের সাবসেট