ألعاب الورق

ألعاب الورق

تمرين تعلّمي

مقدمة

في Clojure، القوائم هي مجموعات، تمامًا مثل القوائم في لغات أخرى. وعلى غرار لغات أخرى من عائلة Lisp، تستخدم Clojure الأقواس الهلالية للتعبير عن القوائم.

يمكن إنشاء قوائم Clojure بإحدى طريقتين: إما أن تنشئ دالة list قائمة، أو أن تستخدم quote على قائمة حرفية.

والقوائم حالة خاصة لأن Clojure تتعامل معها بوصفها استدعاءات. فهي تتوقع أن يبدأ الاستدعاء بـ عامل، وهو عادة دالة. أما بقية عناصر القائمة فتُعتبر قيمًا يعمل عليها العامل، أي أنها تصبح وسائط الدالة.

هذه المعاملة الخاصة التي تخصّ بها Clojure القوائم هي السبب في أننا لا نستطيع إنشاء قائمة حرفية مباشرة. فاستخدام quote أو صيغته المختصرة ' للإحاطة بقائمة يشير إلى أنه لا ينبغي تقييم تلك القائمة.

وخلافًا لبعض اللغات الحديثة، فإن قوائم Clojure غير متجانسة، أي أنها قد تحتوي داخليًا على أنواع متعددة من العناصر، مثل '(2 "a" "b" 3). وخلافًا للغات Lisp الأخرى، فإن القائمة الفارغة في Clojure تُعامَل كقيمة صحيحة منطقيًا، وهي ليست مكافئة لـ nil أو false.

التعليمات

تتطلع إليز بشدة إلى لعب البوكر (وألعاب ورق أخرى) خلال رحلتها القادمة إلى لاس فيغاس. وبما أنها من أشد المعجبين بـ"التتبع الذاتي"، فإنها تريد أن تجمع بعض الدوال الصغيرة التي ستساعدها في مهام التتبع، وقد طلبت مساعدتك في التفكير فيها.

1. تتبّع جولات البوكر

إليز مغرمة بالبوكر على وجه الخصوص، وتريد تتبع عدد الجولات التي تلعبها، و_أي الجولات_ تكون. لكل جولة رقمها الخاص، وكل طاولة تعرض رقم الجولة التي تُلعب حاليًا. تختار إليز طاولة وتجلس لتلعب جولتها الأولى، وهي تخطط للعب ثلاث جولات.

اكتب دالة rounds تأخذ رقم الجولة الحالية وتُرجع list واحدة تضم تلك الجولة و_الجولتين_ القادمتين:

(rounds 27)
;;=> (27 28 29)

2. الاحتفاظ بكل الجولات في المكان نفسه

لعبت إليز بضع جولات على الطاولة الأولى، ثم أخذت استراحة ولعبت مزيدًا من الجولات على طاولة ثانية ... لكنها انتهت بمصفوفة مختلفة لكل طاولة! تريد أن تجمع المصفوفتين معًا، حتى تتبع كل جولات البوكر في المكان نفسه.

اكتب دالة concat-rounds تأخذ مصفوفتين وتُرجع list واحدة تتكوّن من كل الجولات في list الأولى، تليها كل الجولات في list الثانية:

(concat-rounds '(27 28 29) '(35 36))
;;=> (27 28 29 35 36)

3. العثور على الجولات السابقة

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

اكتب دالة contains-round? تأخذ وسيطين: مصفوفة بالجولات الملعوبة ورقم جولة. وستُرجع الدالة true إذا كانت الجولة ضمن مصفوفة الجولات الملعوبة، وfalse إن لم تكن:

(contains-round? '(27 28 29 35 36) 29)
;;=> true

(contains-round? '(27 28 29 35 36) 30)
;;=> false

4. حساب متوسط قيم الأوراق

تريد إليز أن تجرّب لعبة جديدة تُسمى Black Joe. وهي تشبه لعبة Black Jack، حيث يكون هدفك أن يصل مجموع قيم الأوراق في يدك إلى قيمة مستهدفة، لكن الهدف في Black Joe هو أن يكون متوسط قيم الأوراق مساويًا 7. ويمكن إيجاد المتوسط بجمع كل قيم الأوراق ثم قسمة هذا المجموع على عدد الأوراق في اليد.

اكتب دالة card-average تُرجع متوسط قيمة يد في Black Joe.

(card-average '(5 6 7))
;;=> 6.0

5. متوسطات بديلة

في Black Joe، السرعة مهمة. وستحاول إليز إيجاد أسلوب أسرع لحساب المتوسط.

لقد فكّرت في أسلوبين للحصول على عدد شبيه بالمتوسط:

  • حساب متوسط أول عدد وآخر عدد في اليد.
  • استخدام الوسيط (الورقة الوسطى) في اليد.

اكتب الدالة approx-average?، بمعلومية hand، وهي مصفوفة تحتوي على قيم الأوراق في يدك.

أرجِع true إذا أدّى أحد الأسلوبين المذكورين أعلاه or كليهما إلى عدد يساوي المتوسط الفعلي.

ملاحظة: أطوال كل الأيدي فردية، لتسهيل العثور على الوسيط.

(approx-average? '(1 2 3))
;;=> true

(approx-average? '(2 3 4 8 8))
;;=> true

(approx-average? '(1 2 3 5 9))
;;=> false

6. المزيد من تقنيات حساب المتوسط

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

اكتب دالة average-even-odd? تُرجع قيمة منطقية تشير إلى ما إذا كان متوسط الأوراق عند الفهارس الزوجية مساويًا لمتوسط الأوراق عند الفهارس الفردية.

(average-even-odd? '(1 2 3))
;;=> true

(average-even-odd? '(1 2 3 4))
;;=> false

7. قواعد الجولة الإضافية

كل يد رقمها 11 في Black Joe هي يد إضافية بقاعدة إضافية: إذا كانت آخر ورقة تسحبها جاك، فاضاعف قيمتها.

اكتب دالة maybe-double-last تأخذ يدًا وتتحقق مما إذا كانت آخر ورقة جاك (11). وإذا كانت آخر ورقة هي جاك (11)، فاضاعف قيمتها قبل إرجاع اليد.

(maybe-double-last '(5 9 11))
;;=> '(5 9 22)

(maybe-double-last '(5 9 10))
;;=> '(5 9 10)
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Clojure Exercism

مستعد لبدء ألعاب الورق؟

سجّل في Exercism لتتعلّم وتتقن Clojure عبر 12 مفهومًا105 تمارين، وإرشاد بشري حقيقي، وكل ذلك مجانًا.