شائع ہوا: 2025-09-08

گرڈ سے کوڈ تک: سڈوکو فنکشنل پروگرامنگ کا بہترین راستہ کیوں ہے؟

عزم سے بھری شکلیں روشنی میں ڈھلتی ہیں جو منطقی سوچ کو خالص کوڈ کے لیے منتقل کرتی ہے۔

سوڈوکو کو عالمی سطح پر ایک کلاسیک منطق کے پہیلی کے طور پر جانا جاتا ہے، لیکن پروگرامرز کے لیے اس کی اعداد کی گرڈ کے نیچے ایک پوشیدہ تہہ موجود ہوتی ہے۔ جبکہ زیادہ تر شوقین افراد 81 خانوں کو دیکھتے ہیں جو ہندسوں سے بھرنا باقی ہے، ڈویلپرز اکثر ایک موزوں نفاذ کا چیلنج دیکھتے ہیں: ایک پابندی کی تکمیل والا مسئلہ جو فنکشنل پروگرامنگ (FP) کے اصولوں پر خوبصورتی سے فٹ بیٹھتا ہے۔ سوڈوکو اور FP کا ملاپ اس بات کو سمجھنے کا واضح طریقہ پیش کرتا ہے کہ ڈیٹا کیسے متغیر حالت (mutable state) کے اضافی بوجھ کے بغیر خالص ٹرانسفارمیشنز کے ذریعے بہہ سکتا ہے۔

اس مضمون میں، ہم اس بات کا جائزہ لیں گے کہ سوڈوکو فنکشنل تصورات کے لیے ایک مثالی شروعاتی نقطہ کیوں ہے۔ ہم دیکھیں گے کہ غیر متغیر ڈیٹا سٹرکچرز، ری کرشن (recursion)، اور پیٹرن میچنگ پیچیدہ منطقی پہیلیوں کے حل میں کیسے خوبصورت نتائج پیدا کرتے ہیں۔ چاہے آپ FP کا ماہر ہوں یا صرف اپنے پسندیدہ تفریحی عمل کے ریاضیاتی بنیادوں میں دلچسپی رکھتے ہوں، یہ تعلق الگوتھمک ڈیزائن کے پیچھے کی ساخت کو اجاگر کرتا ہے۔

غیر متغیر بورڈ: ڈیٹا بطور ساخت

روایتی امپیریٹیو پروگرامنگ میں، سوڈوکو گرڈ حل کرنے میں اکثر ایے (array) کی حالت کو تبدیل کرنا شامل ہوتا ہے۔ آپ ایک عدد تلاش کرتے ہیں، اسے رکھتے ہیں، میموری کے مقام کو اپ ڈیٹ کرتے ہیں اور اگلا قدم اٹھاتے ہیں۔ فنکشنل پروگرامنگ میں، ہم مکمل طور پر تبدیلی (mutation) سے گریز کرتے ہیں۔ موجودہ بورڈ کو تبدیل کرنے کے بجائے، ہم بورڈ کا ایک نیا ورژن بناتے ہیں جس میں اپ ڈیٹ لاگو ہوتا ہے۔

یہ تصور اس طریقے سے اچھی طرح مطابقت رکھتا ہے جس طرح انسان اکثر کاغذ پر سوڈوکو کو حل کرتے ہیں۔ آپ شاید کسی خانے میں ایک عدد کو ذہنی طور پر تصور کر سکتے ہیں بغیر اسے لکھے، یہاں تک کہ جب تک آپ اس کی درستی سے یقین نہیں ہو جاتے۔ کوڈ میں، یہ غیر متغیر ڈیٹا سٹرکچرز کے ذریعے حاصل کیا جاتا ہے۔ جب آپ کسی خاص خانے میں "5" رکھتے ہیں، تو فنکشن اصل گرڈ کو تبدیل کرنے کے بجائے ایک بالکل نیا گرڈ کنفیگریشن واپس کرتا ہے۔ اس سے یقینی بنایا جاتا ہے کہ پچھلی حالتیں درست اور قابل رسائی رہتی ہیں، جو بیک ٹریکنگ الگوتھمز کے لیے انتہائی اہم ہے جہاں آپ کو بغیر کسی سائیڈ ایفیکٹ کے تبدیلیوں کو واپس لینے کی ضرورت ہوتی ہے۔

ری کرشن: منطق کا قدرتی بہاؤ

سوڈوکو کے مسائل فطری طور پر ریکرسیو (recursive) نوعیت کے ہوتے ہیں۔ ایک خانہ حل کرنے کے لیے، آپ کو یہ یقینی بنانا ہوگا کہ وہ اپنے قطار (row)، کالم اور 3x3 خانے کے حوالے سے پابندیوں کو پورا کرتا ہے۔ اگر کوئی عدد کام نہیں کرتا، تو آپ کو پچھلے فیصلے کے نقطے پر واپس جانا (backtrack) پڑتا ہے۔

FP میں، ہم for یا while جیسے لوپس سے کم استعمال کرتے ہیں۔ اس کے بجائے، ہم ری کرشن پر انحصار کرتے ہیں، جہاں ایک فنکشن اسی مسئلے کے چھوٹے حصوں کو حل کرنے کے لیے خود کو کال کرتا ہے۔ بائنری سوڈوکو (جسے ٹیکوزو بھی کہا جاتا ہے) کی حکمت عملی پر غور کریں، جہاں آپ کو صفر اور ون سے گرڈ بھرنا ہوتا ہے۔ منطق زیادہ سخت ہوتی ہے: جفت سائز والی گرڈز میں، ہر قطار میں 0s اور 1s کی مساوی تعداد ہونی چاہیے، اور کوئی بھی تین مسلسل خانے ایک جیسے نہیں ہو سکتے۔ بائنری سوڈوکو کے لیے سلور لکھنا Haskell یا Erlang میں تقریباً ریاضیاتی ثبوت کی طرح پڑھا جا سکتا ہے۔ بیس کیس ایک مکمل بھرا ہوا گرڈ (حل شدہ) ہوتا ہے، اور ری کرسیو قدم امکانات کو کم کرنے کے لیے منطقی اصولوں کو لاگو کرتا ہے یہاں تک کہ حالت ایک واحد درست حل میں تبدیل ہو جائے۔

پابندی کا پھیلاؤ: فلٹر اور میپ

سوڈوکو حل کرنے کی سب سے طاقتور تکنیکوں میں سے ایک "کنسٹرنٹ پروپیگیشن" ہے—اگر آپ جانتے ہیں کہ '3' قطار 1 میں نہیں ہو سکتا، تو اسے کہیں اور رکھا جائے گا۔ فنکشنل پروگرامنگ میں، یہ لسٹس پر filter اور map آپریشنز کے ساتھ براہ راست مطابقت رکھتا ہے۔

فرض کریں ہر خانے میں ایک واحد عدد نہیں، بلکہ ممکنہ امیدواروں کی ایک لسٹ ہے (مثلاً [1, 2, 3, 4, 5, 6, 7, 8, 9])۔ جب آپ بورڈ کو اسکن کرتے ہیں، تو آپ فنکشنل پائپ لائنز کا استعمال کر کے ناممکن امیدواروں کو ہٹاتے ہیں۔ جب آپ ایک ایسے خانے کو تلاش کرتے ہیں جس میں صرف ایک امیدوار باقی ہے، تو وہ عدد اپنے ہمراہیوں تک پھیلا دیا جاتا ہے۔

اس عمل کو ٹرانسفارمیشن پائپ لائن کے طور پر ماڈل کیا جا سکتا ہے:

  • میپ: ہر خالی خانے کے لیے ابتدائی امکانات پیدا کرنے کے لیے ایک فنکشن لاگو کریں۔
  • فلٹر: کٹائی میں موجود اقدار کو ہٹائیں جو تقاطع (intersecting) قطار، کالم یا خانے میں پہلے سے موجود ہیں۔
  • ریڈیوس: ان پابندیوں کو جمع کریں کہ چیک کریں کیا کسی خانے نے "سنگل ٹون" حالت تک رسائی حاصل کر لی ہے (صرف ایک امیدوار)۔

یہ طریقہ صرف معیاری سوڈوکو کے لیے لاگو نہیں ہوتا۔ یہ Calcudoku جیسی اقسام کے لیے بھی بہت موثر ہے، جہاں حسابی آپریشنز سادہ استنتاج کی جگہ لیتے ہیں۔ کیلکڈوکو میں، پابندیاں ریاضیاتی عدم مساوات ہوتی ہیں۔ ایک فنکشنل سلور کینج (cage) کے اعداد کے وہ permutations جن کی تکمیل ممکن ہو اور منفرد قطار/کالم کی پابندیوں کا احترام کریں، تولید کرنے کے لیے ہائی آرڈر فنکشنز کا استعمال کرے گی اور باطل ریاضیاتی نتائج کو فلٹر کر دے گی۔

پیٹرن میچنگ: شرائط سے زیادہ وضاحت

اگر آپ نے کبھی جاوا یا پیټھون میں سوڈوکو ویلیڈیٹر لکھا ہو، تو آپ نے بے شک if-else کے نیسٹ شدہ بیانوں پر ختم کیا ہوگا۔ فنکشنل زبانیں اکثر پیٹرن میچنگ (جیسے Haskell یا Scala میں case ایکسپریشنز) کا استعمال کرتی ہیں، جو زیادہ خواندہ منطق کی اجازت دیتی ہے۔

"کیا یہ عدد 1 ہے؟ کیا یہ 2 ہے؟" پوچھنے کے بجائے، آپ ڈیٹا کی ساخت سے میل کھاتے ہیں۔ مثال کے طور پر، جب 3x3 خانے کا تجزیہ کر رہے ہوں، تو آپ نو اشیاء کی لسٹ کے ساتھ پیٹرن میچ کر سکتے ہیں۔ اگر ایک آیات '0' (خالی جگہ کی نمائندگی کرتی ہے) اور آٹھ معلوم اعداد ہیں، تو پیٹن فوراً میل کھا جاتا ہے، پیچیدہ لوپ کاؤنٹر کے بغیر ایک "ناکڈ سنگل" امیدکار کی شناخت کرتا ہے۔

یہ تکنیک کِلر سوڈوکو سے نمٹنے میں چمکتی ہے۔ کیلر سوڈوکو میں، آپ "کینجز" (cages) سے نمٹتے ہیں—خانوں کے گروہ جن کا مجموعہ منفرد اعداد کا استعمال کرتے ہوئے ایک مخصوص ہدف قدر پر ہونا چاہیے۔ ایک فنکشنل نقطہ نظر کینج ساختوں پر پیٹرن میچنگ کا استعمال انہیں گرڈ کے باقی حصے سے الگ کرنے اور صرف ان مخصوص ٹیوپلز (tuples) پر جمع کرنے کی منطق لاگو کرنے کے لیے کرتا ہے۔

فنکشنل کمپوزیشن کے ساتھ آسان پہیلیوں کا حل

FP کی خوبصورتی کمپوزیشن میں ہے، چھوٹے، خالص فنکشنز کو جوڑ کر پیچیدہ رویہ تعمیر کرنا۔ آسان سوڈوکو پہیلی کو حل کرنے کو کمپوز شدہ فنکشنز کے تسلسل کے طور پر دیکھا جا سکتا ہے:

  1. findEmptyCell(board): پہلی صفر کے مقامات واپس کرتا ہے۔
  2. getValidCandidates(board, x, y): اجازت شدہ اعداد کی ایک لسٹ واپس کرتا ہے۔
  3. applyMove(board, x, y, number): منتقلی لاگو کر کے نیا بورڈ واپس کرتا ہے۔

ایک آسان پہیلی کے لیے، ان فنکشنز کو "اندازہ" لگانے کی ضرورت نہیں ہوتی۔ ایک فنکشنل لوپ (ری کرشن کے ذریعے نافذ) صرف findEmptyCell چلاتا ہے، امیدواروں کو فلٹر کرتا ہے اور پہلا درست عدد منتخب کرتا ہے۔ چونکہ ایسی کوئی شاخیں نہیں ہیں جہاں آپ کو اندازہ لگانا پڑے اور ممکنہ طور پر واپس جانا پڑے، کوڈ لکیری اور سادہ رہتا ہے۔

مونڈ: غیر یقینی صورتحال کا انتظام

جیسے جیسے پہیلیاں مشکل ہوتی ہیں، سادہ فلٹرنگ کافی نہیں ہوتی۔ ہمیں ایک عدد کی کوشش کرنی چاہیے، دیکھنا چاہیے کہ کیا یہ حل کی طرف لے جاتا ہے، اور اگر نہیں، تو کوشش کرنی چاہیے۔ یہ "غیر تعیناتی" (nondeterminism) متعارف کراتا ہے۔ فنکشنل پروگرامنگ میں، اسے اکثر مونڈز (Monads) کے ذریعے ہینڈل کیا جاتا ہے (خاص طور پر Haskell میں لسٹ مونڈ یا دیگر زبانوں میں مماثل ساختیں)۔

ایک مونڈ آپ کو ایسے آپریشنز کو تسلسل دیتا ہے جو ناکام ہو سکتے ہیں یا متعدد نتائج رکھتے ہیں بغیر واضح غلطی ہینڈلنگ کے۔ جب آپ solve(board) کال کرتے ہیں، تو فنکشن صرف ایک بورڈ واپس نہیں کرتا؛ یہ ممکنہ بورڈز کا ایک "کنٹینر" واپس کرتا ہے۔ اگر اندرونی منطق تضاد تلاش کرتی ہے، تو حساب کتاب کی وہ شاخ ختم ہو جاتی ہے، جبکہ درست شاخیں تلاش جاری رکھتی ہیں۔

یہ ان پیچیدہ اقسام کے لیے خاص طور پر متعلقہ ہے جہاں منطقی استنتاج دیوار سے ٹکرا جاتا ہے اور دستی حل "اندازہ" لگانے کا مشورہ دیتا ہے۔ FP میں، اسے "دھوکہ دہی" نہیں بلکہ اسٹیٹ اسپیس ٹری (state space tree) کی تلاش سمجھا جاتا ہے۔ فنکشنز کی خالصت یہ یقینی بناتی ہے کہ اگرچہ ہم ہزاروں امکانات کی طرف بڑھ رہے ہیں، کسی بھی واحد راستے کی درستی کو منطقی طور پر تصدیق کیا جا سکتا ہے۔

کر کے سیکھنا: سوڈوکو کوڈ کیوں لکھیں؟

سوڈوکو سلور لکھنا صرف ایک کوڈنگ چیلنج سے زیادہ ہے؛ یہ بیک ٹریکنگ الگوتھمز اور ڈیپتھ فائرس سرچ جیسے کمپیوٹر سائنس کے بنیادی تصورات کو سمجھنے کا دروازہ ہے۔ ان اعداد کے پیچھے کی منطق میں دلچسپی رکھنے والوں کے لیے، پہیلیوں کے ساتھ مشق ان انتہائی تجریدی تصورات کو مضبوط بنانے میں مدد کرتی ہے۔

اگر آپ پہیلی حل کرنے اور کوڈ کے درمیان خلا کو پلنے کی کوشش کر رہے ہیں، تو سادہ گرڈز سے شروع کرنا سفارش کیا جاتا ہے۔ جب آپ سمجھ جاتے ہیں کہ معیاری سوڈوکو میں پابندیاں کیسے کام کرتی ہیں، تو زیادہ پیچیدہ منطق پر مبنی کھیلوں میں فنکشنل پیٹرنز کا اطلاق فطری ہو جاتا ہے۔ شروع کرنے والوں کے لیے موزوں گرڈز سے مشکل منطقی چیلنجز کی طرف منتقلی فنکشنل پروگرامنگ کے سیکھنے کے عمل سے ملتی جلتی ہے۔

نتیجہ

سوڈوکو اور فنکشنل پروگرامنگ کے درمیان تعلق باہمی فائدے والا (symbiotic) ہے۔ سوڈوکو ایک واضح، محدود پابندی کی جگہ فراہم کرتا ہے جو FP کی طاقت دکھانے کے لیے مثالی ہے، جبکہ FP پہیلی کو حل کرنے کے لیے صاف، بغیر بگز والے الگوتھمز پیش کرتا ہے۔

گرڈ کو غیر متغیر ڈیٹا اور حل کرنے کے عمل کو فلٹرز اور ری کرسیو قدموں کی پائپ لائن کے طور پر دیکھنے سے، ہم کھیل اور اس زبان دونوں کی گہری قدر حاصل کرتے ہیں جس کا استعمال اس پر قابو پانے کے لیے کیا جاتا ہے۔ چاہے آپ اپنا پہلا فنکشنل کوڈ ڈیبگ کر رہے ہوں یا صرف ایک اخباری پہیلی کے ساتھ کافی کا کپ لطف اندوز ہو رہے ہوں، یاد رکھیں: ہر بار جب آپ کسی عدد کا استنتاج کرتے ہیں، آپ خالص منطق چلا رہے ہوتے ہیں۔

Play Qoki on mobile

Prefer to play offline? Get the app.