حل المشكلات: من سؤال غامض إلى خطوات
درس 3 من 4
3حل المشكلات: من سؤال غامض إلى خطوات
الصورة الكبيرةالمبرمج الجيد ليس من يكتب أسرع، بل من يفهم المسألة قبل أن يبدأ. أغلب الوقت الضائع سببه حل سؤال غير السؤال المطروح.
ماذا تشاهد في الرسم: خمس محطات قبل أن تعتبر المسألة محلولة. لاحظ أن كتابة الكود تأتي في الأخيرة.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
مثل تخطيط رحلة: تعرف الوجهة أولًا (افهم)، ثم تقسّمها لمحطات (قسّم)، ثم تتخيّل يومًا كاملًا (مثال)، ثم تسأل «ماذا لو تأخّرت الرحلة؟» (حالة حدّية). بعدها فقط تحجز.
هذه طريقة جورج بوليا «How to Solve It» بلغة البرمجة: تحديد المدخلات والمخرجات والقيود، التفكيك لدوال صغيرة، اشتقاق الخوارزمية من أمثلة محلولة يدويًا، تعداد الحالات الحدّية (فارغ، عنصر واحد، قيم سالبة، أكبر حجم)، ثم التحقّق بجدول تتبّع ثم باختبارات.
قبل أن تبدأ
📦البيانات ببساطة
تعرف القائمة والقاموس.
🧩الحركات الثلاث
تسلسل وقرار وتكرار.
الفكرة الجوهرية
1افهم: المدخلات والمخرجات والقيود
أعد صياغة السؤال بكلماتك. ما الذي يدخل؟ ما الذي يجب أن يخرج؟ ما الممنوع؟ مثال: «أعطني أكبر رقم في قائمة». المدخل قائمة أرقام، المخرج رقم واحد، والسؤال المخفي: ماذا لو كانت القائمة فارغة؟
2قسّم: مشكلة كبيرة = مشاكل صغيرة
«احسب متوسط درجات كل طالب وأظهر الأفضل» = (1) لكل طالب اجمع درجاته، (2) اقسم على عددها، (3) قارن المتوسطات. كل جزء صغير تحلّه وحده وتختبره وحده.
3الأمثلة والحالات الحدّية
حلّ مثالين عاديين بيدك، ثم اسأل عن الأطراف: قائمة فارغة، عنصر واحد، كلها متساوية، أرقام سالبة، حجم ضخم. الحالة الحدّية هي المكان الذي تختبئ فيه أغلب الأخطاء.
def largest(numbers):
if not numbers: # edge case: empty
return None
best = numbers[0] # not 0: the list may be all negative
for n in numbers:
if n > best:
best = n
return best
print(largest([3, 9, 2]))
print(largest([-5, -2, -9]))
print(largest([]))best = 0. يعمل مع الأرقام الموجبة ويفشل بصمت مع قائمة كلها سالبة لأنه يعيد 0 وهو غير موجود فيها.4جدول التتبّع: نفّذ الكود بعقلك
اكتب عمودًا لكل متغير وسطرًا لكل دورة. تنفّذ الخوارزمية يدويًا وتسجّل القيم. حين يختلف ما في الجدول عمّا توقّعت، وجدت الخطأ.
numbers = [3, 9, 2] turn | n | best -----+---+----- start | 3 1 | 3 | 3 2 | 9 | 9 3 | 2 | 9 -> returns 9
مثال محلول
المسألة: هل الكلمة متناظرة (تُقرأ من الجهتين نفسها مثل «level»)؟ افهم: نص يدخل، نعم/لا تخرج. أمثلة: level ← نعم، hello ← لا. حدّية: كلمة فارغة، حرف واحد، حروف كبيرة وصغيرة (Level). الخوارزمية: قارن أول حرف بآخر حرف، ثم تقدّم من الطرفين.
def is_palindrome(word):
word = word.lower()
left, right = 0, len(word) - 1
while left < right:
if word[left] != word[right]:
return False
left += 1
right -= 1
return True
for w in ["level", "hello", "Level", "", "a"]:
print(repr(w), is_palindrome(w))خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| المبرمج الشاطر يكتب الحل مباشرة. | المحترفون يقضون وقتًا أطول في الفهم والأمثلة، فيكتبون كودًا أقل ويصلحون أقل. |
| إذا اشتغل على مثال واحد فهو صحيح. | مثال واحد يثبت أنه يعمل مرة. الحالات الحدّية تثبت أنه لا ينكسر. |
اختبر فهمك
دالة ترجع متوسط قائمة. أي حالة حدّية أهم؟
القسمة على عدد العناصر تصير قسمة على صفر. يجب أن تقرّر ماذا ترجع.
ما فائدة جدول التتبّع؟
تسجّل قيمة كل متغير بعد كل خطوة، فترى أين انحرف السلوك عن توقّعك.
ما أول خطوة أمام مسألة جديدة؟
ما لم تعرف ما يدخل وما يجب أن يخرج، كل كود تكتبه تخمين.
بطاقات مراجعة سريعة
تحقق من فهمك
لماذا نحلّ أمثلة يدويًا قبل الكود؟
لأن الخطوات التي تقوم بها بيدك هي الخوارزمية نفسها. تكتبها بعدها بدل أن تخترعها أمام المحرّر.
اذكر ثلاث حالات حدّية لدالة تعكس نصًّا.
نص فارغ، حرف واحد، نص فيه مسافات أو رموز أو حروف عربية.
لماذا best = numbers[0] أفضل من best = 0؟
لأن البداية من عنصر حقيقي في القائمة تعمل مع أي أرقام، بينما 0 قد يكون أكبر من كل العناصر السالبة.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.