خوارزميات للمبتدئين: غوص عميق وودي

٢٣ سبتمبر ٢٠٢٥

Algorithms for Beginners: A Friendly Deep Dive

يمكن أن يبدو مصطلح خوارزمية مخيفًا عندما تبدأ للتو في البرمجة[1]. يبدو وكأنه أحد مصطلحات علوم الحاسوب المخصصة للمُتخصصين في الرياضيات أو المطورين ذوي الخبرة العشرات من السنين. لكن الحقيقة هي: الخوارزميات ليست سوى تعليمات خطوة بخطوة لحل المشكلات[2]. أنت تستخدم الخوارزميات بالفعل في حياتك اليومية — عند اتباع وصفة طبخ، أو ربط حذائك، أو تحديد أسرع طريق للعمل. برمجة الخوارزميات لا تتطلب سوى تعلم كيفية صياغة هذه الخطوات بشكل رسمي حتى تستطيع الحواسيب اتباعها.

في هذا الدليل المطول، سنفكك الخوارزميات بطريقة تبدو ميسرة. سنعتمد على أحد أكثر لغات البرمجة تأثيرًا على الإطلاق — Lisp — لعرض كيف تشكل الأفكار البسيطة مثل القوائم والشروط والدوال أساس التفكير الخوارزمي. Lisp أنيقة لأنها تتعامل مع الكود كبيانات والبيانات ككود[3]، مما يجعلها ملعبًا مثاليًا لاستكشاف الخوارزميات. لا داعي للقلق إذا لم تلمس Lisp من قبل. سنبدأ من الصفر، ونشرح كل مفهوم بلغة إنجليزية بسيطة، ونمر على الأمثلة خطوة بخطوة.


ما هي الخوارزمية؟

في جوهرها، الخوارزمية هي[4]:

  • سلسلة من الخطوات التي تحول المدخلات إلى مخرجات.
  • حتمية، أي أنه عند إعطاء نفس المدخلات، ستنتج دائمًا نفس المخرجات.
  • منتهية، أي أنها تكتمل في النهاية.

فكر في فرز قائمة أسماء ترتيبًا أبجديًا. سواء استخدمت فرز الفقاعات، أو فرز سريع، أو حتى قمت بخلط البطاقات يدويًا على مكتبك، فأنت تطبق خوارزمية.

يمكن التعبير عن الخوارزميات بلغة طبيعية، أو مخططات تدفق، أو رمز وهمي، أو في لغات البرمجة[5]. Lisp هي واحدة من أقدم اللغات التي بدأ فيها المطورون استكشاف الخوارزميات بعمق، وتعود العديد من مفاهيم البرمجة الحديثة إلى أصولها فيها[6].


لماذا تساعد Lisp المبتدئين على فهم الخوارزميات؟

Lisp (اختصار لـ LISt Processing) تم تطويرها من قبل جون مكارثي في معهد ماساتشوستس للتكنولوجيا عام 1958[7]، مما يجعلها واحدة من أقدم لغات البرمجة لا تزال مستخدمة اليوم. على الرغم من عمرها، إلا أنها لا تزال واحدة من أكثر الأدوات أناقة للتفكير في الخوارزميات بسبب[8]:

  • بنية موحدة: كل شيء في Lisp يبدو نفسه — تعبيرات بين قوسين[9]. هذه الوحدة تقلل من المشتتات وتجعلك تركّز على كيف تعمل الخوارزمية.
  • الكود كبيانات: تتعامل Lisp مع البرامج كقوائم، يمكن التعامل معها مثل أي بيانات أخرى[10]. هذا يفتح طرقًا قوية للتفكير في الخوارزميات.
  • تجريدات قوية: الدوال والشروط والتكرار مدمجة وسهلة التجربة[11].

لنستخدم Lisp كعدسة أثناء استكشاف أساسيات الخوارزميات.


إعداد ملعبك

قبل الغوص في الخوارزميات، تحتاج إلى بيئة يمكنك فيها تشغيل كود Lisp. بالنسبة لـ Common Lisp، فإن أحد أكثر الت implementations شيوعًا هو SBCL (Steel Bank Common Lisp)[12].

تثبيت SBCL

  • لينكس (Ubuntu/Debian):
  sudo apt install sbcl rlwrap
  rlwrap sbcl
  • macOS (Homebrew):
  brew install sbcl rlwrap
  rlwrap sbcl
  • ويندوز: قم بتنزيل المثبت من الموقع الرسمي لـ SBCL[13]، وشغّله، ثم افتح sbcl من الطرفية.

إضافة rlwrap تعطيك تجربة سطر أوامر أفضل مع عمل مفاتيح السهم كما هو متوقع[14].

بمجرد التثبيت، ستدخل إلى REPL الخاص بـ Lisp (Read‑Eval‑Print‑Loop). اكتب (+ 1 2) واضغط على Enter — مبروك، لقد قمت للتو بتشغيل أول خوارزمية لك: الجمع.


REPL والتعبيرات الرمزية

في Lisp، كل شيء تعبير[15]. هذا يعني أن كل قطعة من الكود لها قيمة، ويقوم المفسر بتقييم هذه القيم باستمرار في REPL.

  • الأرقام: 42 تُقيّم إلى 42.
  • السلاسل: "hello" تُقيّم إلى "hello".
  • الرموز: تمثل المتغيرات أو أسماء الدوال.
  • القوائم: قلب Lisp، مكتوبة كـ (<function> <arg1> <arg2> ...)[16].

على سبيل المثال:

(+ 3 5)   ; adds 3 and 5
(* 2 4)   ; multiplies 2 and 4

هذا الهيكل المنتظم يجعل Lisp أداة ممتازة لتعلم الخوارزميات. لا يوجد فرق بين المشغلين المدمجين والدوال المعرفة من قبل المستخدم — كل شيء مجرد قائمة[17].


كتل بناء الخوارزمية

عند كتابة الخوارزميات، تحتاج إلى بعض الأدوات الأساسية[18]:

1. المتغيرات

تخزن المتغيرات النتائج الوسيطة.

(let ((x 10)
      (y 20))
  (+ x y)) ; returns 30

2. الشروط

تتطلب الخوارزميات غالبًا منطق تفرعي[19].

defun sign-of (n)
  (cond ((< n 0) "negative")
        ((= n 0) "zero")
        (t "positive")))

3. التكرار

العديد من الخوارزميات الكلاسيكية تكرارية[20]. على سبيل المثال، العامل:

(defun factorial (n)
  (if (= n 0)
      1
      (* n (factorial (- n 1)))))

هذا يُظهر تفكيك المشكلة إلى مشكلات فرعية أصغر — جوهر تصميم الخوارزميات[21].


الخوارزميات الكلاسيكية للمبتدئين في Lisp

لنستعرض بعض الخوارزميات الشائعة باستخدام Lisp.

1. البحث في قائمة

البحث الخطي يفحص كل عنصر حتى يجد تطابقًا[22].

(defun linear-search (item list)
  (cond ((null list) nil)
        ((equal item (car list)) t)
        (t (linear-search item (cdr list)))))
  • car تعطي العنصر الأول[23].
  • cdr تعطي باقي القائمة[24].

2. إيجاد القيمة القصوى في قائمة

(defun max-in-list (lst)
  (if (null (cdr lst))
      (car lst)
      (let ((max-rest (max-in-list (cdr lst))))
        (if (> (car lst) max-rest)
            (car lst)
            max-rest))))

3. الترتيب: فرز الإدراج

فرز الإدراج هو خوارزمية ممتازة للمبتدئين ذات تعقيد زمني O(n²) في أسوأ الحالات[25].

(defun insert (x sorted-list)
  (if (or (null sorted-list) (<= x (car sorted-list)))
      (cons x sorted-list)
      (cons (car sorted-list) (insert x (cdr sorted-list)))))

(defun insertion-sort (lst)
  (if (null lst)
      nil
      (insert (car lst) (insertion-sort (cdr lst)))))

جرب (insertion-sort '(5 2 9 1 6)) — ستلاحظ (1 2 5 6 9).


فهم كفاءة الخوارزميات

الخوارزميات لا تتعلق فقط بالصواب؛ الكفاءة مهمة[26]. هناك بعدان رئيسيان:

  • تعقيد الوقت: المدة التي تستغرقها الخوارزمية مع نمو حجم الإدخال[27].
  • تعقيد المساحة: كمية الذاكرة التي تستخدمها[28].

على سبيل المثال:

  • البحث الخطي له تعقيد وقت O(n)[29].
  • فرز الإدراج له تعقيد وقت O(n²) في أسوأ الحالات وO(n) في أفضل الحالات[30].

حتى في Lisp، يمكنك التفكير في الأداء من خلال تحليل عدد المكالمات التكرارية أو عدد المقارنات التي تحدث[31].


التصحيح والتجربة

عند تعلم الخوارزميات، الأخطاء جزء من الرحلة[32]. واجهة Lisp التفاعلية (REPL) سخية — إذا أدخلت شيئًا غير صالح، فإنها تُظهر لك الخطأ وتسمح لك بالتعافي. هذه الحلقة السريعة للتغذية الراجعة لا تقدر بثمن للتجربة مع الخوارزميات. لا تخشَ تجربة الاختلافات، وكسرها، وإصلاحها.


وراء الأساسيات

بمجرد أن تشعر بالراحة مع الخوارزميات البسيطة، فإن نظام الماكرو في Lisp يفتح الباب أمام البرمجة الميتا[33]. يمكنك كتابة خوارزميات تُولِّد خوارزميات أخرى. بالنسبة للمبتدئين، كفاية أن تقدر هذه الإمكانية كدافع للاستمرار في الاستكشاف.

على سبيل المثال، يمكنك كتابة ماكرو ينشئ تلقائيًا وظائف بحث مُحسَّنة لهياكل بيانات مختلفة[34]. وهذا يظهر كيف أن الخوارزميات ليست وصفات ثابتة — بل يمكنها التطور والتكيف.


الاستنتاجات الرئيسية

  • الخوارزميات هي مجرد إجراءات خطوة بخطوة لحل المشكلات[35].
  • Lisp هي بيئة رائعة لاستكشاف الخوارزميات بسبب بساطتها وقدرتها التعبيرية[36].
  • ابدأ بالكتل الأساسية (المتغيرات، الشروط، التكرار) ثم انتقل إلى الخوارزميات الكلاسيكية مثل البحث والفرز[37].
  • الكفاءة مهمة: فكّر في تعقيد الوقت والمساحة[38].
  • واجهة REPL تجعل التجربة ممتعة وتفاعلية[39].

الخاتمة

إذا كانت الخوارزميات تبدو في السابق كلمة مخيفة، فأرجو أن يكون هذا الدليل قد أظهر لك أنها مجرد خطوات منظمة لحل المشكلات. Lisp تجعل من السهل رؤية الأناقة الكامنة وراء الخوارزميات، من الشروط البسيطة إلى الفرز التكراري. أفضل طريقة للتعلم هي الممارسة — افتح واجهة Lisp التفاعلية، جرب الأمثلة، عدّلها، واخترع خوارزمياتك الخاصة.

الخوارزميات هي لغة حل المشكلات في علوم الحاسوب، وعندما تعتاد عليها، ستكتسب القدرة على مواجهة تحديات أكثر تعقيدًا[40]. اعتبر هذا خطوتك الأولى في رحلة مدى الحياة لتعلم كيفية التفكير كعالم حاسوب.

إذا أعجبك هذا الدليل، ففكر في الاشتراك في نشرتي حيث أشارك المزيد من الدروس المتعمقة، وتجارب البرمجة، والشرح الواضح لمفاهيم علوم الحاسوب.

برمجة سعيدة!


المراجع

[1] Khan Academy. "What is an algorithm and why should you care?" https://www.khanacademy.org/computing/computer-science/algorithms/

[2] Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. "Introduction to Algorithms, 4th Edition." MIT Press, 2022.

[3] Wikipedia. "Lisp (programming language) - Homoiconicity." https://en.wikipedia.org/wiki/Lisp_(programming_language)

[4] Knuth, Donald. "The Art of Computer Programming, Volume 1: Fundamental Algorithms." Addison-Wesley, 1997.

[5] Sedgewick, R. & Wayne, K. "Algorithms, 4th Edition." Addison-Wesley, 2011.

[6] McCarthy, John. "Recursive functions of symbolic expressions and their computation by machine, Part I." Communications of the ACM 3(4), 1960.

[7] Computer History Museum. "John McCarthy and the birth of Lisp." https://www.computerhistory.org/

[8] Graham, Paul. "The Roots of Lisp." http://www.paulgraham.com/rootsoflisp.html

[9] Steele, Guy L. "Common Lisp the Language, 2nd Edition." Digital Press, 1990.

[10] Abelson, H. & Sussman, G. J. "Structure and Interpretation of Computer Programs." MIT Press, 1996.

[11] Touretzky, David S. "Common Lisp: A Gentle Introduction to Symbolic Computation." Benjamin/Cummings, 1990.

[12] Steel Bank Common Lisp. "SBCL Official Documentation." http://www.sbcl.org/

[13] Steel Bank Common Lisp. "Download SBCL." http://www.sbcl.org/platform-table.html

[14] GNU Readline. "rlwrap - readline wrapper." https://GitHub.com/hanslub42/rlwrap

[15] Seibel, Peter. "Practical Common Lisp." Apress, 2005.

[16] Wikipedia. "S-expression." https://en.wikipedia.org/wiki/S-expression

[17] McCarthy, John. "History of Lisp." ACM SIGPLAN Notices, 1978.

[18] Skiena, Steven S. "The Algorithm Design Manual, 3rd Edition." Springer, 2020.

[19] ديكسترا، إدسجر و. "ملاحظات حول البرمجة المبنية على الهيكل." 1970.

[20] روبرتس، إريك إس. "التفكير التكراري." جون ويلي & أبناء، 1986.

[21] ويرث، نيكلوس. "الخوارزميات + هياكل البيانات = البرامج." برينتيس هول، 1976.

[22] كنوث، دونالد. "فن برمجة الحاسوب، المجلد الثالث: الفرز والبحث." أديسون-ويسلي، 1998.

[23] ويكيبيديا. "CAR و CDR." https://en.wikipedia.org/wiki/CAR_and_CDR

[24] Common Lisp HyperSpec. "الوظائف CAR، CDR." http://www.lispworks.com/documentation/HyperSpec/

[25] GeeksforGeeks. "تعقيد الوقت لفرز الإدراج." https://www.geeksforgeeks.org/insertion-sort/

[26] دليل مراجع Big-O. "اعرف تعقيداتك!" https://www.bigocheatsheet.com/

[27] سيبسر، مايكل. "مقدمة في نظرية الحساب، الإصدار الثالث." Cengage Learning، 2012.

[28] أهو، أ. ف.، هوبكروفت، ج. إي.، & أولمان، ج. د. "هياكل البيانات والخوارزميات." أديسون-ويسلي، 1983.

[29] NIST. "قاموس الخوارزميات وهياكل البيانات - البحث الخطي." https://xlinux.nist.gov/dads/HTML/linearsearch.html

[30] مدونة مطوري NVIDIA. "شرح فرز الإدراج." https://developer.nvidia.com/blog/insertion-sort-explained/

[31] نورفيغ، بيتر. "نماذج برمجة الذكاء الاصطناعي: دراسات حالة في ليبس الشائعة." مورغان كاوفمان، 1992.

[32] بيتزولد، تشارلز. "الكود: اللغة المخفية للعتاد والبرمجيات الحاسوبية." ميكروسوفت بريس، 2000.

[33] غراهام، بول. "حول ليبس: تقنيات متقدمة للغة ليبس الشائعة." برينتيس هول، 1993.

[34] كويينيك، كريستيان. "ليبس في أجزاء صغيرة." جامعة كامبريدج للنشر، 1996.

[35] هاينمان، ج. تي., بوليس، جي., & سيلكوف، س. "الخوارزميات في ملخص، الإصدار الثاني." O'Reilly Media، 2016.

[36] فيليسيين، م., فيندلر، ر. ب., فلات، م., & كريشنامورثي، س. "كيفية تصميم البرامج، الإصدار الثاني." مطبعة MIT، 2018.

[37] بهارغا، أديتيا. "فهم الخوارزميات." منشورات مانينغ، 2016.

[38] راوجردن، تيم. "الخوارزميات المضيئة." Soundlikeyourself Publishing، 2017-2020.

[39] سيبيل، بيتر. "المبرمجون في العمل: تأملات في فن البرمجة." أبريس، 2009.

[40] بوليا، جورج. "كيفية حل المسائل: جانب جديد من الطريقة الرياضية." مطبعة جامعة برينستون، 1945.