সরাসরি পর্বে যান
পর্ব ৩৩ · ৮৩-এর মধ্যে · মডিউল ৬

Permutation আর combination

Permutations and Combinations — r-Permutations, r-Combinations, Combinatorial Proofs, Arrangements with Repeated Objects, Circular Seating and Selection with Restrictions

Taught in Bangla, this lesson separates permutations from combinations by asking whether order changes the outcome. It proves the P(n, r) and C(n, r) formulas from the product and division rules, gives algebraic and combinatorial proofs of C(n, r) = C(n, n - r), and counts arrangements of words with repeated letters, circular seatings and teams with restrictions such as "at least four bowlers". In-page Python with itertools brute-forces every formula and exposes the overcounting trap.

এই পর্বে যা শিখবেন

  • r-permutation আর r-combination-এর নিখুঁত সংজ্ঞা, আর কোন প্রশ্নে কোনটি খাটে তা চেনার উপায়
  • P(n, r) আর C(n, r)-এর সূত্র গুণের নিয়ম আর ভাগের নিয়ম দিয়ে প্রমাণ
  • C(n, r) = C(n, n − r)-এর বীজগাণিতিক আর combinatorial প্রমাণ, আর দুই ধরনের প্রমাণের পার্থক্য
  • পুনরাবৃত্ত অক্ষরের শব্দ, গোল টেবিল আর শর্তসহ দল বাছাই, ক্ষেত্রভিত্তিক গণনাসহ
  • প্রতিটি সূত্র Python-এর itertools দিয়ে brute force-এ মিলিয়ে দেখা, আর গোনার ভুল ধরা

১ · ক্রম গোনে কি না — permutation আর combination-এর মূল প্রশ্ন

বাজারঘরের গুদামে দুটি কাজ এসেছে। প্রথম কাজ: অ্যাপের হোম পেজের সামনের তাকে তিনটি ঘর, বামে, মাঝে আর ডানে; সাতটি নতুন পণ্য থেকে তিনটি বেছে এই তিন ঘরে সাজাতে হবে। দ্বিতীয় কাজ: আট জন ডেলিভারি রাইডার থেকে তিনজনকে বেছে আজকের সিলেট রুটের দল বানাতে হবে। দুটিই “কয়েকটি থেকে কয়েকটি বাছাই”, কিন্তু উত্তর একেবারে আলাদা। তাকে চাল-ডাল-তেল আর তেল-ডাল-চাল আলাদা চেহারা, তাই আলাদা সাজানো। অথচ রাইডার রনি, সুমি আর জামিলের দল আর জামিল, রনি, সুমির দল একই দল; নাম কোন ক্রমে লেখা হলো, তাতে কিছু বদলায় না।

এই পর্বের পুরো কাজ ওই পার্থক্যটি নিখুঁত করা। পর্ব ১৪ “সেট — সংজ্ঞা, subset, power set আর Cartesian product”-এর ভাষায়: ক্রমসহ বাছাই হলো একটি sequence বা tuple (যেমন Cartesian product-এর উপাদান), আর ক্রমহীন বাছাই হলো একটি subset. সেটে {রনি, সুমি, জামিল} = {জামিল, রনি, সুমি}; tuple-এ (চাল, ডাল, তেল) ≠ (তেল, ডাল, চাল)। প্রশ্নটি তাই সবসময় এক: আমি কি tuple গুনছি, না subset?

গোনার হাতিয়ার আসে পর্ব ৩১ “গণনার মূল নিয়ম — যোগ, গুণ, বিয়োগ আর ভাগ” থেকে। এখানে দুটি নিয়ম বারবার লাগবে। গুণের নিয়ম (product rule): কাজটি পরপর k ধাপে হয়, আর আগে যা-ই বাছা হোক, i-তম ধাপে সবসময় miটি পছন্দ থাকে; তাহলে মোট উপায় m1 · m2 ⋯ mk. ভাগের নিয়ম (division rule): সসীম সেট A থেকে B-তে এমন একটি onto ফাংশন আছে, যাতে B-এর প্রতিটি উপাদানের ঠিক d-টি preimage; তাহলে |B| = |A|/d. অর্থাৎ প্রতিটি জিনিস ঠিক d বার গোনা হলে মোটকে d দিয়ে ভাগ করুন। ফাংশন আর preimage এসেছে পর্ব ১৬ “ফাংশন — one-to-one, onto, inverse আর composition”-এ।

সংজ্ঞা ১.১

S একটি সেট, |S| = n, আর 0 ≤ r ≤ n একটি পূর্ণসংখ্যা।

S-এর একটি r-permutation হলো S-এর r-টি আলাদা উপাদানের একটি ক্রমযুক্ত তালিকা (x1, x2, …, xr). এদের সংখ্যা লেখা হয় P(n, r). r = n হলে r-permutation-কে শুধু permutation বলে: S-এর সব উপাদানের একটি পুনর্বিন্যাস।

S-এর একটি r-combination হলো S-এর একটি r-উপাদানের subset, যেখানে ক্রমের কোনো অর্থ নেই। এদের সংখ্যা লেখা হয় C(n, r), পড়া হয় “n choose r”; অনেক বইয়ে nCr লেখা হয়। C(n, r)-কে binomial coefficient-ও বলে, নামের কারণ পর্ব ৩৪-এ পরিষ্কার হবে।

দুটি সংজ্ঞাতেই “আলাদা” শব্দটি জরুরি: একই জিনিস দুবার নেওয়া চলে না। পুনরাবৃত্তি চললে (কুপন কোডে একই অঙ্ক বারবার) উত্তর nr, যা পর্ব ৩১-এর বিষয়; আর পুনরাবৃত্তিসহ ক্রমহীন বাছাই পর্ব ৩৫ “পুনরাবৃত্তিসহ বাছাই — stars and bars আর multinomial”-এর বিষয়। মোট চারটি প্রশ্ন:

n-টি থেকে r-টিপুনরাবৃত্তি চলে নাপুনরাবৃত্তি চলে
ক্রম গুরুত্বপূর্ণP(n, r) = n!/(n − r)! (এই পর্ব)nr (পর্ব ৩১)
ক্রম গুরুত্বহীনC(n, r) = n!/(r!(n − r)!) (এই পর্ব)C(n + r − 1, r) (পর্ব ৩৫)

ক্রিকেটে একাদশ ঘোষণা আর ব্যাটিং অর্ডার ঘোষণা দুটি আলাদা কাজ। একাদশ একটি combination: কারা খেলবেন, শুধু সেই প্রশ্ন। ব্যাটিং অর্ডার একটি permutation: একই এগারোজন, কিন্তু কে ওপেন করবেন আর কে এগারো নম্বরে নামবেন, সেই ক্রমও ঠিক করতে হয়। তাই একই এগারোজনের একাদশ একটি, কিন্তু ব্যাটিং অর্ডার 11!টি সম্ভব।

এখানে n! (n factorial) মানে 1 · 2 ⋯ n, আর নিয়ম অনুযায়ী 0! = 1. এই নিয়মটি খেয়ালখুশি নয়: শূন্যটি জিনিস সাজানোর ঠিক একটি উপায় আছে, কিছুই না করা। পরের অংশে দেখবেন এই নিয়মের জন্যই সূত্রগুলো r = 0 আর r = n-এও কোনো ব্যতিক্রম ছাড়া কাজ করে।

২ · r-permutation — P(n, r) = n!/(n − r)!

উপপাদ্য ২.১

n ≥ 1 আর 0 ≤ r ≤ n পূর্ণসংখ্যা হলে

P(n, r) = n(n − 1)(n − 2) ⋯ (n − r + 1) = n!/(n − r)!

বিশেষভাবে P(n, n) = n!, আর P(n, 0) = 1. গুণফল n(n − 1)⋯(n − r + 1)-কে বলে falling factorial, কারণ n থেকে শুরু করে এক এক করে নেমে r-টি গুণনীয়ক।

প্রমাণ: S-এর একটি r-permutation বানানো মানে পরপর r-টি ঘর ভরা: আগে x1, তারপর x2, এভাবে xr পর্যন্ত।

  1. x1-এর জন্য S-এর যেকোনো উপাদান চলে: n-টি পছন্দ। — সংজ্ঞা
  2. x1 যা-ই হোক, x2 হতে হবে x1 ছাড়া অন্য কিছু: ঠিক n − 1টি পছন্দ। সাধারণভাবে, i-তম ঘরের আগে i − 1টি আলাদা উপাদান ব্যবহার হয়ে গেছে, তাই xi-এর জন্য ঠিক n − (i − 1) = n − i + 1টি পছন্দ, আগের বাছাই যা-ই হোক। — উপাদানগুলো আলাদা হওয়ার শর্ত
  3. প্রতিটি ধাপে পছন্দের সংখ্যা আগের বাছাইয়ের ওপর নির্ভর করে না (কোন কোন উপাদান বাকি, তা নির্ভর করে, কিন্তু কয়টি বাকি, তা নয়)। তাই গুণের নিয়ম খাটে: মোট n(n − 1)⋯(n − r + 1). — গুণের নিয়ম
  4. এই গুণফলকে (n − r)! দিয়ে গুণ আর ভাগ করলে লবে n(n − 1)⋯(n − r + 1) · (n − r)(n − r − 1)⋯1 = n!, তাই P(n, r) = n!/(n − r)!. r = 0-তে খালি গুণফল 1, আর সূত্রেও n!/n! = 1; r = n-এ n!/0! = n!. ∎

ধাপ ৩-এর বন্ধনীর কথাটি সূক্ষ্ম কিন্তু জরুরি: গুণের নিয়মের জন্য পছন্দের সংখ্যা স্থির থাকলেই চলে, পছন্দগুলো নিজে বদলালেও। ফাংশনের ভাষায় এটি পর্ব ১৬-এর উপপাদ্য ৬.১(খ)-এর আরেক রূপ: r-টি উপাদানের সেট থেকে n-টি উপাদানের সেটে one-to-one ফাংশনের সংখ্যাও n!/(n − r)!. কারণ একটি r-permutation (x1, …, xr) মানে ঠিক একটি one-to-one ফাংশন i ↦ xi; এই মিলটি একটি bijection, তাই দুই সংখ্যা সমান। আর r > n হলে কোনো r-permutation নেই (r-টি আলাদা উপাদান নেওয়ার মতো উপাদানই নেই); Python-এর math.perm(n, r) তখন 0 দেয়।

এবার বাজারঘরের তাক। সাতটি পণ্য A থেকে G (চাল, ডাল, তেল, চিনি, লবণ, আটা, সুজি), তিনটি ঘর। নিচের stepper-এ প্রতিটি ঘর ভরার সময় পছন্দ কমে যাওয়া দেখুন।

1ঘর: [ বাম ][ মাঝ ][ ডান ]2বাম  ← 7টি থেকে একটি3মাঝ  ← বাকি 6টি থেকে4ডান  ← বাকি 5টি থেকে5P(7,3) = 7 · 6 · 5
তাক আর হিসাব
তাক
বাকি পণ্য
এ পর্যন্ত উপায়
  1. প্রশ্ন চেনা। তিনটি ঘরের নাম আছে (বাম, মাঝ, ডান), তাই (C, F, A) আর (A, F, C) আলাদা সাজানো। আমরা tuple গুনছি, subset নয়: এটি একটি 3-permutation, n = 7.
  2. বাম ঘর। সাতটি পণ্যের যেকোনোটি বসতে পারে: 7টি পছন্দ। ধরা যাক C (তেল) বসল।
  3. মাঝের ঘর। C আর ব্যবহার করা যাবে না, বাকি ছয়টি: 6টি পছন্দ। প্রথম ঘরে অন্য পণ্য বসলেও বাকি থাকত ঠিক ছয়টি। এ পর্যন্ত 7 · 6 = 42টি উপায়। ধরা যাক F বসল।
  4. ডান ঘর। বাকি পাঁচটি: 5টি পছন্দ; মোট 42 · 5 = 210. ধরা যাক A বসল। বাকি চারটি পণ্য (B, D, E, G) এই সাজানোয় আসেনি।
  5. সূত্রের সঙ্গে মেলানো। 7 · 6 · 5 = 210, আর n!/(n − r)! = 7!/4! = 5040/24 = 210. সূত্রের হর 4! আসলে “অব্যবহৃত চারটি পণ্যের যত ক্রম”, যা আমরা গুনতে চাই না। ∎

শেষ ধাপের ব্যাখ্যাটি মনে রাখার মতো। n!/(n − r)! সূত্রটিকে একটি ভাগের নিয়ম হিসেবেও পড়া যায়: সাতটি পণ্যের সব 7!টি পূর্ণ সারি সাজান, তারপর শুধু প্রথম তিনটি ঘর দেখুন। প্রথম তিনটি একই রেখে পরের চারটি 4!টি ক্রমে থাকতে পারে, তাই প্রতিটি 3-permutation ঠিক 4! বার এসেছে। এই “যা গুনতে চাই না, তার ক্রম দিয়ে ভাগ” চিন্তাটিই পরের অংশে combination-এর সূত্র দেবে।

৩ · r-combination — ভাগের নিয়মে C(n, r)

এবার রাইডারের দল। আট জন রাইডার A থেকে H, দলে তিনজন। ক্রম গুরুত্বহীন, তাই সরাসরি গুণের নিয়ম খাটে না: “প্রথম সদস্য, দ্বিতীয় সদস্য, তৃতীয় সদস্য” বলে কিছু নেই। কৌশলটি হলো ইচ্ছা করে ক্রম যোগ করা, তারপর বাড়তি গোনাটুকু ভাগ করে বাদ দেওয়া।

উপপাদ্য ৩.১

n ≥ 0 আর 0 ≤ r ≤ n পূর্ণসংখ্যা হলে P(n, r) = C(n, r) · r!, অর্থাৎ

C(n, r) = P(n, r)/r! = n!/(r! (n − r)!)

প্রমাণ (ভাগের নিয়ম): A = S-এর সব r-permutation-এর সেট, B = S-এর সব r-উপাদানের subset-এর সেট।

  1. ফাংশন φ: A → B সংজ্ঞায়িত করি: φ(x1, …, xr) = {x1, …, xr}, অর্থাৎ তালিকা থেকে ক্রম মুছে ফেলা। উপাদানগুলো আলাদা, তাই ফলটি সত্যিই r-উপাদানের subset. — সংজ্ঞা
  2. φ onto: যেকোনো r-উপাদানের subset T-এর উপাদানগুলো যেকোনো ক্রমে লিখলে এমন একটি তালিকা পাই, যার ছবি T. — onto-র ছক
  3. প্রতিটি T-এর preimage ঠিক T-এর উপাদানগুলোর সব ক্রম, অর্থাৎ T-এর permutation; উপপাদ্য ২.১ অনুযায়ী এদের সংখ্যা P(r, r) = r!. তাই φ একটি r!-to-1 ফাংশন। — উপপাদ্য ২.১
  4. ভাগের নিয়মে |B| = |A|/r!, অর্থাৎ C(n, r) = P(n, r)/r! = n!/((n − r)! r!). ∎

একই প্রমাণ গুণের নিয়মেও লেখা যায়: একটি r-permutation বানাতে আগে কোন r-টি উপাদান নেবেন তা বাছুন (C(n, r) উপায়), তারপর তাদের সাজান (r! উপায়)। প্রতিটি r-permutation ঠিক একবার তৈরি হয়, তাই P(n, r) = C(n, r) · r!. অজানা C(n, r) বের হলো এমন সমীকরণ থেকে, যার বাকি সব অংশ জানা; গোনায় এই কৌশল বারবার ফিরে আসে।

ভাগের নিয়ম: ৬টি ক্রমযুক্ত তালিকা, একটিই দল

বামে {A, B, C}-এর সব 3! = 6টি ক্রম; ক্রম মুছে ফেললে সবগুলো ডানের একই subset-এ গিয়ে পড়ে

Division rule: six ordered lists map to one 3-subset ক্রমযুক্ত তালিকা দল (subset) A B C A C B B A C B C A C A B C B A {A,B,C} 336টি তালিকা ÷ 3! = 56টি দল
ছবি ৩.১ — ফাংশন φ তালিকা থেকে ক্রম মুছে দেয়। প্রতিটি দল ঠিক 3! = 6টি তালিকার ছবি, তাই φ একটি 6-to-1 ফাংশন। আট রাইডারের সব P(8, 3) = 336টি তালিকার ওপর φ চালালে প্রতিটি দল ছয়বার আসে, ফলে দল C(8, 3) = 336/6 = 56টি।
1ক্রমসহ গুনি: P(8,3)2একটি দল {A,B,C} ক'বার?3প্রতিটি দল ঠিক 3! বার4C(8,3) = 336 / 65বাদ পড়া 5 জন: C(8,5)
গোনা আর যুক্তি
এই ধাপের গোনা
যুক্তি
  1. আগে ক্রমসহ গোনা। দলের বদলে যদি “প্রথম, দ্বিতীয়, তৃতীয় রাইডার” বাছতাম, উত্তর হতো P(8, 3) = 8 · 7 · 6 = 336. কিন্তু আমাদের দলে পদ নেই, তাই এই সংখ্যা বেশি গোনা।
  2. একটি দল কতবার এসেছে? দল {A, B, C} তালিকায় এসেছে ABC, ACB, BAC, BCA, CAB, CBA এই ছয় রূপে। ছয়টিই আলাদা তালিকা, কিন্তু একই দল।
  3. সব দলের জন্য একই সংখ্যা। যেকোনো তিনজনের দলকে 3! = 6টি ক্রমে লেখা যায়, কম-বেশি নয়। তাই “তালিকা থেকে দল” ফাংশনটি ঠিক 6-to-1. এই সমতাটুকুই ভাগের নিয়মের শর্ত।
  4. ভাগ। 336টি তালিকা, প্রতিটি দল ছয়বার: দল 336/6 = 56টি। সূত্রে C(8, 3) = 8!/(3! · 5!) = 40320/(6 · 120) = 56.
  5. উল্টো দিক থেকে। তিনজনকে রুটে পাঠানো মানে বাকি পাঁচজনকে গুদামে রাখাও বাছাই করা। তাই 5 জনের “বাদ পড়া দল”-ও 56টি: C(8, 5) = 56. এর প্রমাণ পরের অংশে। ∎

৪ · C(n, r) = C(n, n − r) — বীজগণিত আর combinatorial প্রমাণ

একটি identity (সব মানে সত্য সমতা) প্রমাণের দুটি সম্পূর্ণ আলাদা পথ আছে। বীজগাণিতিক পথে সূত্র বসিয়ে দুই পাশ একই রাশিতে নামানো হয়। Combinatorial proof-এ দেখানো হয় দুই পাশ একই জিনিসের সংখ্যা: হয় একই সেটকে দুইভাবে গোনা (double counting, পর্ব ৩৭-এ বিস্তারিত), নয়তো দুই পাশের গোনা সেটের মধ্যে একটি bijection দেখানো। দ্বিতীয় পথটি প্রায়ই বলে দেয় কেন সমতাটি সত্য।

উপপাদ্য ৪.১

n ≥ 0 আর 0 ≤ r ≤ n পূর্ণসংখ্যা হলে C(n, r) = C(n, n − r).

প্রমাণ ১ (বীজগাণিতিক):

  1. উপপাদ্য ৩.১ অনুযায়ী C(n, n − r) = n!/((n − r)! (n − (n − r))!). — সূত্রে r-এর জায়গায় n − r, যা 0 আর n-এর মধ্যে আছে
  2. n − (n − r) = r, তাই C(n, n − r) = n!/((n − r)! r!). — সরলীকরণ
  3. হরের দুটি গুণনীয়কের ক্রম বদলালে গুণফল বদলায় না, তাই এটি n!/(r! (n − r)!) = C(n, r). ∎

প্রমাণ ২ (combinatorial, bijection দিয়ে): S একটি n-উপাদানের সেট।

  1. A = S-এর সব r-উপাদানের subset, B = S-এর সব (n − r)-উপাদানের subset. সংজ্ঞা অনুযায়ী |A| = C(n, r) আর |B| = C(n, n − r). — সংজ্ঞা ১.১
  2. g: A → B, g(T) = S − T (T-এর complement) সংজ্ঞায়িত করি। |T| = r হলে |S − T| = n − r, তাই g(T) সত্যিই B-তে। — পর্ব ১৫-এর set difference
  3. h: B → A, h(U) = S − U-ও একইভাবে সংজ্ঞায়িত। S − (S − T) = T, তাই h∘g = ιA আর g∘h = ιB; অর্থাৎ g একটি bijection. — পর্ব ১৬-এর উপপাদ্য ৩.২
  4. সসীম দুই সেটের মধ্যে bijection থাকলে তাদের আকার সমান, তাই C(n, r) = C(n, n − r). ∎

দুই প্রমাণই সঠিক, কিন্তু দ্বিতীয়টি একটি গল্প বলে: “কাদের নেবেন” আর “কাদের রেখে যাবেন” একই সিদ্ধান্ত। তাই ১৫ জনের স্কোয়াড থেকে একাদশ বাছা C(15, 11) উপায়ে, আর বাদ পড়া চারজন বাছা C(15, 4) উপায়ে; দুটিই 1365. হিসাবেও সুবিধা: C(100, 98)-এর বদলে C(100, 2) = 100 · 99/2 = 4950.

সংজ্ঞা থেকেই C(n, 0) = C(n, n) = 1 আর C(n, 1) = n. আর r = 0 থেকে n পর্যন্ত সব C(n, r) যোগ করলে পাই power set-এর আকার 2n (পর্ব ১৪)। এমন identity-র পুরো তালিকা পর্ব ৩৪ “Binomial coefficient, Pascal-এর ত্রিভুজ আর combinatorial identity”-এর বিষয়।

এবার সব কিছু brute force দিয়ে মিলিয়ে দেখা যাক। Python-এর itertools.permutations(S, r) সব r-permutation একে একে তৈরি করে, আর itertools.combinations(S, r) সব r-combination; math.perm আর math.comb সরাসরি সূত্রের মান দেয় (Python 3.8 থেকে আছে)। নিচের ব্লক দুই পথের সংখ্যা মেলায়, তারপর আট রাইডারের সব 336টি তালিকাকে দলে ভাগ করে দেখে প্রতিটি দল কতবার এসেছে। প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে।

from itertools import permutations, combinations
from math import perm, comb
from collections import Counter

print(" n  r | itertools   perm | itertools  comb | P/C")
for n, r in [(7, 3), (8, 3), (6, 6), (5, 0), (10, 4)]:
    p = sum(1 for _ in permutations(range(n), r))   # ordered, no repeats
    c = sum(1 for _ in combinations(range(n), r))   # unordered r-subsets
    print(f"{n:2} {r:2} | {p:9} {perm(n, r):6} | {c:9} {comb(n, r):5} |"
          f" {p // c} = {r}!")

# the division rule, seen directly: 8 riders, ordered lists of 3
riders = "ABCDEFGH"
teams = Counter(frozenset(t) for t in permutations(riders, 3))
print("ordered lists:", sum(teams.values()), " distinct teams:", len(teams))
print("each team appears", set(teams.values()), "times")
print("orderings of {A,B,C}:", ["".join(t) for t in permutations("ABC")])

# symmetry C(n, r) = C(n, n - r), and what happens when r > n
print("C(8,3), C(8,5):", comb(8, 3), comb(8, 5))
print("symmetric for all n < 40:", all(comb(n, r) == comb(n, n - r)
                                      for n in range(40) for r in range(n + 1)))
print("perm(5, 7) =", perm(5, 7), " comb(5, 7) =", comb(5, 7))

আসল আউটপুট (ব্রাউজারের Python):

 n  r | itertools   perm | itertools  comb | P/C
 7  3 |       210    210 |        35    35 | 6 = 3!
 8  3 |       336    336 |        56    56 | 6 = 3!
 6  6 |       720    720 |         1     1 | 720 = 6!
 5  0 |         1      1 |         1     1 | 1 = 0!
10  4 |      5040   5040 |       210   210 | 24 = 4!
ordered lists: 336  distinct teams: 56
each team appears {6} times
orderings of {A,B,C}: ['ABC', 'ACB', 'BAC', 'BCA', 'CAB', 'CBA']
C(8,3), C(8,5): 56 56
symmetric for all n < 40: True
perm(5, 7) = 0  comb(5, 7) = 0

প্রতিটি সারিতে brute force আর সূত্র হুবহু মিলেছে, আর শেষ কলামে P/C সবসময় r!: উপপাদ্য ৩.১-এর P(n, r) = C(n, r) · r! সংখ্যায়। (7, 3) সারি তাকের 210টি সাজানো; একই সাত পণ্য থেকে শুধু “কোন তিনটি” বাছলে 35টি। (5, 0) সারিটি 0! = 1 নিয়মের যৌক্তিকতা দেখায়: itertools-ও খালি তালিকা ঠিক একটি গোনে। মাঝের অংশে frozenset তালিকা থেকে ক্রম মুছে দেয়, ঠিক ছবি ৩.১-এর φ; 336টি তালিকা 56টি দলে পড়েছে, প্রতিটি দল ঠিক 6 বার। শেষ লাইন: r > n হলে Python 0 দেয়, যা গোনার অর্থের সঙ্গে মেলে; কিন্তু n!/(r!(n − r)!) সূত্রে তখন ঋণাত্মক সংখ্যার factorial আসত, যা সংজ্ঞায়িত নয়। তাই সূত্রের শর্ত 0 ≤ r ≤ n লিখতে ভুলবেন না।

৫ · একই রকম জিনিসের বিন্যাস — MISSISSIPPI থেকে NARAYANGANJ

এ পর্যন্ত সব জিনিস আলাদা ছিল। এখন বাজারঘরের নামটিই ইংরেজি হরফে লিখুন: BAZARGHAR. নয়টি অক্ষর, কিন্তু A তিনবার, R দুবার। এর অক্ষরগুলো কত রকমে সাজানো যায়? যদি 9! = 362880 বলেন, তাহলে বেশি গোনা হলো: তিনটি A-র নিজেদের মধ্যে জায়গা বদলালে চোখে কোনো নতুন শব্দ আসে না। এটি একটি multiset-এর (যে সংগ্রহে একই উপাদান একাধিকবার থাকতে পারে) বিন্যাস।

উপপাদ্য ৫.১

n-টি জিনিসের মধ্যে k ধরনের জিনিস আছে: প্রথম ধরনের n1টি একই রকম, দ্বিতীয় ধরনের n2টি, …, k-তম ধরনের nkটি, যেখানে n1 + n2 + ⋯ + nk = n. তাহলে এদের আলাদা বিন্যাসের সংখ্যা

n! / (n1! n2! ⋯ nk!)

প্রমাণ ১ (জায়গা বাছাই, গুণের নিয়ম): একটি বিন্যাস মানে n-টি ঘরের কোনগুলোতে কোন ধরনের জিনিস বসবে, তা ঠিক করা।

  1. প্রথম ধরনের n1টি জিনিসের জন্য n-টি ঘর থেকে n1টি বাছুন: C(n, n1) উপায়। জিনিসগুলো একই রকম, তাই ওই ঘরগুলোর মধ্যে তাদের ক্রমের প্রশ্ন নেই। — সংজ্ঞা ১.১
  2. বাকি n − n1টি ঘর থেকে দ্বিতীয় ধরনের জন্য n2টি: C(n − n1, n2) উপায়; প্রথম ধাপে কোন ঘর নেওয়া হলো, তাতে সংখ্যাটি বদলায় না। এভাবে শেষ ধরনের জন্য C(nk, nk) = 1. — গুণের নিয়ম
  3. গুণফল C(n, n1) · C(n − n1, n2) ⋯ = [n!/(n1!(n − n1)!)] · [(n − n1)!/(n2!(n − n1 − n2)!)] ⋯. প্রতিটি ভগ্নাংশের হরের দ্বিতীয় factorial পরের ভগ্নাংশের লবের সঙ্গে কাটা যায়, আর শেষে 0! = 1 থাকে। ফল n!/(n1! ⋯ nk!). ∎

প্রমাণ ২ (লেবেল লাগিয়ে, ভাগের নিয়ম): প্রতিটি একই রকম জিনিসের গায়ে সাময়িক লেবেল লাগান (A1, A2, A3, R1, R2, …)। এখন সব আলাদা, বিন্যাস n!টি। লেবেল মুছে ফেলার ফাংশন প্রতিটি লেবেলহীন বিন্যাসকে ঠিক n1! n2! ⋯ nk! বার পায়, কারণ প্রতিটি ধরনের লেবেলগুলো নিজেদের ঘরে যেকোনো ক্রমে থাকতে পারে, আর বিভিন্ন ধরনের ক্রম স্বাধীন। ভাগের নিয়মে উত্তর একই। ∎

BAZARGHAR-এ n = 9, A তিনটি, R দুটি, বাকি চারটি অক্ষর একটি করে: 9!/(3! 2!) = 362880/12 = 30240. বাংলাদেশের একটি জেলার নাম NARAYANGANJ-এ এগারোটি অক্ষর: A চারবার, N তিনবার, আর R, Y, G, J একবার করে; উত্তর 11!/(4! 3!) = 39916800/144 = 277200. পাঠ্যবইয়ের প্রিয় উদাহরণ MISSISSIPPI-তে I চারবার, S চারবার, P দুবার, M একবার: 11!/(4! 4! 2!) = 34650. নিচের ব্লক দুই রকমে মেলায়: ছোট শব্দে set(permutations(w)) দিয়ে সত্যিকারের brute force, আর বড় শব্দে “প্রথম অক্ষর কোনটি” ভাগে ভাগে গোনা একটি recursion, যা সব শব্দ না বানিয়েই গোনে।

from itertools import permutations
from math import factorial
from collections import Counter
from functools import cache

def formula(word):                      # n! / (n1! n2! ... nk!)
    r = factorial(len(word))
    for m in Counter(word).values():
        r //= factorial(m)
    return r

@cache
def count(left):                        # left = sorted tuple of letter counts
    if sum(left) == 0:
        return 1                        # the empty word: one arrangement
    total = 0
    for i, m in enumerate(left):        # choose which letter goes first
        if m:
            rest = list(left); rest[i] -= 1
            total += count(tuple(sorted(rest)))
    return total

for w in ["ABC", "AAB", "BAZAR", "BAZARGHAR"]:
    raw = factorial(len(w))             # treats equal letters as different
    seen = len(set(permutations(w)))    # brute force: 9! tuples for BAZARGHAR
    print(f"{w:10} n! = {raw:6}  distinct = {seen:5}  formula = {formula(w)}")

for w in ["MISSISSIPPI", "NARAYANGANJ"]:
    c = Counter(w)
    print(f"{w}: {dict(c)}")
    print(f"  first-letter recursion = {count(tuple(sorted(c.values())))}"
          f"  formula = {formula(w)}")

আসল আউটপুট (ব্রাউজারের Python):

ABC        n! =      6  distinct =     6  formula = 6
AAB        n! =      6  distinct =     3  formula = 3
BAZAR      n! =    120  distinct =    60  formula = 60
BAZARGHAR  n! = 362880  distinct = 30240  formula = 30240
MISSISSIPPI: {'M': 1, 'I': 4, 'S': 4, 'P': 2}
  first-letter recursion = 34650  formula = 34650
NARAYANGANJ: {'N': 3, 'A': 4, 'R': 1, 'Y': 1, 'G': 1, 'J': 1}
  first-letter recursion = 277200  formula = 277200

AAB-এর সারিতে ব্যাপারটি চোখে দেখা যায়: 3! = 6টি tuple-এর মধ্যে মাত্র তিনটি আলাদা শব্দ (AAB, ABA, BAA), কারণ দুই A-র অদলবদলে কিছু বদলায় না, তাই 6/2! = 3. BAZARGHAR-এ 362880টি tuple থেকে 30240টি আলাদা শব্দ: প্রতিটি শব্দ ঠিক 3! · 2! = 12 বার এসেছিল, প্রমাণ ২-এর লেবেল মোছার মতো। নিচের দুটি শব্দে recursion: count(…) প্রথম অক্ষর হিসেবে প্রতিটি ধরন একবার চেষ্টা করে, আর বাকি অক্ষরের জন্য নিজেকে ডাকে; আলাদা প্রথম অক্ষরের শব্দগুলো কখনো এক হয় না, তাই যোগের নিয়ম খাটে। brute force এখানে থামালাম, কারণ NARAYANGANJ-এ set(permutations(w)) প্রায় চার কোটি tuple বানাত। এই সূত্রই পর্ব ৩৫-এর multinomial coefficient, আর সব বিন্যাস lexicographic ক্রমে তৈরির পদ্ধতি আসবে পর্ব ৩৬ “Permutation আর combination তৈরি — lexicographic order আর backtracking”-এ।

৬ · গোল টেবিল — circular permutation

বাজারঘরের মাসিক সভায় পাঁচজন ব্যবস্থাপক একটি গোল টেবিলে বসবেন। সারিতে বসলে উপায় 5! = 120. কিন্তু গোল টেবিলে কোনো “প্রথম চেয়ার” নেই; সবাই একসঙ্গে এক চেয়ার ডানে সরে বসলে কারো ডান বা বাম পাশের মানুষ বদলায় না। তাই সেগুলোকে একই বসা ধরা হয়। একে বলে circular permutation.

একই বসা, চারটি সারি-রূপ

টেবিলের চারপাশে ঘড়ির কাঁটার দিকে A, B, C, D; কোন চেয়ার থেকে পড়া শুরু করবেন তার চারটি পছন্দ, বসা একটিই

One circular seating, four linear readings টেবিল A B C D A B C D B C D A C D A B D A B C ৪টি সারি → ১টি বসা
ছবি ৬.১ — চার জনের প্রতিটি গোল বসা ঠিক চারটি সারি-বিন্যাস থেকে আসে (কোন চেয়ার থেকে পড়া শুরু)। তাই সারি থেকে গোল বসার ফাংশন 4-to-1, আর গোল বসা 4!/4 = 3! = 6টি।
উপপাদ্য ৬.১

n ≥ 1 জন আলাদা মানুষকে একটি গোল টেবিলে বসানোর উপায় (একটি বসাকে তার সব rotation-এর সঙ্গে একই ধরলে) (n − 1)!. যদি আয়নার প্রতিবিম্বকেও (ঘড়ির কাঁটার দিক আর উল্টো দিক) একই ধরা হয়, যেমন মালার পুঁতি, তাহলে n ≥ 3-এর জন্য (n − 1)!/2.

প্রমাণ:

  1. একটি গোল বসাকে কোনো একটি চেয়ার থেকে ঘড়ির কাঁটার দিকে পড়লে একটি সারি-বিন্যাস পাই। n-টি চেয়ার, তাই n-টি পড়া। — সংজ্ঞা
  2. এই n-টি সারি সব আলাদা: মানুষগুলো আলাদা, তাই প্রথম স্থানে কে আছেন তা দিয়েই সারিগুলো আলাদা হয়। আবার প্রতিটি সারি-বিন্যাস ঠিক একটি গোল বসা থেকে আসে (সারিটিকে টেবিলে মুড়ে দিলেই হলো)। — মানুষগুলো আলাদা
  3. অতএব “সারি থেকে গোল বসা” ফাংশনটি onto আর ঠিক n-to-1. ভাগের নিয়মে গোল বসা n!/n = (n − 1)!. — ভাগের নিয়ম
  4. n ≥ 3 হলে প্রতিটি গোল বসা আর তার আয়নার প্রতিবিম্ব আলাদা (কারো ডানের মানুষ বামে চলে যায়), আর প্রতিবিম্বের প্রতিবিম্ব আসল বসা। তাই প্রতিবিম্বও একই ধরলে প্রতিটি নতুন শ্রেণিতে ঠিক দুটি গোল বসা; আবার ভাগের নিয়মে (n − 1)!/2. ∎

বিকল্প চিন্তা: একজনকে (ধরুন A) যেকোনো চেয়ারে বসিয়ে “নোঙর” করুন; সব চেয়ার একই রকম বলে এতে কোনো পছন্দ নেই। এরপর A-র ডান থেকে চেয়ারগুলো আলাদা হয়ে গেছে, বাকি n − 1 জনের জন্য (n − 1)!. শর্ত থাকলে “block” কৌশল: দুজনকে পাশাপাশি বসাতে হলে তাঁদের একটি একক ধরুন। পাঁচজনের টেবিলে তখন চারটি একক, গোল বসা (4 − 1)! = 6, আর block-এর ভেতরে দুজন দুই ক্রমে: মোট 2 · 6 = 12. নিচের ব্লক প্রতিটি বসাকে “০ নম্বর মানুষ প্রথমে” রূপে ঘুরিয়ে (canonical form) আলাদা বসা গোনে।

from itertools import permutations
from math import factorial

def canon(p):                    # rotate so that person 0 sits first
    i = p.index(0)
    return p[i:] + p[:i]

def round_table(n):              # seatings up to rotation
    return {canon(p) for p in permutations(range(n))}

def bracelet(n):                 # also identify a seating with its mirror image
    out = set()
    for q in round_table(n):
        mirror = (q[0],) + q[:0:-1]
        out.add(min(q, mirror))
    return out

print(" n | linear n! | round brute (n-1)! | mirror brute (n-1)!/2")
for n in range(3, 8):
    print(f"{n:2} | {factorial(n):9} | {len(round_table(n)):11} {factorial(n - 1):6}"
          f" | {len(bracelet(n)):12} {factorial(n - 1) // 2:6}")

# 5 people, persons 1 and 2 must sit side by side
seat = round_table(5)
together = [q for q in seat if abs(q.index(1) - q.index(2)) in (1, 4)]
print("5 at a round table:", len(seat), " with 1 and 2 adjacent:", len(together))
print("block method 2 * (4-1)! =", 2 * factorial(3))

আসল আউটপুট (ব্রাউজারের Python):

 n | linear n! | round brute (n-1)! | mirror brute (n-1)!/2
 3 |         6 |           2      2 |            1      1
 4 |        24 |           6      6 |            3      3
 5 |       120 |          24     24 |           12     12
 6 |       720 |         120    120 |           60     60
 7 |      5040 |         720    720 |          360    360
5 at a round table: 24  with 1 and 2 adjacent: 12
block method 2 * (4-1)! = 12

canon(p) হলো “নোঙর” কৌশল: 0 নম্বর মানুষকে প্রথমে এনে ঘোরানো, ফলে একই গোল বসার সব rotation একই tuple, আর set সেগুলোকে একবারই রাখে। n = 3 থেকে 7 পর্যন্ত গোল বসা (n − 1)!, আর আয়নাসহ (n − 1)!/2, দুটিই হুবহু মিলেছে। n = 3-এ আয়নাসহ মাত্র একটি: তিনজন গোল হয়ে বসলে প্রত্যেকের দুই পাশে বাকি দুজন, ঘুরিয়ে বা উল্টে সব বসা একই। শেষ দুই লাইন block কৌশল যাচাই করে: পাঁচজনের 24টি গোল বসার 12টিতে 1 আর 2 পাশাপাশি। লক্ষ করুন, গোল টেবিলে পাশাপাশি মানে সূচকের পার্থক্য 1 অথবা 4 (প্রথম আর শেষ চেয়ারও পাশাপাশি); কোডে এটি বাদ দিলে ভুল উত্তর আসত।

৭ · শর্তসহ দল বাছাই — ক্রিকেট একাদশ আর কমিটি

বাস্তব প্রশ্নে বাছাই প্রায় কখনো শর্তহীন নয়। বাজারঘরের অফিস ক্রিকেট টুর্নামেন্টের জন্য ১৫ জনের স্কোয়াড: ৬ জন বোলার আর ৯ জন ব্যাটার (উইকেটরক্ষকসহ)। শর্ত: একাদশে অন্তত ৪ জন বোলার থাকবেন। কতভাবে একাদশ বাছা যায়?

“অন্তত” শব্দটি দেখলেই দুটি নির্ভরযোগ্য পথ মনে আনুন। ক্ষেত্রভিত্তিক গণনা: বোলারের সংখ্যা ঠিক ৪, ঠিক ৫ বা ঠিক ৬; এই ক্ষেত্রগুলো পরস্পর disjoint আর একসঙ্গে সব বৈধ দল ঢাকে, তাই যোগের নিয়ম খাটে। প্রতিটি ক্ষেত্রের ভেতরে গুণের নিয়ম: কোন বোলাররা, আর কোন ব্যাটাররা।

  • ৪ জন বোলার, ৭ জন ব্যাটার: C(6, 4) · C(9, 7) = 15 · 36 = 540
  • ৫ জন বোলার, ৬ জন ব্যাটার: C(6, 5) · C(9, 6) = 6 · 84 = 504
  • ৬ জন বোলার, ৫ জন ব্যাটার: C(6, 6) · C(9, 5) = 1 · 126 = 126

মোট 540 + 504 + 126 = 1170. Complement দিয়ে: সব একাদশ C(15, 11) = 1365; খারাপগুলো, অর্থাৎ ৩ জন বা তার কম বোলার: ৯ জন ব্যাটারের বেশি কেউ নেই, তাই বোলার অন্তত ২ জন লাগেই; ২ জন বোলারে C(6, 2) · C(9, 9) = 15, ৩ জনে C(6, 3) · C(9, 8) = 20 · 9 = 180. মোট খারাপ 195, ভালো 1365 − 195 = 1170. দুই পথে একই উত্তর, যা আস্থার একটি ভালো লক্ষণ।

এবার খাতায় সম্ভবত সবচেয়ে বেশি দেখা ভুলটি: “আগে ৪ জন বোলার নিশ্চিত, C(6, 4) = 15; তারপর বাকি ১১ জন থেকে যেকোনো ৭ জন, C(11, 7) = 330; মোট 15 · 330 = 4950 উপায়।” উত্তরটি সঠিকের চার গুণেরও বেশি। ৫ জন বোলারের একটি একাদশ এই পদ্ধতিতে পাঁচবার তৈরি হয়: পাঁচজনের যেকোনো চারজনকে “নিশ্চিত” ধরে বাকিজনকে “যেকোনো ৭”-এ ফেলে। এটি overcounting: গুণের নিয়ম খাটে শুধু তখন, যখন প্রতিটি ফল ঠিক একবার তৈরি হয়। নিচের ব্লক 1365টি একাদশের প্রত্যেকটি তৈরি করে সরাসরি গোনে, আর ভুল পদ্ধতি প্রতিটি দলকে কতবার গোনে তাও দেখায়।

from itertools import combinations
from math import comb

bowlers = [f"B{i}" for i in range(1, 7)]       # 6 bowlers
batters = [f"T{i}" for i in range(1, 10)]      # 9 batters (keeper included)
squad = bowlers + batters                       # 15 players

def n_bowl(team):
    return sum(p in bowlers for p in team)

teams = list(combinations(squad, 11))
good = [t for t in teams if n_bowl(t) >= 4]
print("all XIs:", len(teams), "  with at least 4 bowlers:", len(good))

cases = {b: comb(6, b) * comb(9, 11 - b) for b in range(4, 7)}
print("by cases (bowlers: count):", cases, " sum =", sum(cases.values()))
bad = sum(comb(6, b) * comb(9, 11 - b) for b in range(0, 4))
print("complement:", comb(15, 11), "-", bad, "=", comb(15, 11) - bad)

wrong = comb(6, 4) * comb(11, 7)     # "first 4 bowlers, then any 7 others"
print("wrong method C(6,4)*C(11,7) =", wrong)
for b in range(4, 7):                # an XI with b bowlers is built C(b,4) times
    print(f"  XI with {b} bowlers is produced {comb(b, 4)} time(s)")
print("check:", sum(cases[b] * comb(b, 4) for b in cases), "=", wrong)

আসল আউটপুট (ব্রাউজারের Python):

all XIs: 1365   with at least 4 bowlers: 1170
by cases (bowlers: count): {4: 540, 5: 504, 6: 126}  sum = 1170
complement: 1365 - 195 = 1170
wrong method C(6,4)*C(11,7) = 4950
  XI with 4 bowlers is produced 1 time(s)
  XI with 5 bowlers is produced 5 time(s)
  XI with 6 bowlers is produced 15 time(s)
check: 4950 = 4950

Brute force, ক্ষেত্রভিত্তিক গণনা আর complement, তিনটিই 1170. Complement-এর 195-এ শূন্য বা একজন বোলারের ক্ষেত্রগুলো স্বয়ংক্রিয়ভাবে 0 এসেছে, কারণ comb(9, 10) আর comb(9, 11) শূন্য: নয়জন থেকে দশজন বাছা যায় না। শেষ অংশটি ভুলের ময়নাতদন্ত: ঠিক b জন বোলারের একাদশকে ভুল পদ্ধতি তৈরি করে C(b, 4) বার, তাই ভুল সংখ্যা = 540 · 1 + 504 · 5 + 126 · 15 = 4950. ভুলটি দৈবাৎ নয়, পূর্বানুমেয় বাড়তি গোনা।

একই ধাঁচের আরেকটি প্রশ্ন stepper-এ ধাপে ধাপে করা যাক। বাজারঘরের ৪ সদস্যের একটি নিরাপত্তা কমিটি হবে ঢাকা অফিসের ৫ জন আর চট্টগ্রাম অফিসের ৪ জন, মোট ৯ জন থেকে; শর্ত: চট্টগ্রামের অন্তত ২ জন থাকবেন।

1ঢাকা 5, চট্টগ্রাম 4; দল 4 জন2চট্টগ্রাম ঠিক 23চট্টগ্রাম ঠিক 34চট্টগ্রাম ঠিক 45যোগ, আর complement-এ যাচাই6ভুল পথ: আগে 2 জন নিশ্চিত
ক্ষেত্র আর গোনা
এই ধাপের গোনা
চলতি মোট
  1. শর্ত পড়া। দলে চট্টগ্রামের সদস্যসংখ্যা k হলে k = 2, 3 বা 4 চলবে। এই তিন ক্ষেত্র পরস্পর disjoint (একটি দলে k একটিই মান), আর সব বৈধ দল ঢাকে; তাই উত্তর হবে তিন ক্ষেত্রের যোগফল।
  2. k = 2. চট্টগ্রামের ৪ জন থেকে ২ জন, C(4, 2) = 6; বাকি দুটি আসন ঢাকার ৫ জন থেকে, C(5, 2) = 10. দুই বাছাই স্বাধীন, তাই 6 · 10 = 60.
  3. k = 3. C(4, 3) · C(5, 1) = 4 · 5 = 20. চলতি মোট 80.
  4. k = 4. চট্টগ্রামের চারজনই, ঢাকার কেউ নন: C(4, 4) · C(5, 0) = 1. চলতি মোট 81.
  5. যাচাই। সব কমিটি C(9, 4) = 126. খারাপ: k = 0-তে C(5, 4) = 5, k = 1-এ C(4, 1) · C(5, 3) = 4 · 10 = 40. 126 − 5 − 40 = 81. দুই পথে একই উত্তর: 81. ∎
  6. ভুল পথ। “আগে চট্টগ্রামের ২ জন নিশ্চিত, C(4, 2) = 6; তারপর বাকি ৭ জন থেকে যেকোনো ২ জন, C(7, 2) = 21”: 126, যা সব কমিটির সমান! চট্টগ্রামের ৩ জনের একটি দল এখানে C(3, 2) = 3 বার আসে, আর ৪ জনের দল C(4, 2) = 6 বার: 60 + 20 · 3 + 1 · 6 = 126.

ক্ষেত্রভিত্তিক গণনার তিনটি পরীক্ষা মনে রাখুন: ক্ষেত্রগুলো কি disjoint? সব মিলিয়ে কি প্রতিটি বৈধ ফল ঢাকে? আর প্রতিটি ক্ষেত্রের ভেতরে কি গুণের নিয়মের শর্ত (প্রতিটি ফল ঠিক একবার) মানা হয়েছে? দলে পদ থাকলে (অধিনায়ক, সহ-অধিনায়ক) প্রশ্ন আবার ক্রমযুক্ত হয়: একাদশ থেকে অধিনায়ক আর সহ-অধিনায়ক বাছার উপায় P(11, 2) = 110, C(11, 2) = 55 নয়, কারণ দুটি পদ আলাদা।

৮ · তাসের হাত, পরীক্ষার অঙ্ক আর ভুল ধরা

গোনার বইয়ে তাসের হাত গোনা একটি চিরাচরিত অনুশীলন: ৫২টি তাস মানে ১৩টি মান (rank) আর ৪টি রঙের (suit) সব জোড়া। কোনো খেলার নিয়ম লাগবে না; “৫টি তাসের হাত” মানে প্যাকেটের একটি 5-combination, কারণ তাস কোন ক্রমে এল তা গুরুত্বহীন। মোট হাত C(52, 5) = 2598960. কয়েকটি প্রচলিত ধরন:

হাতের ধরনধাপে ধাপে বাছাইসংখ্যা
একই মানের চারটি (four of a kind)মান 13 · সেই মানের চারটিই C(4, 4) · পঞ্চম তাস বাকি 48টি থেকে624
এক মানের তিনটি + আরেক মানের দুটি (full house)তিনের মান 13 · C(4, 3) · দুইয়ের মান বাকি 12 · C(4, 2)13 · 4 · 12 · 6 = 3744
পাঁচটিই একই রঙের (flush, ধারাবাহিকগুলো সহ)রং 4 · সেই রঙের 13টি থেকে C(13, 5)4 · 1287 = 5148

full house-এর হিসাবে একটি সূক্ষ্মতা আছে: তিনটির মান আর দুটির মান আলাদা ভূমিকা পালন করে, তাই সেখানে মান দুটি বাছাই ক্রমযুক্ত, 13 · 12 = P(13, 2), C(13, 2) নয়। তিনটি সাত আর দুটি রাজা একটি হাত, তিনটি রাজা আর দুটি সাত আরেকটি। আর flush-এর 5148-এর মধ্যে একই রঙের পাঁচটি ধারাবাহিক মানের হাতও আছে; সেগুলো আলাদা ধরন ধরলে বাদ দিতে হয় (টেক্কাকে উঁচু ও নিচু দুভাবেই ধরলে এমন হাত 40টি, বাকি থাকে 5108টি হাত)। প্রতিটি সংখ্যা scratch-এ Python দিয়ে যাচাই করা।

পরীক্ষার অঙ্ক: পূর্ণ সমাধান

বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর লিখিত পরীক্ষায় যে ধাঁচের অঙ্ক আসে, তার কয়েকটি:

  1. বাজারঘরের চার অঙ্কের কুপন কোডে কোনো অঙ্ক পুনরাবৃত্ত হবে না, আর প্রথম অঙ্ক 0 হবে না। কয়টি কোড? প্রথম অঙ্ক 9টি (1–9), দ্বিতীয়টি 9টি (0 এখন চলে, কিন্তু প্রথমটি বাদ), তারপর 8, 7: 9 · 9 · 8 · 7 = 4536. বিকল্প: P(10, 4) = 5040 থেকে 0 দিয়ে শুরু হওয়াগুলো P(9, 3) = 504 বাদ, 5040 − 504 = 4536.
  2. CHATTOGRAM শব্দের অক্ষরগুলো কতভাবে সাজানো যায়? দশটি অক্ষর, A দুটি, T দুটি: 10!/(2! 2!) = 3628800/4 = 907200.
  3. ৮ জন রাইডার থেকে ৩ জনের দল, যেখানে রনি আর সুমি একসঙ্গে থাকবেন না। সব দল C(8, 3) = 56; দুজনেই আছেন এমন দল: তৃতীয় জন বাকি ৬ জনের যেকোনো, 6টি। উত্তর 56 − 6 = 50.

ভুল ধরুন: “অন্তত একজন”-এর ফাঁদ

একজন লিখলেন: “প্রশ্ন: ঢাকার ৫ জন আর চট্টগ্রামের ৪ জন থেকে ৪ জনের কমিটি, চট্টগ্রামের অন্তত একজন থাকবেন। সমাধান: আগে চট্টগ্রামের একজন বাছি, 4 উপায়। তারপর বাকি ৮ জন থেকে যেকোনো ৩ জন, C(8, 3) = 56. গুণের নিয়মে উত্তর 4 · 56 = 224টি কমিটি।” পড়ে ভুলটি নিজে খুঁজুন।

ভুল কোথায়: সঠিক উত্তর complement-এ: C(9, 4) − C(5, 4) = 126 − 5 = 121. 224 তো সব কমিটির সংখ্যা 126-এর চেয়েও বেশি, যা নিজেই লাল সংকেত। চট্টগ্রামের দুজন (X আর Y) আছেন এমন কমিটি দুবার গোনা হয়েছে: একবার X-কে “প্রথমে বাছা” ধরে, একবার Y-কে; অথচ কমিটিতে “প্রথমে বাছা” সদস্য বলে কিছু নেই। নিরাপদ নিয়ম: “অন্তত একজন” দেখলে আগে complement (“একজনও না”) ভাবুন।

আরও গভীরে: n! কত দ্রুত বাড়ে, তার নিখুঁত মাপ দেয় Stirling-এর সূত্র n! ≈ √(2πn) (n/e)n, যার আপেক্ষিক ভুল n বাড়লে শূন্যের দিকে যায়; তা থেকে C(2n, n) ≈ 4n/√(πn) পাওয়া যায়। গোল টেবিলের প্রশ্নটির সাধারণ রূপ হলো একটি group (এখানে rotation-এর group) দিয়ে “একই” ধরা বিন্যাস গোনা; যখন কিছু বিন্যাস নিজের rotation-এর সঙ্গে মিলে যায় (যেমন একই রঙের পুঁতি বারবার থাকলে), তখন সরল ভাগ কাজ করে না, আর Burnside-এর lemma ও Pólya-র গণনা তত্ত্ব লাগে। কম্পিউটার বিজ্ঞানে প্রতিটি permutation-কে 0 থেকে n! − 1 পর্যন্ত একটি সংখ্যা দেওয়ার (ranking) কৌশল factorial number system ব্যবহার করে, যার ঘনিষ্ঠ আত্মীয় পর্ব ৩৬-এ আসবে।

পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:

  • ১০ জন থেকে সভাপতি, সম্পাদক আর কোষাধ্যক্ষ কতভাবে? পদ আলাদা, তাই P(10, 3) = 720.
  • ১০ জন থেকে ৩ জনের সাধারণ কমিটি? C(10, 3) = 120 = 720/3!.
  • ৬ জনকে গোল টেবিলে? (6 − 1)! = 120; মালার মতো উল্টানো গেলে 60.
  • BANANA-র অক্ষর কতভাবে সাজানো যায়? 6!/(3! 2!) = 60.
  • একটি অষ্টভুজের কর্ণ কয়টি? দুই শীর্ষবিন্দুর জোড়া C(8, 2) = 28, তার 8টি বাহু, তাই 20টি কর্ণ।

৯ · AI-এর যুগে — গোনার উত্তর যাচাই

“কতভাবে” প্রশ্নে AI সহকারীরা প্রায়ই চমৎকার ব্যাখ্যাসহ ভুল সংখ্যা দেয়, কারণ গোনার ভুল দেখতে যুক্তিসংগত। এই পর্বের প্রায় প্রতিটি ফাঁদে তারা নিয়মিত পড়ে:

AI-এর ভুলকীভাবে ধরবেন
ক্রম গুরুত্বপূর্ণ কি না ভুল পড়া: পদহীন কমিটিতে P, বা পদওয়ালা বাছাইয়ে Cপ্রশ্ন করুন: দুটি ফলের মধ্যে শুধু ক্রমের পার্থক্য হলে কি তারা আলাদা? ছোট উদাহরণে তালিকা করে দেখুন
“অন্তত একজন”-এ আগে একজন নিশ্চিত করে বাকিদের যেকোনোভাবে বাছা (overcounting)উত্তর মোট সংখ্যার চেয়ে বেশি কি না দেখুন; complement দিয়ে আবার গুনতে বলুন
পুনরাবৃত্ত অক্ষরে ভাগ ভুলে যাওয়া, বা ভুল factorial দিয়ে ভাগপ্রতিটি অক্ষর কতবার আছে, তা আগে লিখতে বলুন; len(set(permutations(w))) চালান
গোল টেবিলে n!, বা আয়নার প্রতিবিম্ব অনুমতি না থাকলেও 2 দিয়ে ভাগপ্রশ্নে rotation আর প্রতিবিম্ব কী ধরা হয়েছে, স্পষ্ট করুন; n = 4-এ হাতে তালিকা করুন
ক্ষেত্রভিত্তিক গণনায় একটি ক্ষেত্র বাদ বা দুই ক্ষেত্রে একই ফলক্ষেত্রগুলো disjoint কি না আর সব মিলে সব ফল ঢাকে কি না জিজ্ঞেস করুন; ক্ষেত্রের যোগফল complement-এর সঙ্গে মেলান
সূত্রের শর্ত বাদ (0 ≤ r ≤ n), বা বড় সংখ্যায় factorial-এর পাটিগণিতে ভুলPython-এর math.comb আর math.perm দিয়ে সংখ্যাটি নিজে হিসাব করুন

AI-এর কাছে গোনার সমাধান চাইলে এমন কাঠামো দিন, যাতে প্রতিটি সিদ্ধান্ত আলাদা করে যাচাই করা যায়:

নিচের গোনার প্রশ্নটি ধাপে ধাপে সমাধান করো: প্রশ্ন: [এখানে প্রশ্ন] ১. প্রথমে বলো আমরা কী গুনছি: ক্রমযুক্ত তালিকা (tuple) না ক্রমহীন দল (subset)? পুনরাবৃত্তি চলে কি না? কেন? ২. শর্ত থাকলে ক্ষেত্রগুলো লেখো, আর দেখাও যে সেগুলো disjoint এবং সব সম্ভাবনা ঢাকে। ৩. প্রতিটি গুণের ধাপে বলো, প্রতিটি ফল ঠিক একবার তৈরি হচ্ছে কি না; "আগে একজন নিশ্চিত করি" ধরনের ধাপ থাকলে overcounting হচ্ছে কি না পরীক্ষা করো। ৪. complement বা অন্য একটি পদ্ধতিতে আবার গুনে দুই উত্তর মেলাও। ৫. ছোট মানে brute force করার একটি Python কোড দাও (itertools দিয়ে), যা সূত্রের সঙ্গে তুলনা করে। ৬. কোনো সূত্র ব্যবহার করলে তার শর্ত (যেমন 0 ≤ r ≤ n, জিনিসগুলো আলাদা কি না) উল্লেখ করো।

AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট

সবচেয়ে সস্তা প্রথম পরীক্ষা: AI-এর যুক্তিটি সংখ্যা ছোট করে চালান। ১৫ জনের স্কোয়াডের বদলে ৫ জন, NARAYANGANJ-এর বদলে AAB. ছোট প্রশ্নে সব ফল হাতে বা itertools দিয়ে তালিকা করা যায়; সেখানে যুক্তি ভুল সংখ্যা দিলে বড় প্রশ্নেও ভুল।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।

প্র ০১“Combination lock” নামের তালাটি কি আসলে combination? ক্রম গুরুত্বপূর্ণ কি না, তা নিশ্চিতভাবে ঠিক করার উপায় কী?

নামটি গাণিতিকভাবে ভুল, আর ভুলটি শিক্ষণীয়। তিনটি চাকার তালায়, প্রতিটি চাকায় 0 থেকে 9, কোড 3-7-2 আর 2-7-3 আলাদা: একটিতে খোলে, অন্যটিতে খোলে না। তাই ক্রম গুরুত্বপূর্ণ। আবার একই অঙ্ক বারবার আসতে পারে (5-5-1 বৈধ কোড)। এটি তাই পুনরাবৃত্তিসহ ক্রমযুক্ত বাছাই, মোট 103 = 1000টি কোড। যদি সত্যিই “combination” হতো, অর্থাৎ শুধু কোন তিনটি আলাদা অঙ্ক তা গুরুত্বপূর্ণ হতো, তবে কোড হতো মাত্র C(10, 3) = 120টি, আর তালা অনেক দুর্বল হতো। দৈনন্দিন ভাষায় “combination” মানে প্রায়ই শুধু “মিশ্রণ” বা “জোড়া লাগানো”, গাণিতিক অর্থ নয়; বই আর পরীক্ষার প্রশ্নে এই ধরনের শব্দের ফাঁদ থাকে।

ক্রম গুরুত্বপূর্ণ কি না ঠিক করার নির্ভরযোগ্য পরীক্ষা হলো একটি নির্দিষ্ট ফল নিয়ে তার উপাদানগুলোর জায়গা অদলবদল করা, তারপর জিজ্ঞেস করা: এটি কি এখন আলাদা ফল? তাকের ঘরে পণ্য অদলবদল করলে গ্রাহক আলাদা পাতা দেখেন: ক্রম গুরুত্বপূর্ণ। কমিটির সদস্যদের নামের তালিকা উল্টে লিখলে কমিটি একই থাকে: গুরুত্বহীন। কিন্তু সভাপতি আর সম্পাদক অদলবদল হলে কমিটি বদলায়: পদ থাকলে ক্রম ফিরে আসে। মোবাইল নম্বর, পাসওয়ার্ড আর PIN-এ অদলবদল মানে আলাদা নম্বর; লটারির টিকিটে সাধারণত শুধু কোন সংখ্যা, ক্রম নয়।

আরেকটি সূক্ষ্মতা: একই প্রশ্নের দুটি বৈধ গাণিতিক মডেল থাকতে পারে, যতক্ষণ দুই পাশ একই জিনিস গোনে। ৮ জন থেকে ৩ জনের দল বাছার প্রশ্ন একটি subset গোনা হিসেবে C(8, 3), আবার “৮ জনের প্রত্যেককে হ্যাঁ বা না লেবেল দেওয়া, যেখানে ঠিক ৩টি হ্যাঁ” হিসেবে একটি বিন্যাস গোনা: 8!/(3! 5!), পুনরাবৃত্ত জিনিসের সূত্রে। দুটি একই সংখ্যা, কারণ দুই মডেলের মধ্যে একটি bijection আছে।

মূল উপলব্ধি: নাম বা শব্দ দেখে নয়, একটি নির্দিষ্ট ফলের উপাদান অদলবদল করে দেখে ঠিক করুন ক্রম গুরুত্বপূর্ণ কি না; তারপর পুনরাবৃত্তি চলে কি না, এই দুই প্রশ্নেই চারটি সূত্রের কোনটি খাটে তা ঠিক হয়।

প্র ০২Permutation আর combination-এর সূত্র প্রথম কারা ভেবেছিলেন? ইতিহাসে এই গোনার উৎস কোথায়?

গোনার এই প্রশ্নগুলো বহু সভ্যতায় স্বাধীনভাবে এসেছে, আর অনেক তারিখ নিয়ে ইতিহাসবিদদের মধ্যে অনিশ্চয়তা আছে, তাই নিচের দাবিগুলো সাবধানে পড়ুন। প্রাচীন ভারতের চিকিৎসাশাস্ত্রের গ্রন্থ সুশ্রুত সংহিতায় ছয়টি মৌলিক স্বাদ থেকে এক বা একাধিক স্বাদের মোট 63টি মিশ্রণের কথা আছে বলে প্রায়ই উল্লেখ করা হয়; সংখ্যাটি 26 − 1, অর্থাৎ অশূন্য subset-এর সংখ্যা। গ্রন্থটির রচনাকাল নিয়ে মতভেদ আছে। ছন্দশাস্ত্রে পিঙ্গলের কাজ, যা binomial coefficient-এর সঙ্গে যুক্ত, পর্ব ৩৪-এ আসবে।

সাধারণ সূত্রের দিকে এগোনো একটি পরিচিত নাম জৈন গণিতবিদ মহাবীর: নবম শতকের (প্রায় ৮৫০ সাল) তাঁর গ্রন্থ গণিতসারসংগ্রহে n-টি থেকে r-টি বাছাইয়ের সংখ্যার একটি সাধারণ নিয়ম আছে বলে গণিতের ইতিহাসের বইগুলো উল্লেখ করে। দ্বাদশ শতকে ভাস্করাচার্যের (ভাস্কর দ্বিতীয়) লীলাবতীতে (প্রায় ১১৫০) অঙ্কের বিন্যাস, পুনরাবৃত্ত অঙ্কসহ, গোনার নিয়ম আছে বলে প্রায়ই বলা হয়। আরবি ভাষার জগতে অষ্টম শতকের ভাষাবিদ আল-খলিল ইবনে আহমদ সম্ভাব্য শব্দ গোনার কাজে বিন্যাস নিয়ে ভেবেছিলেন বলে উল্লেখ আছে, আর পরের শতকগুলোতে মাগরিবের গণিতবিদরা এই ধারা এগিয়ে নেন।

ইউরোপে ১৩২১ সালে লেভি বেন গেরশন (Gersonides) P(n, r) আর C(n, r)-এর সূত্র প্রমাণসহ লিখেছিলেন বলে উল্লেখ করা হয়, আর তাঁর যুক্তি mathematical induction-এর একটি আদি রূপ বলে অনেকে মনে করেন (পর্ব ১০ “Mathematical induction — এক ধাপ থেকে অসীম পর্যন্ত”)। সতেরো শতকে Pascal আর Fermat-এর চিঠিপত্রে জুয়ার সমস্যা থেকে সম্ভাবনা তত্ত্বের যাত্রা শুরু হয়, আর সেখানে combination কেন্দ্রীয় ভূমিকা নেয়। Jacob Bernoulli-র মৃত্যুর পর ১৭১৩ সালে প্রকাশিত “Ars Conjectandi”-র একটি বড় অংশ permutation আর combination-এর তত্ত্ব; “permutation” শব্দের আধুনিক ব্যবহারের প্রচারে এই বইয়ের ভূমিকা প্রায়ই উল্লেখ করা হয়।

মূল উপলব্ধি: permutation আর combination কোনো একজনের আবিষ্কার নয়; বহু সংস্কৃতি বাস্তব প্রশ্ন থেকে স্বাধীনভাবে এদের কাছে পৌঁছেছে, আর প্রমাণসহ সাধারণ রূপ এসেছে ধীরে ধীরে।

প্র ০৩n! কত দ্রুত বাড়ে? ভালোভাবে শাফল করা ৫২ তাসের একটি প্যাকেটের ক্রম কেন প্রায় নিশ্চিতভাবে আগে কখনো ঘটেনি?

Factorial যেকোনো সূচকীয় ফাংশন cn-এর চেয়েও শেষ পর্যন্ত দ্রুত বাড়ে। 10! = 3628800, প্রায় ছত্রিশ লাখ; 20! ≈ 2.43 × 1018; আর 52! ≈ 8.07 × 1067, অর্থাৎ ৬৮ অঙ্কের একটি সংখ্যা (scratch-এ Python দিয়ে হিসাব করা)। তুলনার জন্য: পৃথিবীর বয়স সেকেন্ডে মাপলে মোটামুটি 1017-এর ঘরে। তাই যদি পৃথিবীর সব মানুষ ইতিহাসের শুরু থেকে প্রতি সেকেন্ডে একটি করে প্যাকেট শাফল করতেন, তবুও মোট শাফল 52!-এর তুলনায় নগণ্য একটি ভগ্নাংশ।

এ থেকে একটি সম্ভাবনার যুক্তি আসে (বিস্তারিত পর্ব ৩৮ “বিচ্ছিন্ন সম্ভাবনা — sample space, event আর Laplace-এর সংজ্ঞা”-এ): প্যাকেট সত্যিই সমসম্ভাব্য এলোমেলো হলে, আপনার হাতের ক্রমটি আগে কখনো ঘটার সম্ভাবনা এতই ক্ষুদ্র যে কার্যত শূন্য। এখানে শর্তটি জরুরি: “ভালোভাবে শাফল করা”। Dave Bayer আর Persi Diaconis-এর ১৯৯২ সালের একটি পরিচিত গবেষণা অনুযায়ী ৫২ তাসের প্যাকেটকে প্রায় এলোমেলো করতে মোটামুটি সাতবার riffle shuffle (দুই ভাগ করে মেশানো) লাগে বলে উল্লেখ করা হয়; কম শাফলে আগের ক্রমের ছাপ থেকে যায়।

প্রোগ্রামিংয়ে এই বৃদ্ধির দুটি সরাসরি ফল আছে। প্রথমত, পূর্ণসংখ্যার সীমা: 20! একটি signed 64-bit integer-এ ধরে, কিন্তু 21! ≈ 5.1 × 1019 unsigned 64-bit-এর সীমাও (প্রায় 1.8 × 1019) ছাড়ায়। C বা Java-তে factorial দিয়ে C(n, r) হিসাব করলে তাই n = 21-এই overflow, যদিও উত্তরটি ছোট হতে পারে। Python-এর int-এর সীমা নেই, তাই এই সমস্যা সেখানে দেখা যায় না। দ্বিতীয়ত, brute force-এর সীমা: সব permutation পরীক্ষা করা অ্যালগরিদম (যেমন ছোট traveling salesman সমস্যায়) n = 10–12-এর পর অচল হয়ে যায়। কেন, আর কী করা যায়, তা DSA কোর্সের পর্ব ৫৬ (backtracking)-এ।

n! কত বড় তার একটি ভালো আন্দাজ দেয় Stirling-এর সূত্র n! ≈ √(2πn)(n/e)n, যা আঠারো শতকে de Moivre আর Stirling-এর কাজ থেকে এসেছে বলে উল্লেখ করা হয়; n = 10-এই এর আপেক্ষিক ভুল এক শতাংশের কম।

মূল উপলব্ধি: n! এত দ্রুত বাড়ে যে ছোট n-এও সব বিন্যাস গোনা বা পরীক্ষা করা অসম্ভব হয়ে যায়; তাই সূত্র আর প্রমাণ দরকার, আর brute force শুধু ছোট ক্ষেত্রে সূত্র যাচাইয়ের হাতিয়ার।

প্র ০৪একটি cipher-এর সম্ভাব্য key 26!টি হলেও কেন তা সহজে ভাঙা যায়? গোনা নিরাপত্তা সম্পর্কে কী বলে, আর কী বলে না?

Substitution cipher-এ ইংরেজি বর্ণমালার প্রতিটি অক্ষরকে আরেকটি অক্ষর দিয়ে বদলানো হয়, আর বদলের নিয়মটি ২৬টি অক্ষরের একটি permutation. এই পর্বের ভাষায় key-এর সংখ্যা 26! ≈ 4.03 × 1026, যা প্রায় 288. সংখ্যাটি বিশাল: প্রতি সেকেন্ডে একশো কোটি key পরীক্ষা করলেও সব key দেখতে কোটি কোটি বছর লাগত। তবু এই cipher হাতে, কাগজ-কলমে ভাঙা যায়, আর নবম শতকের আরব দার্শনিক আল-কিন্দি frequency analysis-এর (অক্ষরের ঘনত্ব গোনা) একটি আদি বর্ণনা দিয়েছিলেন বলে সাধারণত উল্লেখ করা হয়।

কারণটি হলো, আক্রমণকারী সব key একে একে পরীক্ষা করেন না। ইংরেজিতে e, t, a-এর মতো অক্ষর বেশি আসে; সাংকেতিক লেখায় সবচেয়ে বেশি আসা অক্ষরটি সম্ভবত e-এর বদলি। একটি অক্ষর মিলে গেলে বাকি সম্ভাবনা অনেক কমে যায়, আর key-এর বিশাল স্থানটি টুকরো টুকরো করে আলাদাভাবে অনুসন্ধান করা যায়। পর্ব ২৭ “Classical cipher — shift, affine আর frequency analysis”-এ এই আক্রমণ প্রমাণসহ দেখানো হয়েছে।

তাই গোনা নিরাপত্তার একটি প্রয়োজনীয় শর্ত দেয়, যথেষ্ট শর্ত নয়। key-এর সংখ্যা ছোট হলে (যেমন shift cipher-এ মাত্র ২৬টি) brute force নিশ্চিতভাবে জেতে; এই নিচের সীমাটি গোনা দিয়েই বের হয়। কিন্তু key-এর সংখ্যা বড় হলেও কাঠামোগত দুর্বলতা থাকতে পারে। একই কথা পাসওয়ার্ডে খাটে: বাজারঘরের নিয়ম যদি ৮ অক্ষরের পাসওয়ার্ডে ৬২টি অক্ষরের যেকোনোটি অনুমোদন করে, তাত্ত্বিক সংখ্যা 628; কিন্তু মানুষ যদি নাম আর জন্মসাল দিয়ে পাসওয়ার্ড বানান, আসল অনুসন্ধানের স্থান তার চেয়ে বহুগুণ ছোট।

আধুনিক cryptography-তে নিরাপত্তার দাবি তাই গণনার কঠিনতার ওপর দাঁড়িয়ে, শুধু key গোনার ওপর নয়, আর বাস্তব ব্যবহারে পরীক্ষিত লাইব্রেরি লাগে; বিস্তারিত Cybersecurity কোর্সের পর্ব ০৭-এ।

মূল উপলব্ধি: বিশাল key-স্থান brute force ঠেকায়, কিন্তু কাঠামো ব্যবহার করা চালাক আক্রমণ ঠেকায় না; গোনা নিরাপত্তার নিচের সীমা দেয়, নিশ্চয়তা নয়।

প্র ০৫প্রোগ্রামে C(n, r) কীভাবে হিসাব করা উচিত? n!/(r!(n − r)!) সূত্রটি সরাসরি কোডে লেখায় সমস্যা কোথায়?

সূত্রটি গাণিতিকভাবে নিখুঁত, কিন্তু সরাসরি কোডে লিখলে তিনটি সমস্যা। প্রথমত overflow: C(30, 2) = 435 ছোট সংখ্যা, অথচ পথে 30! ≈ 2.65 × 1032, যা 64-bit integer-এ ধরে না। দ্বিতীয়ত float-এ হিসাব করলে বড় n-এ নির্ভুলতা হারায়, আর পূর্ণসংখ্যার উত্তর 434.99999 হয়ে যেতে পারে। তৃতীয়ত অপচয়: n! সম্পূর্ণ হিসাব করে তারপর ভাগ করা অপ্রয়োজনীয়।

প্রচলিত সমাধান হলো গুণফলের রূপ ব্যবহার করে ধাপে ধাপে ভাগ করা: res = 1; i = 1 থেকে r পর্যন্ত res = res · (n − r + i) / i. প্রতিটি ধাপের পর res নিজেই একটি binomial coefficient, C(n − r + i, i), তাই ভাগটি সবসময় নিঃশেষে হয়, আর মধ্যবর্তী মান চূড়ান্ত উত্তরের চেয়ে খুব বেশি বড় হয় না। সঙ্গে প্রতিসাম্য: r > n/2 হলে r-এর জায়গায় n − r নিলে ধাপ কমে (উপপাদ্য ৪.১-এর ব্যবহারিক প্রয়োগ)। Python-এর math.comb (Python 3.8 থেকে) পূর্ণসংখ্যায় নির্ভুল উত্তর দেয়, তাই সেখানে নিজে লেখার দরকার প্রায় নেই।

অনেক C(n, r) একসঙ্গে লাগলে (যেমন competitive programming-এ) আরেকটি পথ হলো Pascal-এর recurrence C(n, r) = C(n − 1, r − 1) + C(n − 1, r) দিয়ে একটি টেবিল ভরা, যা dynamic programming-এর একটি প্রথম উদাহরণ; টেবিল ভরার কৌশল DSA কোর্সের পর্ব ৫২-এ, আর recurrence-টির combinatorial প্রমাণ পর্ব ৩৪-এ। উত্তর একটি বড় prime p দিয়ে mod নিয়ে চাইলে factorial আর তাদের modular inverse আগে থেকে হিসাব করে রাখা হয়, যেখানে পর্ব ২৪-এর Fermat-এর ছোট উপপাদ্য সরাসরি কাজে লাগে।

আর একটি ধারণাগত সতর্কতা: C(n, r) নিজেই খুব দ্রুত বাড়ে। 40টি বৈশিষ্ট্য থেকে 20টির সব subset পরীক্ষা করতে চাইলে C(40, 20) ≈ 1.38 × 1011টি ক্ষেত্র। তাই “সব combination চেষ্টা করি” পদ্ধতি ছোট n-এর বাইরে চলে না, আর অ্যালগরিদম ডিজাইনে এই সংখ্যাটি আগে হিসাব করে নেওয়া একটি ভালো অভ্যাস।

মূল উপলব্ধি: একই গাণিতিক সংখ্যার জন্য ভালো আর খারাপ গণনা-পদ্ধতি আছে; ধাপে ধাপে নিঃশেষ ভাগ, প্রতিসাম্য আর Pascal-এর recurrence হলো বড় factorial এড়িয়ে নির্ভুল উত্তর পাওয়ার উপায়।

অনুশীলন

আগে খাতায় করুন, তারপর উত্তর খুলে মেলান।

  1. প্রমাণ: 1 ≤ k ≤ n পূর্ণসংখ্যার জন্য k · C(n, k) = n · C(n − 1, k − 1). একটি বীজগাণিতিক আর একটি combinatorial প্রমাণ দিন। (ইঙ্গিত: n জন থেকে k সদস্যের একটি কমিটি আর তার একজন সভাপতি।)

    বীজগাণিতিক: k · n!/(k!(n − k)!) = n!/((k − 1)!(n − k)!), আর n · (n − 1)!/((k − 1)!(n − k)!) = n!/((k − 1)!(n − k)!). দুই পাশ সমান। ∎

    Combinatorial (একই সেট দুইভাবে গোনা): সেট X = সব জোড়া (কমিটি, সভাপতি), যেখানে কমিটি k সদস্যের আর সভাপতি সেই কমিটির একজন।

    1. প্রথম গোনা: আগে কমিটি, C(n, k) উপায়; তারপর তার k সদস্য থেকে সভাপতি, k উপায়। |X| = k · C(n, k). — গুণের নিয়ম
    2. দ্বিতীয় গোনা: আগে সভাপতি, n উপায়; তারপর বাকি n − 1 জন থেকে কমিটির বাকি k − 1 জন, C(n − 1, k − 1) উপায়। |X| = n · C(n − 1, k − 1). — গুণের নিয়ম
    3. একই সেটের আকার, তাই দুই রাশি সমান। ∎

    প্রতিটি জোড়া দুই গোনাতেই ঠিক একবার আসে, কারণ সভাপতির পদটি আলাদা: তাই এখানে কোনো overcounting নেই। scratch-এ n < 30-এর সব মানে Python দিয়েও মিলিয়ে দেখা হয়েছে।

  2. হিসাব: (ক) CHATTOGRAM শব্দের অক্ষরগুলোর কয়টি বিন্যাসে দুটি T পাশাপাশি থাকে? (খ) ৬ জনকে গোল টেবিলে কতভাবে বসানো যায়, যদি দুজন নির্দিষ্ট মানুষ পাশাপাশি বসতে না চান? (গ) ১২টি পণ্য থেকে ৩টি নিয়ে “আজকের অফার”-এর প্রথম, দ্বিতীয় আর তৃতীয় স্থান কতভাবে ঠিক করা যায়, আর শুধু কোন তিনটি পণ্য অফারে যাবে তা কতভাবে?

    (ক) দুটি T-কে একটি block “TT” ধরুন: এখন ৯টি একক (C, H, A, TT, O, G, R, A, M), যার মধ্যে A দুটি। বিন্যাস 9!/2! = 362880/2 = 181440. Block-এর ভেতরে দুটি T একই রকম, তাই আর 2 দিয়ে গুণ নেই। (scratch-এ brute force-এও 181440.)

    (খ) সব গোল বসা (6 − 1)! = 120. দুজন পাশাপাশি: তাঁদের একটি block ধরলে ৫টি একক, (5 − 1)! = 24, block-এর ভেতরে 2 ক্রম, মোট 48. উত্তর 120 − 48 = 72.

    (গ) স্থান আলাদা, তাই P(12, 3) = 12 · 11 · 10 = 1320. শুধু কোন তিনটি: C(12, 3) = 220 = 1320/3!.

  3. আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে। তারপর যেকোনো Python-এ (3.8 বা নতুন) চালিয়ে মেলান।
    from math import comb, perm
    from itertools import permutations
    print(perm(4, 2), comb(4, 2))
    print(len(set(permutations("ABA"))))
    print(comb(6, 0), comb(6, 7), perm(3, 3))
    12 6
    3
    1 0 6

    P(4, 2) = 4 · 3 = 12, আর C(4, 2) = 12/2! = 6. “ABA”-র 3! = 6টি tuple-এর মধ্যে আলাদা মাত্র ABA, AAB, BAA: 3!/2! = 3. C(6, 0) = 1 (খালি দল একটি); C(6, 7) = 0, কারণ ছয়জন থেকে সাতজন বাছা যায় না (Python এখানে error দেয় না); P(3, 3) = 3! = 6.

  4. প্রমাণের ভুল ধরুন: একজন লিখলেন: “দাবি: ৫২ তাসের প্যাকেট থেকে ঠিক দুটি জোড়ার (দুই আলাদা মানের দুটি করে তাস, আর পঞ্চম তাস তৃতীয় একটি মানের) হাত 247104টি। প্রমাণ: প্রথম জোড়ার মান 13 উপায়, তার দুটি তাস C(4, 2) = 6; দ্বিতীয় জোড়ার মান বাকি 12 উপায়, তার দুটি তাস 6; পঞ্চম তাস বাকি দুই মান বাদে 44টি থেকে। গুণের নিয়মে 13 · 6 · 12 · 6 · 44 = 247104. ∎” ভুল কোথায়, আর সঠিক উত্তর কত?
    • ভুল: দুটি জোড়ার ভূমিকা একই, অথচ প্রমাণে “প্রথম জোড়া” আর “দ্বিতীয় জোড়া” আলাদা ধরা হয়েছে। সাতের জোড়া আর রাজার জোড়ার একটি হাত দুবার গোনা হয়েছে: একবার সাতকে প্রথম ধরে, একবার রাজাকে। মান দুটি বাছাই আসলে ক্রমহীন: P(13, 2) = 156-এর বদলে C(13, 2) = 78.
    • সঠিক: C(13, 2) · C(4, 2) · C(4, 2) · 44 = 78 · 6 · 6 · 44 = 123552, ঠিক অর্ধেক (প্রতিটি হাত ঠিক দুবার গোনা হয়েছিল, ভাগের নিয়ম)। scratch-এ Python দিয়ে যাচাই করা।
    • তুলনা করুন full house-এর সঙ্গে, যেখানে তিনটির মান আর দুটির মান আলাদা ভূমিকায়, তাই 13 · 12 সঠিক ছিল। শিক্ষা: দুটি বাছাই “অদলবদল করলে একই ফল” দিলে সেগুলো ক্রমহীন।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমশর্তসহ একটি বাছাইয়ের প্রশ্ন (যেমন “অন্তত ৪ জন বোলার”) সমাধানের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. ক্রম গুরুত্বপূর্ণ কি না আর পুনরাবৃত্তি চলে কি না ঠিক করা
  2. শর্ত অনুযায়ী disjoint ক্ষেত্রগুলো লেখা
  3. প্রতিটি ক্ষেত্রে গুণের নিয়মে C(n, r)-এর গুণফল হিসাব করা
  4. যোগের নিয়মে ক্ষেত্রগুলোর ফল যোগ করা
  5. Complement বা ছোট brute force দিয়ে উত্তর যাচাই করা

১০ জন প্রার্থী থেকে একজন সভাপতি, একজন সম্পাদক আর একজন কোষাধ্যক্ষ (তিনজন আলাদা মানুষ) কতভাবে বাছা যায়?

  • 120
  • 1000
  • 720
  • 30

BANANA শব্দের অক্ষরগুলো কতভাবে সাজানো যায়?

  • 720
  • 60
  • 120
  • 20

৭ জন আলাদা মানুষকে একটি গোল টেবিলে কতভাবে বসানো যায়, যদি শুধু rotation-কে একই বসা ধরা হয়?

  • 720
  • 5040
  • 360
  • 120

৬ জন বোলার আর ৯ জন ব্যাটারের ১৫ জনের স্কোয়াড থেকে একাদশ, যেখানে অন্তত ৪ জন বোলার। “C(6, 4) · C(11, 7) = 4950” উত্তরটি সম্পর্কে কোনটি সঠিক?

  • এটি সঠিক
  • কিছু দল বাদ পড়েছে, তাই উত্তর কম
  • প্রতিটি দল ঠিক দুবার গোনা, তাই উত্তর 2475
  • overcounting: সঠিক উত্তর 1170

C(n, r) = C(n, n − r)-এর একটি combinatorial প্রমাণে কোন bijection ব্যবহার করা যায়? (S একটি n-উপাদানের সেট, T তার একটি r-উপাদানের subset)

  • T ↦ T-এর উপাদানগুলোর একটি ক্রম
  • T ↦ S − T (complement)
  • T ↦ T ∪ {x}, একটি নির্দিষ্ট x-এর জন্য
  • T ↦ T-এর power set

ঢাকার ৫ জন আর চট্টগ্রামের ৪ জন থেকে ৪ জনের কমিটি, যেখানে চট্টগ্রামের অন্তত একজন থাকবেন। কমিটি কয়টি?

  • 224
  • 126
  • 121
  • 81

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. প্রথম প্রশ্ন: ক্রম গুরুত্বপূর্ণ? পুনরাবৃত্তি চলে? উপাদান অদলবদল করে দেখুন ফল বদলায় কি না।
  2. P(n, r) = n!/(n − r)! গুণের নিয়ম থেকে; C(n, r) = n!/(r!(n − r)!) ভাগের নিয়ম থেকে, কারণ প্রতিটি দল r!টি তালিকায় আসে।
  3. C(n, r) = C(n, n − r): কাদের নেবেন বাছা = কাদের রাখবেন বাছা; complement একটি bijection.
  4. বিশেষ বিন্যাস: একই রকম জিনিসে n!/(n1!⋯nk!); গোল টেবিলে (n − 1)!, আর n ≥ 3 হলে আয়নাসহ (n − 1)!/2 উপায়।
  5. শর্ত থাকলে: disjoint ক্ষেত্রে ভাগ করুন বা complement নিন; “আগে একজন নিশ্চিত, তারপর যে কেউ” প্রায় সবসময় overcounting. ছোট ক্ষেত্রে brute force দিয়ে মেলান।

পরের পর্বে: পর্ব ৩৪ “Binomial coefficient, Pascal-এর ত্রিভুজ আর combinatorial identity”: C(n, r) কেন (x + y)n-এর সহগ, Pascal-এর ত্রিভুজ, আর এই পর্বের মতো combinatorial প্রমাণে আরও অনেক identity.

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান