مقدمة في علوم الحاسوب والبرمجة باستخدام Python › مجموعات المسائل 29 / 30 السابق التالي

مجموعة المسائل 5 — استخدام المكتبات

مجموعة المسائل 5: استخدام المكتبات (Using Libraries)

زميل مجموعة المسائل (Pset Buddy): لم يُعيَّن لك زميل لهذه المجموعة في النسخة المنشورة.

المقدمة

تعرّفك مجموعة المسائل هذه على موضوع استخدام المكتبات (Using Libraries)، أي استخدام مكتبات موجودة مسبقًا من أجل إنجاز هدف ما. وتتطلب هذه المجموعة كتابة قدر ضئيل جدًا من الكود؛ فالعملية التعليمية هنا هي إيجاد دوال مفيدة تنفّذ العمل نيابةً عنك داخل المكتبات الموجودة. ومن المتوقَّع أن تستخدم البحث على الويب للعثور على الدوال اللازمة.

الأهداف

  • تعلّم كيفية استخدام المكتبات الموجودة سلفًا للوصول إلى هدف.
  • تعلّم كيفية قراءة توثيق (Documentation) دوال مكتبة ما واستخدامها.

التعاون

  • يمكنك العمل مع طلاب آخرين. لكن يجب أن يكتب كل طالب تكليفه ويسلّمه على حدة. تأكّد من الإشارة في تعليقات تسليمك إلى من عملت معهم.

ملاحظة عن الدرجة

سيكون لهذا التكليف وزن أكبر للتصحيح اليدوي لأن أداة التصحيح الآلي ليست شاملة. 50% من الدرجة ستأتي من أداة التصحيح الآلي، و50% من التصحيح اليدوي على الصور المُنتَجة.

تساعدك أداة الاختبار test_ps5_student.py على التحقق مما إذا كنت تُظهر الصور المخفية بشكل صحيح.

البدء (Getting Started)

حمّل ملف 1_ps5.zip وفكّ ضغط كل ملفاته في المجلد نفسه. الملفات المُضمَّنة هي: ps5.py، وtest_ps5_student.py، والصور المُستخدَمة في المجموعة. وعندما تنتهي، تأكّد من تشغيل ملف الاختبار للتحقق من كودك مقابل بعض حالات الاختبار لدينا.

ملاحظة

ملاحظة المترجم: لم يُنشر ملف الاختبار test_ps5_student.py ولا الحزمة الأصلية في static/؛ فهما متاحان من صفحة الكود الرسمية على OCW. المواعيد المذكورة أدناه هي مواعيد المقرر الأصلي في خريف 2022 وليست مواعيد جديدة لهذه الترجمة.

A) مرشّحات عمى الألوان (Colorblindness Filters)

يحتوي عين الإنسان على نوعين من الخلايا المُستقبِلة للضوء (Photoreceptive Cells): العصيات (Rods) والمخاريط (Cones). العصيات مسؤولة عن الرؤية في البيئات ذات الإضاءة المنخفضة مثل الليل، بينما المخاريط مسؤولة عن رؤية الألوان. وهناك ثلاثة أنواع من المخاريط، كل نوع منها مسؤول عن لون بعينه: الأحمر والأخضر والأزرق. وتعمل المخاريط الثلاثة معًا فتتيح لك رؤية كامل الطيف اللوني. فمثلًا، عندما تُنشَّط مخاريط الأحمر والأزرق بطريقة معيّنة، ترى اللون البنفسجي.

وتظهر الحالة المعروفة بـعمى الألوان (Colorblindness) عادةً على شكل نقص في أحد أنواع المخاريط هذه؛ فمثلًا، العمى الأحمر (Protanopia) هو نقص في الحساسية للضوء الأحمر، وإليك مثالًا على الفرق في رؤية صورة ما:

ملاحظة المترجم: الصورة المقارنة في هذه الشريحة لم تُنشر هنا لأن حقوقها تعود إلى طرف ثالث خارج نطاق ترخيص CC الذي تطبّقه MIT على هذه النشرة (انظر «استثناءات الأطراف الثالثة» أدناه). لم يُخمَّن أي وصف بديل لها.

الهدف من هذا الجزء هو إنشاء مرشّحات تحاكي هذه الفروق. وسنستخدم لذلك مكتبة صور بايثون (Python's Image Library أو PIL). ومن PIL سنستورد Image، وهي مكتبة فرعية (Sublibrary)، أي مجموعة من الدوال والطرق (Methods) المتعلقة بمعالجة الصور. ومع Image يمكننا تحويل الصور إلى قائمة من البكسلات (Pixels)، ثم التعامل مع قيم RGB (الأحمر والأخضر والأزرق) لتلك البكسلات.

ويمكننا محاكاة آثار عمى الألوان عبر ضرب مصفوفة تحويل عمى الألوان (Colorblindness Transformation Matrix) في قيم RGB لإحدى البكسلات، وهي ممثَّلة كمتجه (Vector) من ثلاثة مدخلات.

لا تحتاج إلى معرفة أي شيء عن ضرب المصفوفات (Matrix Multiplication)؛ لكن إن أردت المزيد من المعلومات عنه فراجع Material here.

وهنا هو التفصيل العام لعملية تحويل الصورة:

  1. افتح الصورة في بايثون.
  2. استرجع قائمة (من الصفوف أو الأعداد الصحيحة) بمعلومات البكسلات.
  3. مرّ على البكسلات واضربها في مصفوفة التحويل باستخدام matrix_multiply.
  4. احفظ البكسلات المحوَّلة في صورة.

1.1) تنفيذ الدوال المساعدة (Implementing Helper Functions)

1.1.1) img_to_pix(filename)

الدالة المساعدة الأولى هي تحويل الصورة إلى قائمة بكسلات. المُدخل هو نص يمثّل ملف صورة، مثل 'example.jpg'، والمُخرج هو قائمة تمثّل البكسلات في تلك الصورة، مثل [(0,0,0),(255,255,255),(38,29,58)...] لصور RGB، أو [60, 66, 72...] لصور بالأبيض والأسود. وستتكوّن القائمة من صفوف (Tuples) من ثلاثة عناصر تمثّل قيم RGB لتلك البكسلات في صورة RGB، أو من عدد صحيح يمثّل سطوع تلك البكسل في صورة بالأبيض والأسود.

سترغب في فتح الصورة والحصول على بيانات تلك الصورة. (راجع توثيق وحدة Image لمعرفة كيفية هذين الأمرين.) لاحظ: لا تقلق بشأن تحديد ما إذا كانت الصورة RGB أم بالأبيض والأسود. فدوال مكتبة PIL التي ستستخدمها تُعيد قيم البكسلات الصحيحة لأي من نمطي الصورة.

يجب أن يكون هذا قصيرًا جدًا إن وجدت الدوال المناسبة.

1.1.2) pix_to_img(pixels_list, size, mode)

الدالة المساعدة التالية هي تحويل قائمة البكسلات إلى صورة. المُدخل سيكون pixels_list، بنفس تنسيق مُخرج الدالة السابقة، إضافةً إلى معامل size وهو صف من عنصرين يصف أبعاد الصورة المُخرَجة، ومعامل mode الذي يحدّد ما إذا كانت البكسلات المُدخَلة تمثّل صورة بالأبيض والأسود أم صورة ملوّنة. افترض أن size مُدخل صالح بحيث size[0] * size[1] == len(pixels).

بعبارة أخرى، أنت تريد نسخ قيم البكسلات من كائن تسلسلي (Sequence Object) إلى الصورة، لذا عليك مراجعة توثيق وحدة Image لمعرفة كيفية فعل ذلك. وراجع الـdocstring (سلسلة التوثيق) للتفاصيل حول كيفية تمثيل mode.

يجب أن يكون هذا قصيرًا جدًا إن وجدت الدوال المناسبة.

1.1.3) filter(pixels_list, color)

تأخذ هذه الدالة قائمة بكسلات بصيغة RGB، مثل [(0,0,0),(255,255,255),(38,29,58)...]، إضافةً إلى لون: 'red' أو 'blue' أو 'green' أو 'none'. والغرض من هذه الدالة هو تطبيق تحويل على البكسلات في قائمة المُدخل بحيث يحاكي نقصًا في مخاريط لون المُدخل.

أعِد قائمة البكسلات المحوَّلة.

ولإجراء التحويل، اضرب كل بكسل في المصفوفة المناسبة. وقد وفّرنا لك الدالة make_matrix التي تُعطي مصفوفة تمثّل التحويل المناسب حسب نص المُدخل. فمثلًا، تُعيد make_matrix('red') المصفوفة التي تمثّل نقصًا في رؤية الأحمر.

تذكّر أنه يجب أن تمرّ على قائمة البكسلات وتضرب كل واحدة منها في المصفوفة المناسبة. واستخدم الدالة matrix_multiply(matrix1, matrix2) المقدَّمة لذلك. ولاحظ أن مصفوفة التحويل يجب أن تكون المُدخل الأول ومتجه البكسل RGB هو المُدخل الثاني، وإلا فستكون الصورة الناتجة غير صحيحة. ولاحظ أيضًا أن matrix_multiply تُعيد قائمة من الأعداد العشرية (Floats) وأن البكسلات يجب أن تكون صفوفًا من الأعداد الصحيحة (Ints).

يجب أن يكون هذا قصيرًا إلى حد ما إن وجدت الدوال المناسبة.

إذا كان كل شيء على ما يرام، فإن تشغيل البرنامج مع الصورة التجريبية ('image_15.png') ومع نقص في رؤية الأحمر ينبغي أن ينتج ما يلي:

ملاحظة المترجم: لم تُنشر هنا صورتا «الأصلية» و«بعد التحويل» لأن MIT تستثني من ترخيص CC الصور التي حقوقها تعود إلى أطراف ثالثة. ولأن النص لا يقدّم عنهما بديلًا، لم يُخمَّن أي وصف لهما.

تُعرف الصور من هذا النوع باختبارات إشيهارا (Ishihara Tests).

للحصول على الدرجة، سلّم الصورة المحوَّلة في نهاية المجموعة.

B) رسائل مخفية في الصور (Hidden Messages in Images)

في الصورة من الممكن إخفاء صورة ثانية (سرّية) لا يمكن استرجاعها إلا بعمليات رياضية معيّنة. وتُعرف هذه بـالاختباء الشفاف (Steganography). وفي هذا القسم ستمرّ على بعض الأمثلة وتكتب وحدة اختباء شفاف خاصة بك لإخفاء الصور.

ملاحظة المترجم — مادة مستثناة: يذكر ملف النشرة الأصلي بوضوح أن الصور المستخدمة في هذا القسم حقوقها © Cyp على ويكيبيديا الإنجليزية، وأنها مرخّصة بـ CC-BY-SA وأن MIT تستثنيها من ترخيصها الخاص. لذلك لم تُنشر صورتا «الأصلية» و«الصورة السرّية» هنا، ولم يُخمَّن أي وصف بديل. النص الشرحي التالي هو كامل الترجمة لما ورد في النشرة.

أُعطي مثال على الاختباء الشفاف في الأعلى. الصورة على اليسار تحتوي الصورة على اليمين. وعندما تنتهي من مجموعة المسائل هذه، ستفهم كيفية استخراج الصورة السرّية من الصورة الأصلية.

في الصورة بالأبيض والأسود، تمثَّل كل بكسل بقيمة عددية تدلّ على سطوعه. القيمة الدنيا لكل بكسل هي 0 (والتي تمثّل الأسود)، بينما القيمة العليا (والتي تمثّل الأبيض) تعتمد على عدد البتات (Bits) المستخدمة لكل بكسل. وفي أمثلتنا سنستخدم صورًا بعمق 8 بت (8-bit Images). أي أن البكسلات يمكن أن تأخذ قيمًا بين 0 و255 شاملةً (هل ترى لماذا؟).

افترض في هذا الجزء أنك تتعامل مع صور بعمق ألوان 8 بت.

2.1) العمل مع الأعداد الثنائية (Working with Binary Numbers)

يعتمد هذا الجزء من المجموعة على قراءة الأعداد الثنائية (Binary Numbers) والتعامل معها.

ولنأخذ مثالًا التمثيل الثنائي للعدد العشري 13، وهو 1101. بدءًا من الرقم في أقصى اليمين، ثمّ التحرك يسارًا،، يمثّل كل موضع فهرس قوة متزايدة للعدد 2:

1 1 0 1
232^3 222^2 212^1 202^0

وحين نجمع هذه القوى للعدد 2 (أي 23+22+202^3 + 2^2 + 2^0) نحصل على 13.

لمزيد من الأمثلة والشروح عن الأعداد الثنائية، راجع شرائح المحاضرة 3.

2.1.1) البتات الأقل أهمية (Least Significant Bits)

التقنية الأكثر شيوعًا لتضمين صور سرّية هي استخدام البت الأقل أهمية (Least Significant Bit أو LSB) من كل قيمة بكسل. يمكننا تعديل الـLSB في كل بكسل من دون إحداث أي فرق ملحوظ. وبهذه الطريقة يمكن أن تحمل صورة صورةً سرّية أخرى غير مرئية تمامًا للعين المجرّدة.

ما هو البت الأقل أهمية؟

مثال: ما هو الـLSB للعدد 13؟ أوّلًا نحوّل التمثيل العشري إلى ثنائي كما سبق: 13 -> 1101. والـLSB هو الرقم في أقصى اليمين، وهو هنا 1. أمّا الـ3 LSBs (أقل ثلاثة بتات أهمية) فهي آخر ثلاثة أرقام، وهي هنا 101، وهو ما يساوي 5 في الأساس 10.

ملاحظة المترجم: يرد في النص الأصلي عدم اتساق لفظي: فيُشار إلى أن «آخر ثلاثة بتات» هي «الرقمان في أقصى اليمين»، بينما العدد المذكور 101 من ثلاثة أرقام. والمقصود هو آخر ثلاثة بتات، أي 101، ويساوي 5 في الأساس 10. وقد نُقل المعنى الصحيح مع الإشارة هنا إلى عدم الاتساق في الأصل.

2.1.2) أسئلة للتفكير (Questions to Consider)

ملاحظة

ملاحظة: هذه الأسئلة ليست جزءًا من التكليف، وإنما هي لمساعدتك على التفكير في المشكلة. إن تعثّرت فاكتب على Piazza أو تعال إلى ساعات المكتب.

  1. إذا كان عدد ما قابلًا للقسمة على 2، فما قيمة الـLSB له؟ وأيٌّ من هذه الأعداد الثنائية يقبل القسمة على 2: 1001، 10111، 10110، 111110؟
  2. كيف يمكننا الحصول على قيمة الـLSB من غير تحويل العدد من الأساس 10 إلى تمثيل ثنائي؟
  3. هل العدد الثنائي xxx00 (حيث يمكن أن يكون x صفرًا أو واحدًا) يقبل القسمة على 4؟ وإن كان كذلك، فلماذا؟
  4. ما الباقي عند قسمة هذه الأعداد الثنائية على 4: xxx01، xxx10، xxx11؟
  5. كيف يمكننا استخراج آخر بتين (آخر LSBs) من عدد في الأساس 10 من غير تحويله إلى ثنائي؟
  6. كيف يمكننا استخراج آخر n بت من عدد في الأساس 10 من غير تحويله إلى ثنائي؟

تأكّد أنك تفهم هذه الأسئلة قبل المتابعة. فهمها سيبسّط تنفيذك لدالة extract_end_bits.

2.2) تنفيذ extract_end_bits

لاستخراج أي عدد من هذه الـLSBs من قيم البكسلات، ستنفّذ دالة مساعدة اسمها extract_end_bits(num_end_bits, pixel). وستُخرج هذه الدالة آخر num_end_bits بت من pixel كعدد صحيح في الأساس 10.

المُعاملات (Parameters):

  • num_end_bits: عدد البتات التي يجب إعادتها.
  • pixel: قيمة البكسل التي ستُعاد آخر بتات لها.

ومثالًا، انطلاقًا من المثال أعلاه، يمكننا كتابة:

extract_end_bits(1, 13) # get one LSB -> return 1
extract_end_bits(2, 13) # get two LSBs -> return 1
extract_end_bits(3, 13) # get three LSBs -> return 5

تلميحات (Hints):

  • لا تحوّل الأعداد إلى ثنائي.
  • يجب أن يكون تنفيذ هذه الدالة قصيرًا جدًا.
  • عند التفكير في كيفية تنفيذ extract_end_bits، قد يكون عامل الباقي % (Modulo) مفيدًا جدًا.

يمكنك تشغيل test_ps5_student.py للتحقق من تنفيذك لدالة extract_end_bits.

2.3) استرجاع صورة ثنائية (Recovering a Binary Image)

في الصورة الثنائية (بالأسود والأبيض)، تمثَّل كل بكسل بقيمة عددية تمثّل شدّته (Intensity). القيمة الدنيا لكل بكسل هي 0 (والتي تمثّل الأسود)، بينما القيمة العليا (والتي تمثّل الأبيض) تعتمد على عدد البتات المستخدمة لكل بكسل. وفي أمثلتنا سنستخدم صورًا بعمق 8 بت. أي أن البكسلات يمكن أن تأخذ قيمًا بين 0 و255 شاملةً (هل ترى لماذا؟).

في ملف ps5.py، أكمل الجزء الخاص بالأبيض والأسود من الدالة reveal_image بتنفيذ reveal_bw_image وفقًا للـdocstring. تأخذ هذه الدالة اسم ملف صورة، وتستخدم قيمة الـLSB لإيجاد الصورة المخفية، وتُعيدها ككائن PIL.Image.

ملاحظة

ملاحظة: يجب أن تكون reveal_image قادرة على التعامل مع صور BW وRGB معًا؛ وستنفّذ الجزء الخاص بـRGB في القسم 2.4.

مهم: الصورة المخفية مضمَّنة في البت الأقل أهمية ويمكن استرجاعها باستخدام extract_end_bits مع المُعامل num_bits المناسب على كل قيمة بكسل. لكن استخدام النتيجة الخام من هذه العملية سينتج صورة ذات تباين (Contrast) منخفض جدًا. فبعد استرجاع المعلومات، عليك إجراء عملية أخرى لإعادة معايرة قيم البكسلات (Rescale) بحيث تستفيد من كامل نطاق القيم المتاحة.

في مجلد مجموعة المسائل ستجد صورة اسمها hidden1.bmp. باستخدام دالتك، اعثر على الصورة السرّية في هذا الملف واحفظ نسخة منها مستعينًا بوظائف مكتبة PIL. لاحظ: صورة تدرّج الرمادي (Grayscale) يجب أن تكون الصورة السرّية فيها تدرّج رماديًا أيضًا. وتذكّر اسم الملف الذي اخترته لأنك ستحتاج اسم الملف بعد قليل.

2.3.1) أسئلة للتفكير

ملاحظة

ملاحظة: هذه الأسئلة ليست جزءًا من التكليف، وإنما هي لمساعدتك على التفكير في المشكلة. إن تعثّرت فاكتب على Piazza أو تعال إلى ساعات المكتب.

  1. ما الأعداد في الأساس 10 التي يمكن تمثيلها في بت واحد؟ وفي بتّين؟
  2. ما نطاق قيم بكسل BW (أو عنصر في بكسل RGB)؟
  3. كيف يمكننا إعادة معايرة قيم الـLSB للاستفادة من نطاق البكسل؟

2.4) استرجاع صورة ملوّنة (Recovering a Color Image)

الأساليب الموصوفة أعلاه متينة بما يكفي لتطبيقها على بتات أكثر. وفي هذا القسم ستعمل مع صورة RGB وتستخدم ثلاثة أقل بتات أهمية لاسترجاع الصورة السرّية.

في ملف ps5.py، أكمل المكوّن المناسب من الدالة reveal_image بتنفيذ reveal_color_image وفقًا للـdocstring الخاص بها. بالنسبة للصورة الملوّنة، تأخذ هذه الدالة اسم الملف، وتستخرج الصورة السرّية من أقل ثلاث بتات في كل قناة (الأحمر والأخضر والأزرق)، وتُعيدها ككائن PIL.Image. وستحتاج مجددًا إلى إعادة معايرة البكسلات.

في مجلد مجموعة المسائل ستجد صورة اسمها hidden2.bmp. باستخدام دالتك، اعثر على الصورة السرّية في هذا الملف واحفظ نسخة منها مستعينًا بوظائف مكتبة PIL. وتذكّر اسم الملف الذي اخترته لأنك ستحتاج اسم الملف بعد قليل.

2.5) اجعل فنّك خاصًا بك (Making Your Art Your Own)

في هذه المرحلة يجب أن تكون قد حصلت على ثلاث صور جديدة:

  1. الصورة بعد الترشيح: image_15.png
  2. الصورة بعد كشفها: hidden1.bmp
  3. الصورة بعد كشفها: hidden2.bmp

باستخدام الدالة المساعدة المقدَّمة draw_kerb، مرّر كل صورك من هذه الدالة لتضيف علامة «كيربيروس» (Kerberos Watermark) الخاصة بك على كل واحدة منها.

ولتساعدك على البدء: إن كانت لديك صورة اسمها img1.png وكان اسم «كيربيروس» الخاص بك هو timthebeaver، فيمكنك استدعاء:

draw_kerb("img1.png", "timthebeaver)"

والذي سيُنتج صورة في مجلدك اسمها img1_kerb.png.

ملاحظة المترجم: أعلاه مقتبس حرفيًا من النشرة الأصلية بما فيه قوس إغلاق ناقص في السلسلة النصية. نُقل كما هو من غير تصحيح لأن النص جزء من النص النمطي للتمرين.

وحالما تصبح لديك الصور الثلاث وعليها علامة كيربيروس، اجمعها في ملف PDF واحد للتسليم. يمكنك استخدام أداة مثل أداة دمج ملفات PDF لإنجاز ذلك. وينبغي أن تتمكّن من رفع الثلاث صور بصيغها الأصلية لتُخرج لك ملف PDF واحدًا تسلّمه.

تحذير

مهم: قبل رفع كودك إلى الموقع، علّق (Comment out) استدعاءات دالة draw_kerb حتى لا تعطّل أداة التصحيح الآلي!

3) إجراءات التسليم (Hand-in Procedure)

3.1) معلومات الوقت والتعاون

في بداية كل ملف، اكتب في تعليق أسماء من تعاونت معهم. مثال:

# Problem Set 5
# Name: Jane Lee
# Collaborators: John Doe

يُرجى تقدير عدد الساعات التي قضيتها في مجموعة المسائل في مربّع الإجابة أدناه.

3.2) التسليم في منتصف الطريق (Half-way Submission)

ينبغي لجميع الطلاب تسليم تقدّمهم بحلول موعد التسليم في منتصف الطريق (أسبوع واحد قبل الموعد النهائي).

هذا التسليم يستحق نقطة واحدة من درجة المجموعة، ولن يُصحَّح من حيث الصحة. والغرض منه التأكّد من أنك تتقدّم في المجموعة بانتظام بدلًا من العمل عليها في الأيام الأخيرة قبل الموعد.

يمكنك رفع نسخ جديدة من كل ملف حتى 30 نوفمبر الساعة 09:00 مساءً. ولا يمكنك استخدام تمديدات أو أيام تأخّر في هذا التسليم.

يُرجى تحديث الصفحة قبل رفع ملف جديد. إذا لم تفعل فلن يتم تحديث آخر تسليم لك.

3.3) التسليم النهائي (Submission)

تأكّد من تشغيل أداة الاختبار الخاصة بالطالب وأن جميع الاختبارات تنجح.

سلّم شيفرة بايثون و ملف صور الـPDF أدناه.

تأكّد من رفع ملف .py وملف .pdf في مربّعي التسليم.

يمكنك رفع نسخ جديدة حتى 7 ديسمبر الساعة 09:00 مساءً، لكن أي شيء يُرفع بعد ذلك الوقت سيُحسب ضمن أيام التأخّر، إن كانت لديك أيّ أيام تأخّر متبقية. وإذا لم تكن لديك أي أيام تأخّر متبقية، فلن تحصل على أي درجة لتسليم متأخّر.

3.3.1) تسليم شيفرة بايثون (Python Submission)

اختر ملفًا: Select File — لم يُحدَّد أي ملف — Submit — «تبقّى لك عدد لا نهائي من مرات التسليم».

3.3.2) تسليم ملف صور الـPDF (Images PDF Submission)

اختر ملفًا: Select File — لم يُحدَّد أي ملف — Submit — «تبقّى لك عدد لا نهائي من مرات التسليم».

المصدر والنَّسب والترخيص

المصدر: تعليمات PS 5 الرسمية، extracted/mit6_100l_f22_ps5.txt. ترجمة عربية لجميع التعليمات مع إبقاء الكود والمخرجات النموذجية دون ترجمة حتى تبقى نافعة للاختبار. المواعيد تاريخية.

استثناءات الأطراف الثالثة: صور الاختباء الشفاف في القسم 2 (© Cyp على ويكيبيديا الإنجليزية، CC-BY-SA) مستثناة صراحةً من ترخيص MIT ولم تُنشر هنا؛ وكذلك لم تُنشر صور المقارنة في القسم 1.1.3. ولم يُخمَّن أي محتوى بديل. كما لم يُنشر ملف الاختبار test_ps5_student.py ولا الحزمة الأصلية في static/.

النَّسب: Ana Bell. 6.100L Introduction to CS and Programming using Python, Fall 2022. Massachusetts Institute of Technology: MIT OpenCourseWare. المقرر الأصلي. المواد المملوكة لـ MIT وهذه الترجمة بموجب CC BY-NC-SA 4.0: النَّسب، غير تجاري، المشاركة بالمثل. ترجمة غير رسمية لا تعني اعتماد MIT. شروط الاستخدام.